Canvas 2D API 是零基础开发 HTML5 小游戏的首选入口,需用 getContext('2d')、requestAnimationFrame、clearRect 和 fillRect 实现基础动画,注意绘图坐标更新、canvas 像素尺寸设置、时间校准、按键状态机及 AABB 碰撞检测。

Canvas 2D API 是你第一个必须盯住的入口
零基础做 HTML5 小游戏,canvas 元素 + getContext('2d') 就是绕不开的起点。它不靠 DOM 操作,而是用 JS 直接画像素,性能可控、逻辑清晰,适合打地鼠、弹球、贪吃蛇这类 2D 游戏。
别一上来就碰 WebGL 或框架——那些会掩盖“怎么让一个方块动起来”这个最核心的问题。先用 requestAnimationFrame 驱动循环,用 clearRect 清屏,用 fillRect 画角色,三步就能跑通一帧逻辑。
- 常见错误:把
canvas当成普通 div,试图用style.left/top移动角色 → 实际要改的是绘制坐标(x,y)再重绘 - 容易忽略:
canvas默认宽高是 300×150 像素,CSS 设置只缩放显示,不改变绘图分辨率 → 必须同时设canvas.width和canvas.height属性 - 练手建议:写一个“键盘控制小方块移动”的 demo,只用
keydown监听 +requestAnimationFrame循环 +fillRect绘制,15 行内搞定
游戏循环里最常崩掉的其实是时间控制
新手写的“每帧移动 2 像素”,在不同设备上速度天差地别。不是帧率不稳定,而是没做时间校准。浏览器的 requestAnimationFrame 只保证“下一帧”,不保证“多久一帧”。
真正稳的写法是记录上一帧时间戳,算出本次耗时(deltaTime),再按比例更新位置:position += speed * deltaTime / 16(以 60fps 为基准)。这样哪怕掉帧,移动距离也一致。
立即学习“前端免费学习笔记(深入)”;
- 错误示范:用
setInterval定时刷新 → 与屏幕刷新率不同步,易撕裂、卡顿 - 参数差异:
requestAnimationFrame(callback)的callback会自动传入当前时间戳(DOMHighResTimeStamp),直接用就行 - 性能提示:别在每帧里反复调用
Date.now()或performance.now()—— 时间戳已由浏览器提供,拿来即用
键盘事件监听要防住重复触发和焦点丢失
写个方向键控制,结果按住不放角色狂飙、切到别的标签页再回来就失灵——这是没处理好事件状态机。原生 keydown 在长按时会连续触发,而 keyup 又可能因窗口失焦收不到。
正确做法是用布尔对象记录按键状态:keys['ArrowUp'] = true/false,在 keydown 和 keyup 里更新它;游戏循环中只查这个对象,不直接响应事件。
- 兼容性注意:老式键盘可能不触发
keyup(比如 Alt+Tab 切出时),所以得加window.onblur清空所有keys - 移动端?先别碰。HTML5 小游戏初期专注桌面端键盘+鼠标,触屏要额外处理
touchstart/touchmove和防止滚动冲突(event.preventDefault()) - 练手验证:加一行
console.log(keys)到循环里,按住方向键看布尔值是否稳定切换,松开后是否归 false
从“能动”到“像游戏”只差一个碰撞检测函数
小方块碰到墙停住、子弹打中敌人消失——这些都依赖矩形碰撞判断。别抄复杂算法,90% 的入门项目用 AABB(Axis-Aligned Bounding Box)就够了:两个矩形左边界小于对方右边界,且上边界小于对方下边界。
写成函数就四行:rect1.x rect2.x && ...。把它抽出来,命名 isColliding(rectA, rectB),后面所有交互逻辑就干净了。
- 典型坑:用
getBoundingClientRect()获取 canvas 内元素位置 → 它返回的是相对于视口的坐标,和 canvas 坐标系不一致,要手动减去 canvas 偏移 - 调试技巧:临时用
strokeRect把碰撞盒画出来,一眼看出错在哪边 - 扩展提醒:如果要做圆和矩形碰撞,别硬推公式——先用圆心到矩形边缘的最近点距离 vs 半径,比纯数学推导快得多
真正卡住人的从来不是语法,而是“怎么把物理规则翻译成 if 判断”。先跑通一个可移动、有边界、能碰撞的最小闭环,后面加分数、音效、关卡都是往里填零件。别等学完所有再动手,第一版只要能让方块撞墙反弹,就已经在做游戏了。











