格斗游戏html代码怎么写?html5开发小游戏教程
- 虚拟主机
- 2026-06-20
- 7
核心架构设计
构建一个基于HTML5 Canvas的格斗游戏,核心在于利用JavaScript处理游戏循环、物理碰撞检测以及状态机管理,代码结构通常分为三个主要部分:HTML用于定义画布容器,CSS用于基础样式重置,JavaScript负责所有的逻辑运算。

| 模块 | 功能描述 | 关键技术点 |
|---|---|---|
| HTML结构 | 提供游戏渲染区域 | <canvas> 标签,设置宽高 |
| CSS样式 | 隐藏滚动条,居中画布 | display: flex, margin: auto |
| JS引擎 | 处理帧更新与绘制 | requestAnimationFrame, update(), draw() |
角色类与属性定义
在JavaScript中,我们需要创建一个Fighter类来实例化玩家和敌人,每个角色对象需要包含位置、速度、尺寸、生命值以及当前的动作状态(如站立、跳跃、攻破)。
class Fighter { constructor({ position, velocity, color = 'red', offset = { x: 0, y: 0 } }) { this.position = position; this.velocity = velocity; this.width = 50; this.height = 150; this.lastKey; this.attackBox = { position: { x: this.position.x, y: this.position.y }, offset: offset, width: 100, height: 50 }; this.color = color; this.isAttacking = false; this.health = 100; } draw() { // 绘制角色主体 ctx.fillStyle = this.color; ctx.fillRect(this.position.x, this.position.y, this.width, this.height); // 绘制攻破判定框(仅在攻破时显示,便于调试) if (this.isAttacking) { ctx.fillStyle = 'green'; ctx.fillRect( this.attackBox.position.x, this.attackBox.position.y, this.attackBox.width, this.attackBox.height ); } } update() { this.draw(); // 更新攻破框位置跟随角色 this.attackBox.position.x = this.position.x + this.attackBox.offset.x; this.attackBox.position.y = this.position.y; // 物理移动逻辑 this.position.x += this.velocity.x; this.position.y += this.velocity.y; // 重力模拟 if (this.position.y + this.height + this.velocity.y >= canvas.height) { this.velocity.y = 0; this.position.y = canvas.height this.height; // 防止陷入地面 } else { this.velocity.y += 0.7; // 重力加速度 } } attack() { this.isAttacking = true; setTimeout(() => { this.isAttacking = false; }, 100); // 攻破持续100毫秒 } }
游戏循环与输入控制
游戏的主循环通过requestAnimationFrame实现,确保动画流畅,我们需要监听键盘事件来改变角色的速度向量,从而实现移动和跳跃。
碰撞检测机制
格斗游戏的核心反馈在于击中判定,我们需要编写一个矩形碰撞检测函数,判断攻破框是否与对手的身体矩形重叠,如果重叠,则扣除对方生命值。

function rectangularCollision({ rectangle1, rectangle2 }) { return ( rectangle1.attackBox.position.x + rectangle1.attackBox.width >= rectangle2.position.x && rectangle1.attackBox.position.x <= rectangle2.position.x + rectangle2.width && rectangle1.attackBox.position.y + rectangle1.attackBox.height >= rectangle2.position.y && rectangle1.attackBox.position.y <= rectangle2.position.y + rectangle2.height ); } // 在 animate 循环中加入检测 if ( rectangularCollision({ rectangle1: player, rectangle2: enemy }) && player.isAttacking ) { player.isAttacking = false; // 命中后立即重置攻破状态,防止多段伤害 enemy.health -= 20; console.log('Player hit!'); } // 同理检测敌人击中玩家 if ( rectangularCollision({ rectangle1: enemy, rectangle2: player }) && enemy.isAttacking ) { enemy.isAttacking = false; player.health -= 20; console.log('Enemy hit!'); } // 游戏结束判定 if (enemy.health <= 0 || player.health <= 0) { // 这里可以添加游戏结束逻辑,如显示胜负画面 console.log('Game Over'); }
常见问题与解答
问题 1:为什么角色在跳跃时会穿过地面或者陷入地面?
解答:这通常是因为重力计算和地面碰撞检测的顺序或逻辑有误,在上面的代码中,我们在update()方法中先应用了重力加速度this.velocity.y += 0.7,然后检查this.position.y + this.height是否大于等于画布高度,如果大于,则将速度设为0并强制将Y坐标设置为地面位置,如果角色陷入地面,可能是因为初始Y坐标设置过低,或者重力加速度过大导致单帧内位移超过地面阈值,解决方法是确保地面高度常量准确,并在碰撞发生后立即修正位置,而不仅仅是速度。
问题 2:如何防止角色在攻破时连续触发多次伤害?
解答:在代码中,我们使用了this.isAttacking标志位和setTimeout来限制攻破持续时间,如果在animate循环中,每一帧都检测到碰撞且isAttacking为真,就会造成连续扣血,解决方案是在检测到碰撞并造成伤害后,立即将isAttacking设置为false(如代码中player.isAttacking = false所示),这样,即使攻破框仍然与敌人重叠,由于标志位已重置,也不会再次触发伤害判定,直到下一次完整的攻破动作开始。
