云计算百科
云计算领域专业知识百科平台

DeepSeek生成的网页小游戏 - 单人壁球挑战赛

单人壁球挑战赛

🎯 核心目标

用球拍控制小球,击中上方目标得分,尽可能获得高分。

🕹️ 基础操作

PC端控制:

  • ← → 箭头键 或 A/D键:左右移动球拍

  • 空格键:发射球/暂停游戏

  • R键:重新开始游戏

移动端控制:

  • 左右箭头按钮:移动球拍

  • 发射按钮:发射球/暂停游戏

  • 滑动屏幕:直接移动球拍(触摸控制)

  • 点击画布:发射球

🎮 游戏机制

1. 球拍与球

  • 球初始停在球拍上(闪烁提示)

  • 按空格键或点击发射按钮将球射出

  • 球击中球拍会反弹,根据击中位置改变反弹角度

2. 目标系统

  • 屏幕上方有多行多列彩色目标

  • 不同颜色的目标有不同分数:

    • 普通目标:10分(蓝色系)

    • 金色目标:50分(金色,高分奖励)

    • 红色生命目标:10分 + 恢复1条生命

3. 得分与升级

  • 每次击中目标获得相应分数

  • 每得100分:触发花朵特效庆祝

  • 等级系统:每100分升1级,球速随等级提高

4. 生命与失败

  • 初始生命值:3条命

  • 损失生命:球掉落到底部

  • 生命恢复:击中红色生命目标

  • 最大生命值:最多5条命

  • 游戏结束:生命值为0

🌸 特效系统

1. 花朵特效

  • 每获得100分触发一次

  • 屏幕上方飘落彩色花朵

  • 花朵有不同形状和颜色

2. 得分动画

  • 每次击中目标显示"+"分数动画

  • 动画从击中位置向上飘散

⚙️ 游戏界面

1. 统计信息

  • 分数:当前得分

  • 生命值:剩余生命数

  • 等级:当前游戏等级

2. 控制区域

  • PC端:显示键盘控制提示和操作按钮

  • 移动端:显示触摸控制按钮

3. 特殊状态

  • 暂停状态:可以暂停和继续游戏

  • 游戏结束:显示最终得分和重玩按钮

🎵 音效系统

  • 背景音乐:放松的背景音乐(可开关)

  • 得分音效:击中目标时播放

  • 花朵特效音效:每100分时播放

📱 设备适配

PC端优化:

  • 键盘控制

  • 大尺寸目标

  • 完整控制面板

移动端优化:

  • 触摸控制按钮

  • 滑动控制

  • 自适应目标大小

  • 优化的画布尺寸

