即时可玩web小游戏(二):打砖块(支持移动端版) - 集成InsCode快来阅读并即时体验吧~

建议全屏或者新页面运行、首次运行需要冷启动,时间要一点,不如倒杯茶去~白屏也是需要等一下即可

已经实现的游戏一览:

游戏界面

游戏实现解析

代码参考Inscode - 查看文件即可,在本节,我将分步解析一个使用HTML5 Canvas和JavaScript实现的经典打砖块游戏。通过拆解游戏的各个模块,你将了解如何通过代码实现碰撞检测、动画循环和用户交互等核心功能。

页面布局与交互元素

index.html文件中,我们主要设置了游戏的基本界面,包括画布区域、得分显示、速度选择、控制按钮和开始按钮。

html 复制代码
<div class="game-container">
    <div style="display:flex;width:100%;justify-content:space-between;">
        <div id="score">得分: 0</div>
        <div class="settings">
            <select id="speedSelect" class="speed-select">
                <option value="1">慢速</option>
                <option value="2" selected>中速</option>
                <option value="3">快速</option>
            </select>
        </div>
    </div>
    <canvas id="gameCanvas"></canvas>
    <div class="controls">
        <button class="btn" id="leftBtn">←</button>
        <button class="btn" id="rightBtn">→</button>
    </div>
    <button id="startBtn">开始游戏</button>
</div>
  • <canvas id="gameCanvas">:用于绘制游戏元素(小球、砖块和挡板),游戏的主要区域。
  • 得分和速度选择:实时更新得分,速度选择允许玩家选择游戏的难度。
  • 控制按钮:使用左右箭头按钮(适用于触屏设备)控制挡板的移动。
  • 开始按钮:用于控制游戏的开始、暂停和重置。

JavaScript游戏逻辑与渲染

JavaScript部分实现了整个游戏的核心逻辑和绘图。

画布初始化与参数设置
javascript 复制代码
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
canvas.width = Math.min(400, window.innerWidth - 40);
canvas.height = 500;

我们创建画布并获取绘图上下文 (ctx)。接着,设定画布尺寸,使其在较小的屏幕上自适应宽度(限制最大宽度为400像素)。

游戏参数配置
javascript 复制代码
const paddleHeight = 10, paddleWidth = 75;
const brickRowCount = 5, brickColumnCount = 5, brickWidth = 60, brickHeight = 20;
const brickPadding = 8, brickOffsetTop = 30;
  • 挡板:宽75高10,用于控制小球的反弹。
  • 砖块:5行5列,每个砖块宽60高20,行列之间有8像素的间距。

这些参数定义了游戏的布局,确保砖块和挡板的尺寸适合画布。

速度配置与选择事件
javascript 复制代码
const speedConfigs = {
    1: { dx: 2, dy: -2, paddleSpeed: 5 },
    2: { dx: 3, dy: -3, paddleSpeed: 7 },
    3: { dx: 4, dy: -4, paddleSpeed: 9 }
};
let currentSpeed = speedConfigs[2];

游戏的难度通过speedConfigs配置。dxdy是小球在X和Y轴上的移动速度,paddleSpeed表示挡板的移动速度。玩家可以通过速度选择菜单 (speedSelect) 改变这些配置。

游戏初始化 (initGame)

initGame函数用于重置游戏状态,包括小球位置、挡板位置、砖块状态和得分。

javascript 复制代码
function initGame() {
    // 初始化挡板位置
    paddleX = (canvas.width - paddleWidth) / 2;
    // 初始化小球位置与速度
    x = canvas.width / 2;
    y = canvas.height - 30;
    dx = currentSpeed.dx;
    dy = currentSpeed.dy;
    // 初始化砖块数组
    for (let c = 0; c < brickColumnCount; c++) {
        bricks[c] = [];
        for (let r = 0; r < brickRowCount; r++) {
            bricks[c][r] = { x: 0, y: 0, status: 1 };
        }
    }
    // 重置得分
    score = 0;
    scoreElement.textContent = `得分: ${score}`;
    draw();
}
  • 挡板和小球初始位置:使小球位于画布下方中心,挡板位于画布底部中心。
  • 砖块数组 :砖块存储在二维数组bricks中。status属性表示砖块是否存在(1表示存在,0表示已被打掉)。
  • 重置分数:得分清零并更新显示。
控制事件

我们为触摸按钮和键盘添加事件监听,使玩家能够通过左右方向键或按钮移动挡板。

javascript 复制代码
document.addEventListener('keydown', (e) => { /*...*/ });
document.addEventListener('keyup', (e) => { /*...*/ });

