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

news/2024/11/12 20:55:35 标签: 前端, inscode, canvas, javascript, h5游戏

inscode-box">

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

已经实现的游戏一览:

  • 俄罗斯方块

游戏界面

在这里插入图片描述

游戏实现解析

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

页面布局与交互元素

index.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结合可实现流畅的动画和交互功能。

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


http://www.niftyadmin.cn/n/5747056.html

相关文章

发送方确认

在使用RabbitMQ的时候&#xff0c;可以通过消息持久化来解决因为服务器的异常而导致的消息就是&#xff0c;但是还有一个问题&#xff0c;当消息的生产者将消息发送出去之后&#xff0c;消息到底有没有正确地到达服务器呢&#xff1f;如果消息在到达服务器之前已经丢失&#xf…

【数据结构】ArrayList的具体实现:简单的洗牌算法--Java

目录 引言 简单的洗牌算法 Card类&#xff08;牌类&#xff09; CardList&#xff08;一副牌&#xff09; washCard&#xff08;洗牌&#xff09; dealCard&#xff08;发牌&#xff09; 引言 实现一个简单的洗牌算法&#xff0c;这幅牌一共52张&#xff0c;不包含大小王…

XMLHttpRequest以及Promise对象的使用

AJAX原理 通过[XHR]XMLHttpRequest对象来和服务器进行交互&#xff0c;axios库的底层也是通过XMLHttpRequest来和服务器进行交互&#xff0c;只是将实现细节进行了封装&#xff0c;让操作更加简洁 可以用于某些只需和服务器进行少次交互的静态网站进行使用&#xff0c;减少代…

目录树文件名映射深度1分组计数,tree(映射(目录A))

#!/bin/bash#【描述】 目录树文件名映射深度1分组计数,tree(映射(目录A)) #【术语】 # aggaggregate聚合统计按照mime-type分组 # FNFileName文件名 #【基本思路】 # 0. linux gnu tree命令的优点: 目录结构树展示的很友好. 而且 单独做一个同样的展示效果 并不容易 # 1. …

散列表(Hashing table),散列函数(Hashing function),分离链接法(separate chaining)

引言 散列表&#xff08;hashing table)的实现通常称为散列(hashing).散列是一种用于以常数平均时间执行插入&#xff0c;删除和查找的技术。但是&#xff0c;那些需要元素间任何序信息的树操作在这里都不会得到有效的支持&#xff08;譬如说findmax&#xff0c;findmin&#…

GIF图片格式详解(三)

gif历史部分介绍请参考上一篇《GIF图片格式详解&#xff08;一&#xff09;》&#xff0c; 格式部分详解参考 《GIF图片格式详解&#xff08;二&#xff09;》 或直接访问博客地址&#xff1a;https://blog.whatsroot.xyz/2023/12/16/all-about-gif/ 本篇介绍下用于处理gif图…

k8s中基于overlay网络和underlay网络的网络插件分别有哪些

在 Kubernetes 中&#xff0c;不同的网络插件会使用 overlay 或 underlay 网络来连接 Pod 和节点。以下是基于 overlay 网络和 underlay 网络的常见 Kubernetes 网络插件&#xff1a; 1. 基于 Overlay 网络的插件 这些插件通过隧道封装技术&#xff08;如 VXLAN、GRE 等&#…

基于微信小程序的实习管理系统(附源码,文档)

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…