🏆 策略提示

  • 控制反弹角度:球击中球拍的不同位置会改变反弹角度

  • 优先击中特殊目标:金色目标(50分)和红色生命目标

  • 节奏控制:不要急于发射,等待合适时机

  • 生命管理:保持至少1条生命作为安全缓冲

  • 利用墙壁反弹:让球从侧面墙壁反弹击中难以直接击中的目标

  • 💡 游戏特色

    • 自适应难度:球速随等级提高,挑战性逐渐增加

    • 双重控制:同时支持键盘和触摸控制

    • 视觉反馈:丰富的动画和特效

    • 放松体验:柔和的背景音乐和视觉效果

    • 跨平台:在PC和移动设备上都能良好运行

    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
    <title>单人壁球挑战赛</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <style>
    * {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    -webkit-tap-highlight-color: transparent;
    -webkit-overflow-scrolling: touch;
    }

    html, body {
    font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif;
    background: #000;
    color: white;
    overflow-x: hidden;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 0;
    position: fixed;
    width: 100%;
    height: 100%;
    overscroll-behavior: none;
    }

    /* 防止iOS橡皮筋效果 */
    body {
    overflow: hidden;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    }

    /* 背景图片 */
    #background-image {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-image: url('https://amitofo.icu/lianchi.jpg');
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    opacity: 0.7;
    z-index: -2;
    }

    /* 背景遮罩 */
    #background-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(10, 20, 40, 0.85);
    z-index: -1;
    }

    /* 更多游戏角标 */
    .more-games-corner {
    position: absolute;
    top: 15px;
    left: 15px;
    z-index: 100;
    padding: 8px 15px;
    background: linear-gradient(135deg, #ff3366, #ff6633);
    border-radius: 20px;
    box-shadow: 0 4px 12px rgba(255, 51, 102, 0.4);
    transition: all 0.3s ease;
    }

    .more-games-corner:hover, .more-games-corner:active {
    transform: translateY(-2px);
    box-shadow: 0 6px 16px rgba(255, 51, 102, 0.6);
    }

    .more-games-link {
    color: white;
    text-decoration: none;
    font-size: 14px;
    font-weight: 600;
    display: flex;
    align-items: center;
    gap: 6px;
    }

    .more-games-link i {
    font-size: 16px;
    }

    /* 游戏容器 */
    .game-container {
    width: 100%;
    max-width: 900px;
    margin: 0 auto;
    padding: 20px;
    padding-top: 70px;
    display: flex;
    flex-direction: column;
    align-items: center;
    flex: 1;
    overflow: hidden;
    }

    /* 标题 */
    .header {
    text-align: center;
    margin-bottom: 25px;
    width: 100%;
    }

    h1 {
    font-size: 2.8rem;
    margin-bottom: 8px;
    text-shadow: 0 2px 10px rgba(0, 0, 0, 0.7);
    background: linear-gradient(90deg, #FFD700, #FFA500, #FF6347);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    letter-spacing: 1px;
    font-weight: 800;
    }

    .subtitle {
    font-size: 1.1rem;
    opacity: 0.9;
    color: #e0e0ff;
    max-width: 600px;
    margin: 0 auto;
    line-height: 1.5;
    }

    /* 游戏UI */
    .game-ui {
    display: flex;
    justify-content: space-between;
    width: 100%;
    margin-bottom: 20px;
    flex-wrap: wrap;
    gap: 15px;
    }

    .stats {
    display: flex;
    gap: 20px;
    flex-wrap: wrap;
    justify-content: center;
    width: 100%;
    }

    .stat-box {
    background: rgba(255, 255, 255, 0.12);
    padding: 15px 20px;
    border-radius: 12px;
    min-width: 120px;
    text-align: center;
    backdrop-filter: blur(8px);
    border: 1px solid rgba(255, 255, 255, 0.2);
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);
    }

    .stat-label {
    font-size: 0.95rem;
    opacity: 0.8;
    margin-bottom: 5px;
    color: #b0b0ff;
    }

    .stat-value {
    font-size: 2.2rem;
    font-weight: 800;
    color: #FFD700;
    text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
    }

    /* 游戏画布容器 */
    .canvas-container {
    width: 100%;
    max-width: 800px;
    overflow: hidden;
    border-radius: 12px;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.6);
    border: 2px solid rgba(255, 215, 0, 0.3);
    position: relative;
    background-color: rgba(10, 15, 35, 0.85);
    touch-action: manipulation;
    height: 500px; /* 固定高度 */
    margin: 0 auto;
    }

    /* 游戏画布 */
    #gameCanvas {
    display: block;
    width: 100%;
    height: 100%;
    }

    /* 控制区域 – PC端 */
    .pc-controls {
    display: flex;
    flex-direction: column;
    align-items: center;
    margin-top: 25px;
    width: 100%;
    max-width: 800px;
    }

    .control-info {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 25px;
    margin-bottom: 20px;
    background: rgba(0, 0, 0, 0.3);
    padding: 18px;
    border-radius: 12px;
    width: 100%;
    border: 1px solid rgba(255, 255, 255, 0.1);
    }

    .control-item {
    display: flex;
    align-items: center;
    gap: 10px;
    }

    .key {
    background: rgba(255, 255, 255, 0.15);
    padding: 8px 16px;
    border-radius: 8px;
    font-weight: 700;
    border: 1px solid rgba(255, 255, 255, 0.3);
    min-width: 50px;
    text-align: center;
    color: #FFD700;
    }

    /* 按钮 */
    .buttons {
    display: flex;
    gap: 15px;
    margin-top: 10px;
    flex-wrap: wrap;
    justify-content: center;
    }

    button {
    background: linear-gradient(to bottom, #4a6ee0, #3a5ed0);
    color: white;
    border: none;
    padding: 14px 28px;
    border-radius: 10px;
    font-size: 1.05rem;
    cursor: pointer;
    transition: all 0.2s;
    font-weight: 600;
    letter-spacing: 0.5px;
    box-shadow: 0 4px 12px rgba(58, 94, 208, 0.4);
    display: flex;
    align-items: center;
    gap: 8px;
    }

    button:hover {
    background: linear-gradient(to bottom, #5a7ef0, #4a6ee0);
    transform: translateY(-3px);
    box-shadow: 0 6px 18px rgba(58, 94, 208, 0.6);
    }

    button:active {
    transform: translateY(1px);
    }

    button#restartBtn {
    background: linear-gradient(to bottom, #FF9800, #F57C00);
    box-shadow: 0 4px 12px rgba(245, 124, 0, 0.4);
    }

    button#restartBtn:hover {
    background: linear-gradient(to bottom, #FFB74D, #FF9800);
    box-shadow: 0 6px 18px rgba(245, 124, 0, 0.6);
    }

    /* 花朵特效容器 */
    #flower-effects {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    z-index: 10;
    overflow: hidden;
    }

    .flower {
    position: absolute;
    font-size: 24px;
    opacity: 0;
    animation: fall linear forwards;
    }

    @keyframes fall {
    0% {
    transform: translateY(-50px) rotate(0deg);
    opacity: 0;
    }
    10% {
    opacity: 1;
    }
    100% {
    transform: translateY(100vh) rotate(360deg);
    opacity: 0;
    }
    }

    /* 得分动画 */
    .score-popup {
    position: absolute;
    font-size: 28px;
    font-weight: 900;
    color: #FFD700;
    text-shadow: 0 2px 10px rgba(0, 0, 0, 0.8);
    z-index: 5;
    pointer-events: none;
    animation: scorePopup 1s ease-out forwards;
    }

    @keyframes scorePopup {
    0% {
    opacity: 0;
    transform: translateY(0) scale(0.5);
    }
    50% {
    opacity: 1;
    transform: translateY(-30px) scale(1.2);
    }
    100% {
    opacity: 0;
    transform: translateY(-60px) scale(0.8);
    }
    }

    /* 游戏结束界面 */
    .game-over {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background: rgba(0, 0, 0, 0.92);
    padding: 45px;
    border-radius: 16px;
    text-align: center;
    display: none;
    z-index: 100;
    width: 90%;
    max-width: 500px;
    border: 2px solid #FFD700;
    box-shadow: 0 0 50px rgba(255, 215, 0, 0.4);
    backdrop-filter: blur(10px);
    }

    .game-over h2 {
    font-size: 2.8rem;
    color: #FFD700;
    margin-bottom: 20px;
    }

    .game-over p {
    font-size: 1.4rem;
    margin-bottom: 35px;
    color: #e0e0ff;
    }

    /* 移动端控制按钮 */
    .mobile-controls {
    display: none;
    margin-top: 25px;
    width: 100%;
    max-width: 300px;
    justify-content: center;
    gap: 20px;
    }

    .mobile-btn {
    width: 80px;
    height: 80px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.2);
    border: 2px solid rgba(255, 215, 0, 0.5);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 32px;
    color: white;
    cursor: pointer;
    user-select: none;
    box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3);
    touch-action: manipulation;
    }

    /* 音频控制 */
    .audio-control {
    position: fixed;
    bottom: 20px;
    right: 20px;
    z-index: 50;
    background: rgba(0, 0, 0, 0.7);
    border-radius: 50%;
    width: 50px;
    height: 50px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    border: 1px solid rgba(255, 255, 255, 0.3);
    box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
    }

    /* PC端专用样式 */
    @media (min-width: 769px) {
    .mobile-controls {
    display: none !important;
    }

    .pc-controls {
    display: flex !important;
    }
    }

    /* 移动端样式 */
    @media (max-width: 768px) {
    .pc-controls {
    display: none !important; /* 移动端隐藏控制区域 */
    }

    .mobile-controls {
    display: flex;
    }

    h1 {
    font-size: 2.2rem;
    }

    .subtitle {
    font-size: 1rem;
    padding: 0 10px;
    }

    .game-ui {
    flex-direction: column;
    align-items: center;
    gap: 15px;
    }

    .stats {
    width: 100%;
    justify-content: center;
    }

    .stat-box {
    min-width: 100px;
    padding: 12px 15px;
    }

    .stat-value {
    font-size: 1.8rem;
    }

    .more-games-corner {
    top: 10px;
    left: 10px;
    padding: 6px 12px;
    }

    .more-games-link {
    font-size: 13px;
    }

    /* 移动端调整画布高度 */
    .canvas-container {
    height: 400px;
    }

    /* 移动端游戏容器调整 */
    .game-container {
    padding: 15px;
    padding-top: 60px;
    }
    }

    @media (max-width: 480px) {
    .game-container {
    padding: 15px;
    padding-top: 60px;
    }

    .stat-box {
    min-width: 85px;
    padding: 10px 12px;
    }

    .stat-label {
    font-size: 0.85rem;
    }

    .stat-value {
    font-size: 1.6rem;
    }

    .game-over {
    padding: 30px 20px;
    width: 95%;
    }

    .game-over h2 {
    font-size: 2.2rem;
    }

    .game-over p {
    font-size: 1.2rem;
    }

    /* iPhone竖屏优化 */
    .canvas-container {
    height: 350px;
    }

    h1 {
    font-size: 1.8rem;
    }

    .subtitle {
    font-size: 0.9rem;
    margin-bottom: 10px;
    }

    .game-ui {
    margin-bottom: 10px;
    }
    }

    /* iPhone竖屏特殊优化 */
    @media (max-width: 480px) and (max-height: 850px) {
    .game-container {
    padding-top: 50px;
    }

    .canvas-container {
    height: 300px;
    }

    .header {
    margin-bottom: 15px;
    }

    .stat-box {
    padding: 8px 10px;
    min-width: 70px;
    }

    .stat-value {
    font-size: 1.4rem;
    }

    .mobile-controls {
    margin-top: 15px;
    }

    .mobile-btn {
    width: 70px;
    height: 70px;
    font-size: 28px;
    }
    }

    /* iPhone小屏幕特殊优化 */
    @media (max-width: 375px) and (max-height: 670px) {
    .canvas-container {
    height: 280px;
    }

    .game-container {
    padding-top: 40px;
    padding: 10px;
    padding-top: 40px;
    }

    h1 {
    font-size: 1.6rem;
    }

    .stat-box {
    padding: 6px 8px;
    min-width: 65px;
    }

    .stat-label {
    font-size: 0.75rem;
    }

    .stat-value {
    font-size: 1.2rem;
    }

    .mobile-btn {
    width: 65px;
    height: 65px;
    font-size: 24px;
    }
    }

    /* 横屏优化 */
    @media (orientation: landscape) and (max-height: 600px) {
    .game-container {
    padding-top: 15px;
    }

    .header {
    margin-bottom: 10px;
    }

    h1 {
    font-size: 1.8rem;
    }

    .subtitle {
    font-size: 0.9rem;
    margin-bottom: 10px;
    }

    .game-ui {
    margin-bottom: 10px;
    }

    .stat-box {
    padding: 8px 12px;
    min-width: 80px;
    }

    .stat-value {
    font-size: 1.4rem;
    }

    .canvas-container {
    height: 280px;
    }

    .mobile-controls {
    margin-top: 15px;
    }
    }
    </style>
    </head>
    <body>
    <!– 背景图片 –>
    <div id="background-image"></div>
    <div id="background-overlay"></div>

    <!– 花朵特效容器 –>
    <div id="flower-effects"></div>

    <!– 更多游戏角标 –>
    <div class="more-games-corner">
    <a href="https://game.amitofo.icu" class="more-games-link">
    <i class="fas fa-gamepad"></i>
    <span>更多游戏</span>
    </a>
    </div>

    <!– 音频控制 –>
    <div class="audio-control" id="audioToggle">
    <i class="fas fa-volume-up" id="audioIcon"></i>
    </div>

    <!– 游戏主容器 –>
    <div class="game-container">
    <div class="header">
    <h1>单人壁球挑战赛</h1>
    <p class="subtitle">按空格键从球拍发射球,击中目标得分!每100分触发花朵特效。</p>
    </div>

    <div class="game-ui">
    <div class="stats">
    <div class="stat-box">
    <div class="stat-label">分数</div>
    <div id="score" class="stat-value">0</div>
    </div>
    <div class="stat-box">
    <div class="stat-label">生命值</div>
    <div id="lives" class="stat-value">3</div>
    </div>
    <div class="stat-box">
    <div class="stat-label">等级</div>
    <div id="level" class="stat-value">1</div>
    </div>
    </div>
    </div>

    <!– 游戏画布容器 –>
    <div class="canvas-container">
    <canvas id="gameCanvas" width="800" height="500"></canvas>
    </div>

    <!– 移动端控制按钮 –>
    <div class="mobile-controls">
    <div class="mobile-btn" id="mobileLeft">
    <i class="fas fa-arrow-left"></i>
    </div>
    <div class="mobile-btn" id="mobileSpace">
    <i class="fas fa-arrow-up"></i>
    <span style="font-size: 12px; margin-left: 5px;">发射</span>
    </div>
    <div class="mobile-btn" id="mobileRight">
    <i class="fas fa-arrow-right"></i>
    </div>
    </div>

    <!– 游戏控制按钮 – PC端显示 –>
    <div class="pc-controls">
    <div class="control-info">
    <div class="control-item">
    <div class="key">← →</div>
    <span>移动球拍</span>
    </div>
    <div class="control-item">
    <div class="key">空格</div>
    <span>发射球/暂停</span>
    </div>
    <div class="control-item">
    <div class="key">R</div>
    <span>重新开始</span>
    </div>
    </div>

    <div class="buttons">
    <button id="startBtn">
    <i class="fas fa-play"></i>
    <span>开始游戏</span>
    </button>
    <button id="pauseBtn">
    <i class="fas fa-pause"></i>
    <span>暂停游戏</span>
    </button>
    <button id="restartBtn">
    <i class="fas fa-redo"></i>
    <span>重新开始</span>
    </button>
    </div>
    </div>

    <!– 游戏结束界面 –>
    <div id="gameOver" class="game-over">
    <h2>游戏结束</h2>
    <p>最终得分: <span id="finalScore">0</span></p>
    <button id="playAgainBtn">
    <i class="fas fa-redo"></i>
    <span>再来一局</span>
    </button>
    </div>
    </div>

    <!– 背景音乐 –>
    <audio id="backgroundMusic" loop>
    <source src="https://amitofo.icu/beijing.ogg" type="audio/ogg">
    </audio>

    <!– 得分音效 –>
    <audio id="scoreSound">
    <source src="https://amitofo.icu/xiaochu.mp3" type="audio/mpeg">
    </audio>

    <!– 新的击球得分音效 –>
    <audio id="winSound" preload="auto">
    <source src="https://amitofo.icu/win.mp3" type="audio/mpeg">
    </audio>

    <script>
    // 获取Canvas元素和上下文
    const canvas = document.getElementById('gameCanvas');
    const ctx = canvas.getContext('2d');

    // 游戏状态
    let gameRunning = false;
    let gamePaused = false;
    let score = 0;
    let lives = 3;
    let level = 1;
    let animationId = null;
    let ballOnPaddle = true; // 球是否在球拍上(等待发射)
    let lastScoreForEffect = 0; // 上次触发特效的分数
    let isMobile = false; // 是否是移动设备

    // 球拍属性
    const paddle = {
    width: 100,
    height: 15,
    x: canvas.width / 2 – 50,
    y: canvas.height – 30,
    speed: 8,
    color: '#4a6ee0',
    borderColor: '#5a7ef0'
    };

    // 球属性
    const ball = {
    x: canvas.width / 2,
    y: canvas.height – 45, // 初始位置在球拍上方
    radius: 10,
    speedX: 0, // 初始速度为0,等待发射
    speedY: 0,
    color: '#FFD700',
    borderColor: '#FFA500'
    };

    // 目标属性 – 根据设备类型调整
    let targets = [];
    let targetRows = 5;
    let targetCols = 10;
    let targetWidth = 70;
    let targetHeight = 20;
    let targetPadding = 5;
    let targetOffsetTop = 50;
    let targetOffsetLeft = 25;

    // 音频元素
    const backgroundMusic = document.getElementById('backgroundMusic');
    const scoreSound = document.getElementById('scoreSound');
    const winSound = document.getElementById('winSound');
    let musicEnabled = true;

    // 花朵颜色数组
    const flowerColors = ['#FF3366', '#FF6633', '#FF33CC', '#33FF99', '#33CCFF', '#FFCC00', '#9966FF'];
    const flowerIcons = ['❀', '✿', '❁', '🌸', '🌺', '🌼', '🌻'];

    // 检测设备类型
    function detectDevice() {
    isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
    return isMobile;
    }

    // 根据屏幕尺寸调整目标参数(优化版本)
    function adjustTargetParameters() {
    const canvasWidth = canvas.width;
    const canvasHeight = canvas.height;

    if (isMobile && window.innerWidth < 768) {
    // 移动端竖屏调整
    if (canvasWidth < 400) {
    targetCols = 6;
    targetRows = 4;
    targetWidth = Math.max(40, (canvasWidth – targetOffsetLeft * 2 – targetPadding * (targetCols – 1)) / targetCols);
    targetHeight = 15;
    targetPadding = 3;
    targetOffsetTop = 40;
    targetOffsetLeft = (canvasWidth – (targetCols * targetWidth + (targetCols – 1) * targetPadding)) / 2;
    } else {
    targetCols = 8;
    targetRows = 5;
    targetWidth = Math.max(45, (canvasWidth – targetOffsetLeft * 2 – targetPadding * (targetCols – 1)) / targetCols);
    targetHeight = 18;
    targetPadding = 4;
    targetOffsetTop = 45;
    targetOffsetLeft = (canvasWidth – (targetCols * targetWidth + (targetCols – 1) * targetPadding)) / 2;
    }

    // 确保目标不会太小或太大
    targetWidth = Math.min(Math.max(targetWidth, 40), 70);
    targetHeight = Math.min(Math.max(targetHeight, 12), 20);

    // 确保目标不会超出屏幕
    const totalWidth = targetCols * targetWidth + (targetCols – 1) * targetPadding;
    if (totalWidth > canvasWidth – 10) {
    targetWidth = (canvasWidth – 10 – (targetCols – 1) * targetPadding) / targetCols;
    }
    } else {
    // PC端默认参数
    targetCols = 10;
    targetRows = 5;
    targetWidth = 70;
    targetHeight = 20;
    targetPadding = 5;
    targetOffsetTop = 50;
    targetOffsetLeft = 25;

    // 如果画布较小,适当调整
    if (canvasWidth < 600) {
    targetCols = 8;
    targetWidth = Math.max(50, (canvasWidth – targetOffsetLeft * 2 – targetPadding * (targetCols – 1)) / targetCols);
    }
    }
    }

    // 初始化目标
    function initTargets() {
    targets = [];
    adjustTargetParameters();

    for (let r = 0; r < targetRows; r++) {
    for (let c = 0; c < targetCols; c++) {
    // 随机生成特殊目标
    let isSpecial = Math.random() < 0.1; // 10%概率生成特殊目标
    let color, points, isLife;

    if (isSpecial) {
    // 随机选择特殊目标类型
    if (Math.random() < 0.5) {
    color = '#FFD700'; // 金色目标 – 高分
    points = 50;
    isLife = false;
    } else {
    color = '#FF5252'; // 红色目标 – 恢复生命
    points = 10;
    isLife = true;
    }
    } else {
    // 普通目标
    const hue = 200 + (r * 20); // 不同行的颜色不同
    color = `hsl(${hue}, 70%, 60%)`;
    points = 10;
    isLife = false;
    }

    targets.push({
    x: c * (targetWidth + targetPadding) + targetOffsetLeft,
    y: r * (targetHeight + targetPadding) + targetOffsetTop,
    width: targetWidth,
    height: targetHeight,
    color: color,
    points: points,
    isLife: isLife,
    visible: true
    });
    }
    }
    }

    // 初始化游戏
    function initGame() {
    score = 0;
    lives = 3;
    level = 1;
    ballOnPaddle = true;
    lastScoreForEffect = 0;

    // 重置球拍位置
    paddle.x = canvas.width / 2 – paddle.width / 2;

    // 根据设备调整球拍大小
    if (isMobile) {
    paddle.width = Math.min(120, canvas.width * 0.2);
    paddle.speed = 6;
    } else {
    paddle.width = 100;
    paddle.speed = 8;
    }

    // 调整球的大小
    ball.radius = isMobile ? Math.min(10, canvas.width * 0.02) : 10;

    // 重置球位置和速度(在球拍上等待发射)
    ball.x = paddle.x + paddle.width / 2;
    ball.y = paddle.y – ball.radius;
    ball.speedX = 0;
    ball.speedY = 0;

    // 初始化目标
    initTargets();

    // 更新UI
    updateUI();

    // 隐藏游戏结束界面
    document.getElementById('gameOver').style.display = 'none';

    // 播放背景音乐
    if (musicEnabled) {
    backgroundMusic.volume = 0.5;
    backgroundMusic.play().catch(e => console.log("自动播放被阻止,需要用户交互"));
    }
    }

    // 绘制球拍
    function drawPaddle() {
    // 绘制球拍阴影
    ctx.shadowColor = 'rgba(0, 0, 0, 0.3)';
    ctx.shadowBlur = 5;
    ctx.shadowOffsetX = 2;
    ctx.shadowOffsetY = 2;

    // 绘制球拍主体
    ctx.fillStyle = paddle.color;
    ctx.fillRect(paddle.x, paddle.y, paddle.width, paddle.height);

    // 绘制球拍边框
    ctx.strokeStyle = paddle.borderColor;
    ctx.lineWidth = 2;
    ctx.strokeRect(paddle.x, paddle.y, paddle.width, paddle.height);

    // 绘制球拍内部细节
    ctx.fillStyle = 'rgba(255, 255, 255, 0.2)';
    ctx.fillRect(paddle.x + 5, paddle.y + 3, paddle.width – 10, paddle.height – 6);

    // 重置阴影
    ctx.shadowColor = 'transparent';
    ctx.shadowBlur = 0;
    ctx.shadowOffsetX = 0;
    ctx.shadowOffsetY = 0;
    }

    // 绘制球
    function drawBall() {
    // 如果球在球拍上等待发射,绘制特殊效果
    if (ballOnPaddle) {
    // 绘制脉动效果
    const pulseSize = Math.sin(Date.now() / 200) * 2;

    // 绘制球阴影
    ctx.shadowColor = 'rgba(255, 215, 0, 0.5)';
    ctx.shadowBlur = 10 + pulseSize * 3;
    ctx.shadowOffsetX = 0;
    ctx.shadowOffsetY = 0;

    // 绘制球体
    ctx.beginPath();
    ctx.arc(ball.x, ball.y, ball.radius + pulseSize, 0, Math.PI * 2);
    ctx.fillStyle = '#FFD700';
    ctx.fill();

    // 绘制球边框
    ctx.strokeStyle = '#FFA500';
    ctx.lineWidth = 2;
    ctx.stroke();

    // 只在PC端显示提示文字
    if (!isMobile) {
    ctx.font = "14px Arial";
    ctx.fillStyle = "#FFFFFF";
    ctx.textAlign = "center";
    ctx.fillText("按空格发射", ball.x, ball.y – ball.radius – 15);
    }

    // 重置阴影
    ctx.shadowColor = 'transparent';
    ctx.shadowBlur = 0;
    } else {
    // 正常绘制球
    ctx.shadowColor = 'rgba(0, 0, 0, 0.4)';
    ctx.shadowBlur = 8;
    ctx.shadowOffsetX = 2;
    ctx.shadowOffsetY = 2;

    ctx.beginPath();
    ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2);
    ctx.fillStyle = ball.color;
    ctx.fill();

    ctx.strokeStyle = ball.borderColor;
    ctx.lineWidth = 2;
    ctx.stroke();

    ctx.shadowColor = 'transparent';
    ctx.shadowBlur = 0;
    }

    // 绘制球高光
    ctx.beginPath();
    ctx.arc(ball.x – ball.radius/3, ball.y – ball.radius/3, ball.radius/3, 0, Math.PI * 2);
    ctx.fillStyle = 'rgba(255, 255, 255, 0.6)';
    ctx.fill();
    }

    // 绘制目标
    function drawTargets() {
    targets.forEach(target => {
    if (!target.visible) return;

    // 绘制目标阴影
    ctx.shadowColor = 'rgba(0, 0, 0, 0.3)';
    ctx.shadowBlur = 3;
    ctx.shadowOffsetX = 1;
    ctx.shadowOffsetY = 1;

    // 绘制目标主体
    ctx.fillStyle = target.color;
    ctx.fillRect(target.x, target.y, target.width, target.height);

    // 绘制目标边框
    ctx.strokeStyle = 'rgba(255, 255, 255, 0.5)';
    ctx.lineWidth = 1;
    ctx.strokeRect(target.x, target.y, target.width, target.height);

    // 特殊目标添加额外效果
    if (target.points === 50) {
    // 金色目标的特殊效果
    ctx.fillStyle = 'rgba(255, 255, 255, 0.3)';
    ctx.fillRect(target.x + 5, target.y + 3, target.width – 10, target.height – 6);
    } else if (target.isLife) {
    // 生命目标的特殊效果
    ctx.fillStyle = 'rgba(255, 255, 255, 0.2)';
    ctx.beginPath();
    ctx.arc(target.x + target.width/2, target.y + target.height/2, target.height/3, 0, Math.PI * 2);
    ctx.fill();
    }

    // 重置阴影
    ctx.shadowColor = 'transparent';
    ctx.shadowBlur = 0;
    ctx.shadowOffsetX = 0;
    ctx.shadowOffsetY = 0;
    });
    }

    // 绘制背景
    function drawBackground() {
    // 清除画布,使用半透明黑色实现渐隐效果
    ctx.fillStyle = 'rgba(10, 15, 35, 0.2)';
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    // 绘制网格线
    ctx.strokeStyle = 'rgba(255, 255, 255, 0.05)';
    ctx.lineWidth = 1;

    // 垂直线
    for (let x = 0; x < canvas.width; x += 40) {
    ctx.beginPath();
    ctx.moveTo(x, 0);
    ctx.lineTo(x, canvas.height);
    ctx.stroke();
    }

    // 水平线
    for (let y = 0; y < canvas.height; y += 40) {
    ctx.beginPath();
    ctx.moveTo(0, y);
    ctx.lineTo(canvas.width, y);
    ctx.stroke();
    }
    }

    // 创建得分动画
    function createScoreAnimation(x, y, points) {
    const canvasContainer = document.querySelector('.canvas-container');
    const scorePopup = document.createElement('div');
    scorePopup.className = 'score-popup';
    scorePopup.textContent = `+${points}`;

    // 根据设备调整字体大小
    const fontSize = isMobile ? '20px' : '28px';
    scorePopup.style.fontSize = fontSize;

    // 计算相对于容器的位置
    const rect = canvas.getBoundingClientRect();
    const containerRect = canvasContainer.getBoundingClientRect();
    const relativeX = x * (rect.width / canvas.width);
    const relativeY = y * (rect.height / canvas.height);

    scorePopup.style.left = `${relativeX}px`;
    scorePopup.style.top = `${relativeY}px`;

    canvasContainer.appendChild(scorePopup);

    // 动画结束后移除元素
    setTimeout(() => {
    if (scorePopup.parentNode) {
    scorePopup.parentNode.removeChild(scorePopup);
    }
    }, 1000);
    }

    // 发射球
    function launchBall() {
    if (ballOnPaddle && gameRunning && !gamePaused) {
    ballOnPaddle = false;
    // 设置球的初始速度
    const baseSpeed = isMobile ? 4 : 5;
    ball.speedX = (Math.random() > 0.5 ? 1 : -1) * baseSpeed;
    ball.speedY = -baseSpeed;
    }
    }

    // 更新球的位置
    function updateBall() {
    if (ballOnPaddle) {
    // 球在球拍上,跟随球拍移动
    ball.x = paddle.x + paddle.width / 2;
    ball.y = paddle.y – ball.radius;
    } else {
    // 移动球
    ball.x += ball.speedX;
    ball.y += ball.speedY;

    // 检测与墙壁的碰撞
    if (ball.x + ball.radius > canvas.width || ball.x – ball.radius < 0) {
    ball.speedX = -ball.speedX;
    }

    // 检测与天花板的碰撞
    if (ball.y – ball.radius < 0) {
    ball.speedY = -ball.speedY;
    }

    // 检测与球拍的碰撞
    if (
    ball.y + ball.radius > paddle.y &&
    ball.y – ball.radius < paddle.y + paddle.height &&
    ball.x > paddle.x &&
    ball.x < paddle.x + paddle.width
    ) {
    // 根据击中球拍的位置调整反弹角度
    let hitPoint = (ball.x – paddle.x) / paddle.width;
    const angleMultiplier = isMobile ? 8 : 10;
    ball.speedX = (hitPoint – 0.5) * angleMultiplier;
    ball.speedY = -Math.abs(ball.speedY); // 确保球向上反弹
    }

    // 检测球是否落到底部
    if (ball.y + ball.radius > canvas.height) {
    lives–;
    updateUI();

    if (lives <= 0) {
    gameOver();
    } else {
    // 重置球的位置到球拍上
    ballOnPaddle = true;
    ball.x = paddle.x + paddle.width / 2;
    ball.y = paddle.y – ball.radius;
    ball.speedX = 0;
    ball.speedY = 0;
    }
    }

    // 检测与目标的碰撞
    targets.forEach(target => {
    if (!target.visible) return;

    if (
    ball.x + ball.radius > target.x &&
    ball.x – ball.radius < target.x + target.width &&
    ball.y + ball.radius > target.y &&
    ball.y – ball.radius < target.y + target.height
    ) {
    // 击中目标
    target.visible = false;
    ball.speedY = -ball.speedY;

    // 更新分数
    score += target.points;

    // 创建得分动画
    createScoreAnimation(ball.x, ball.y – 20, target.points);

    // 播放击球得分音效
    if (musicEnabled) {
    winSound.currentTime = 0;
    winSound.play().catch(e => console.log("得分音效播放失败"));
    }

    // 检查是否需要触发花朵特效
    if (Math.floor(score / 100) > Math.floor(lastScoreForEffect / 100)) {
    createFlowerEffect();
    lastScoreForEffect = score;

    // 播放额外的得分音效
    if (musicEnabled) {
    scoreSound.currentTime = 0;
    scoreSound.play().catch(e => console.log("音效播放失败"));
    }
    }

    // 如果是生命目标,增加生命值
    if (target.isLife) {
    lives = Math.min(lives + 1, 5); // 最多5条命
    }

    // 更新等级
    let newLevel = Math.floor(score / 100) + 1;
    if (newLevel > level) {
    level = newLevel;
    // 每升一级,球速增加
    const speedIncrease = isMobile ? 1.05 : 1.1;
    ball.speedX *= speedIncrease;
    ball.speedY *= speedIncrease;
    }

    updateUI();

    // 检查是否所有目标都被击中
    if (targets.every(t => !t.visible)) {
    // 所有目标被击中,重新生成
    initTargets();
    // 奖励额外生命
    lives = Math.min(lives + 1, 5);
    updateUI();
    }
    }
    });
    }
    }

    // 创建花朵特效
    function createFlowerEffect() {
    const flowerContainer = document.getElementById('flower-effects');
    const flowerCount = isMobile ? 20 : 30; // 移动端减少花朵数量

    for (let i = 0; i < flowerCount; i++) {
    const flower = document.createElement('div');
    flower.className = 'flower';

    // 随机选择花朵图标和颜色
    const iconIndex = Math.floor(Math.random() * flowerIcons.length);
    const colorIndex = Math.floor(Math.random() * flowerColors.length);

    flower.textContent = flowerIcons[iconIndex];
    flower.style.color = flowerColors[colorIndex];
    flower.style.left = Math.random() * 100 + 'vw';
    flower.style.fontSize = (isMobile ? 16 : 20) + Math.random() * (isMobile ? 15 : 20) + 'px';

    // 随机动画参数
    const duration = 3 + Math.random() * 4; // 3-7秒
    const delay = Math.random() * 2; // 0-2秒延迟
    const horizontalMove = (Math.random() – 0.5) * 100; // 水平移动距离

    flower.style.animation = `fall ${duration}s linear ${delay}s forwards`;
    flower.style.transform = `translateX(${horizontalMove}px)`;

    flowerContainer.appendChild(flower);

    // 动画结束后移除花朵元素
    setTimeout(() => {
    if (flower.parentNode) {
    flower.parentNode.removeChild(flower);
    }
    }, (duration + delay) * 1000);
    }
    }

    // 更新UI
    function updateUI() {
    document.getElementById('score').textContent = score;
    document.getElementById('lives').textContent = lives;
    document.getElementById('level').textContent = level;
    }

    // 游戏结束
    function gameOver() {
    gameRunning = false;
    cancelAnimationFrame(animationId);

    document.getElementById('finalScore').textContent = score;
    document.getElementById('gameOver').style.display = 'block';
    }

    // 游戏主循环
    function gameLoop() {
    // 绘制游戏背景
    drawBackground();

    // 绘制游戏元素
    drawTargets();
    drawPaddle();
    drawBall();

    // 更新游戏状态
    if (!gamePaused && gameRunning) {
    updateBall();
    }

    // 继续游戏循环
    if (gameRunning) {
    animationId = requestAnimationFrame(gameLoop);
    }
    }

    // 键盘控制
    const keys = {};

    window.addEventListener('keydown', (e) => {
    keys[e.key] = true;

    // 空格键发射球或暂停游戏
    if (e.key === ' ' && gameRunning) {
    if (ballOnPaddle) {
    launchBall();
    } else {
    togglePause();
    }
    e.preventDefault(); // 防止空格键滚动页面
    }

    // R键重新开始
    if (e.key === 'r' || e.key === 'R') {
    restartGame();
    }
    });

    window.addEventListener('keyup', (e) => {
    keys[e.key] = false;
    });

    // 处理球拍移动
    function handlePaddleMovement() {
    if (keys['ArrowLeft'] || keys['Left'] || keys['a'] || keys['A']) {
    paddle.x = Math.max(0, paddle.x – paddle.speed);
    }

    if (keys['ArrowRight'] || keys['Right'] || keys['d'] || keys['D']) {
    paddle.x = Math.min(canvas.width – paddle.width, paddle.x + paddle.speed);
    }

    // 每帧调用
    if (gameRunning && !gamePaused) {
    requestAnimationFrame(handlePaddleMovement);
    }
    }

    // 切换暂停状态
    function togglePause() {
    gamePaused = !gamePaused;
    // PC端更新按钮文本
    if (!isMobile) {
    document.getElementById('pauseBtn').innerHTML = gamePaused ?
    '<i class="fas fa-play"></i><span>继续游戏</span>' :
    '<i class="fas fa-pause"></i><span>暂停游戏</span>';
    }

    if (!gamePaused && gameRunning) {
    handlePaddleMovement();
    }
    }

    // 开始游戏
    function startGame() {
    if (!gameRunning) {
    initGame();
    gameRunning = true;
    gamePaused = false;
    if (!isMobile) {
    document.getElementById('pauseBtn').innerHTML = '<i class="fas fa-pause"></i><span>暂停游戏</span>';
    }
    gameLoop();
    handlePaddleMovement();
    }
    }

    // 暂停游戏
    function pauseGame() {
    if (gameRunning) {
    togglePause();
    }
    }

    // 重新开始游戏
    function restartGame() {
    gameRunning = false;
    gamePaused = false;
    cancelAnimationFrame(animationId);
    startGame();
    }

    // 音频控制
    document.getElementById('audioToggle').addEventListener('click', function() {
    musicEnabled = !musicEnabled;
    const icon = document.getElementById('audioIcon');

    if (musicEnabled) {
    icon.className = 'fas fa-volume-up';
    backgroundMusic.volume = 0.5;
    backgroundMusic.play().catch(e => console.log("音频播放需要用户交互"));
    } else {
    icon.className = 'fas fa-volume-mute';
    backgroundMusic.pause();
    }
    });

    // 移动端控制
    document.getElementById('mobileLeft').addEventListener('touchstart', function(e) {
    e.preventDefault();
    keys['ArrowLeft'] = true;
    });

    document.getElementById('mobileLeft').addEventListener('touchend', function(e) {
    e.preventDefault();
    keys['ArrowLeft'] = false;
    });

    document.getElementById('mobileRight').addEventListener('touchstart', function(e) {
    e.preventDefault();
    keys['ArrowRight'] = true;
    });

    document.getElementById('mobileRight').addEventListener('touchend', function(e) {
    e.preventDefault();
    keys['ArrowRight'] = false;
    });

    document.getElementById('mobileSpace').addEventListener('touchstart', function(e) {
    e.preventDefault();
    if (gameRunning) {
    if (ballOnPaddle) {
    launchBall();
    } else {
    togglePause();
    }
    }
    });

    // 事件监听 – PC端按钮
    document.getElementById('startBtn').addEventListener('click', startGame);
    document.getElementById('pauseBtn').addEventListener('click', pauseGame);
    document.getElementById('restartBtn').addEventListener('click', restartGame);
    document.getElementById('playAgainBtn').addEventListener('click', restartGame);

    // 窗口调整大小时调整Canvas
    function resizeCanvas() {
    const container = document.querySelector('.canvas-container');
    const containerWidth = Math.min(container.clientWidth, 800);
    const containerHeight = container.clientHeight;

    // 设置Canvas尺寸
    canvas.width = containerWidth;
    canvas.height = containerHeight;

    // 重新调整球拍位置
    paddle.y = canvas.height – 30;

    // 根据设备调整球拍宽度
    if (isMobile) {
    paddle.width = Math.min(120, containerWidth * 0.2);
    paddle.speed = 6;
    } else {
    paddle.width = 100;
    paddle.speed = 8;
    }

    // 调整球的大小
    ball.radius = isMobile ? Math.min(10, containerWidth * 0.02) : 10;

    // 如果球在球拍上,调整球的位置
    if (ballOnPaddle) {
    ball.x = paddle.x + paddle.width / 2;
    ball.y = paddle.y – ball.radius;
    }

    // 如果游戏运行中,重新初始化目标以适应新尺寸
    if (gameRunning) {
    initTargets();
    }
    }

    // 初始调整Canvas大小
    window.addEventListener('load', () => {
    // 检测设备类型
    detectDevice();

    // 初始化Canvas
    resizeCanvas();

    // 自动开始游戏
    setTimeout(() => {
    startGame();
    }, 500);

    // 预加载音频
    winSound.load();

    // 尝试播放背景音乐(需要用户交互)
    document.addEventListener('click', function initAudio() {
    if (musicEnabled) {
    backgroundMusic.volume = 0.5;
    backgroundMusic.play().catch(e => console.log("音频播放需要用户交互"));
    }
    document.removeEventListener('click', initAudio);
    });
    });

    window.addEventListener('resize', resizeCanvas);

    // 触摸设备支持
    let touchStartX = 0;

    canvas.addEventListener('touchstart', (e) => {
    if (!gameRunning || gamePaused) return;

    e.preventDefault();
    const touch = e.touches[0];
    const rect = canvas.getBoundingClientRect();
    touchStartX = touch.clientX – rect.left;
    }, { passive: false });

    canvas.addEventListener('touchmove', (e) => {
    if (!gameRunning || gamePaused) return;

    e.preventDefault();
    const touch = e.touches[0];
    const rect = canvas.getBoundingClientRect();
    const touchX = touch.clientX – rect.left;

    // 计算移动距离并更新球拍位置
    const deltaX = touchX – touchStartX;
    paddle.x += deltaX;

    // 限制球拍在画布内
    if (paddle.x < 0) paddle.x = 0;
    if (paddle.x + paddle.width > canvas.width) paddle.x = canvas.width – paddle.width;

    // 更新起始触摸位置
    touchStartX = touchX;

    // 如果球在球拍上,更新球的位置
    if (ballOnPaddle) {
    ball.x = paddle.x + paddle.width / 2;
    }
    }, { passive: false });

    // 点击画布发射球(移动端)
    canvas.addEventListener('touchend', (e) => {
    if (!gameRunning || gamePaused) return;

    e.preventDefault();
    // 移动端点击发射球
    if (ballOnPaddle) {
    launchBall();
    }
    }, { passive: false });

    // 防止页面滚动
    document.addEventListener('touchmove', function(e) {
    if (gameRunning) {
    e.preventDefault();
    }
    }, { passive: false });

    // 防止双击缩放
    let lastTouchEnd = 0;
    document.addEventListener('touchend', function(event) {
    const now = (new Date()).getTime();
    if (now – lastTouchEnd <= 300) {
    event.preventDefault();
    }
    lastTouchEnd = now;
    }, false);
    </script>
    </body>
    </html>

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » DeepSeek生成的网页小游戏 - 单人壁球挑战赛
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!