通过这些事件,leftPressedrightPressed 控制挡板的移动方向。

碰撞检测 (collisionDetection)

collisionDetection 函数实现小球与砖块的碰撞检测,破坏被碰撞的砖块并更新得分。

javascript 复制代码
function collisionDetection() {
    for (let c = 0; c < brickColumnCount; c++) {
        for (let r = 0; r < brickRowCount; r++) {
            const b = bricks[c][r];
            if (b.status === 1) {
                if (x > b.x && x < b.x + brickWidth && y > b.y && y < b.y + brickHeight) {
                    dy = -dy;
                    b.status = 0;
                    score++;
                    scoreElement.textContent = `得分: ${score}`;
                    if (score === brickRowCount * brickColumnCount) {
                        alert('恭喜你赢了!');
                        initGame();
                        return;
                    }
                }
            }
        }
    }
}
  • 碰撞检测 :检查小球是否在砖块范围内,若是则反转dy方向,破坏砖块(将其status设为0)。
  • 游戏胜利检测:如果破坏的砖块数等于总砖块数,显示胜利信息并重置游戏。
绘制函数
  1. 小球 :使用arc绘制圆形小球。
  2. 挡板 :使用rect绘制矩形挡板。
  3. 砖块 :遍历bricks数组,绘制每个未被破坏的砖块。
javascript 复制代码
function drawBall() { /*...*/ }
function drawPaddle() { /*...*/ }
function drawBricks() { /*...*/ }
游戏主循环 (draw)

draw函数作为主循环,不断更新游戏状态和画布绘制。

javascript 复制代码
function draw() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    drawBricks();
    drawBall();
    drawPaddle();

    if (gameStarted) {
        collisionDetection();

        // 小球碰到左右边界时反弹
        if (x + dx > canvas.width - ballRadius || x + dx < ballRadius) dx = -dx;
        // 小球碰到顶部时反弹,碰到底部未击中挡板时游戏结束
        if (y + dy < ballRadius) dy = -dy;
        else if (y + dy > canvas.height - ballRadius) { /*...*/ }

        // 挡板移动
        if (rightPressed && paddleX < canvas.width - paddleWidth) paddleX += currentSpeed.paddleSpeed;
        else if (leftPressed && paddleX > 0) paddleX -= currentSpeed.paddleSpeed;

        // 更新小球位置
        x += dx;
        y += dy;
    }

    animationId = requestAnimationFrame(draw);
}
  • 清除画布:在每帧绘制前清除画布,避免前一帧图像残留。
  • 碰撞检测 :调用collisionDetection,更新小球的移动方向和砖块状态。
  • 边界反弹:小球到达边界时反弹,若未击中挡板则游戏结束。
  • 挡板移动:根据按键更新挡板位置。
  • 位置更新 :将小球的新位置传递给draw以绘制下一帧。
开始和重新开始

startBtn按钮控制游戏开始和重置。点击"开始游戏"将启动draw函数动画循环,再次点击会重置游戏状态。

总结

通过阅读本文,相信你不只是成功摸鱼(运行了前面的代码),还通过阅读代码解析,看到了HTML5 Canvas的强大绘图能力与JavaScript结合可实现流畅的动画和交互功能。

游戏的核心流程了解的差不多了,记得事件下哈~

相关推荐
乔峰不是张无忌3307 分钟前
【HTML】动态闪烁圣诞树+雪花+音效
前端·javascript·html·圣诞树
鸿蒙自习室14 分钟前
鸿蒙UI开发——组件滤镜效果
开发语言·前端·javascript
m0_7482507421 分钟前
高性能Web网关:OpenResty 基础讲解
前端·openresty
前端没钱1 小时前
从 Vue 迈向 React:平滑过渡与关键注意点全解析
前端·vue.js·react.js
汪洪墩1 小时前
【Mars3d】设置backgroundImage、map.scene.skyBox、backgroundImage来回切换
开发语言·javascript·python·ecmascript·webgl·cesium
NoneCoder1 小时前
CSS系列(29)-- Scroll Snap详解
前端·css
无言非影1 小时前
vtie项目中使用到了TailwindCSS,如何打包成一个单独的CSS文件(优化、压缩)
前端·css
我曾经是个程序员1 小时前
鸿蒙学习记录
开发语言·前端·javascript
羊小猪~~2 小时前
前端入门之VUE--ajax、vuex、router,最后的前端总结
前端·javascript·css·vue.js·vscode·ajax·html5
摸鱼了2 小时前
🚀 从零开始搭建 Vue 3+Vite+TypeScript+Pinia+Vue Router+SCSS+StyleLint+CommitLint+...项目
前端·vue.js