用 400 行代码做一个极简坦克大战:从零到发布的完整实践

举报
yd_255618844 发表于 2026/10/21 10:26:19 2026/10/21
【摘要】 本文记录了一个极简风格坦克大战游戏的完整开发与发布过程。游戏采用纯 HTML + Canvas + JavaScript 实现,零外部依赖,黑白灰三色配色,涵盖玩家操控、敌方 AI、碰撞检测、墙壁障碍、计分与生命系统等核心玩法。最终通过 GitCode 开发者作品展览馆开源发布。文章从设计思路、技术选型、核心代码解析到发布流程逐一展开,适合对 Canvas 游戏开发和轻量级项目发布感兴趣的开发者参

📄 摘要

本文记录了一个极简风格坦克大战游戏的完整开发与发布过程。游戏采用纯 HTML + Canvas + JavaScript 实现,零外部依赖,黑白灰三色配色,涵盖玩家操控、敌方 AI、碰撞检测、墙壁障碍、计分与生命系统等核心玩法。最终通过 GitCode 开发者作品展览馆开源发布。文章从设计思路、技术选型、核心代码解析到发布流程逐一展开,适合对 Canvas 游戏开发和轻量级项目发布感兴趣的开发者参考。


📖 正文

一、为什么做这个项目

经典坦克大战是很多人的童年回忆。市面上的复刻版本往往追求像素还原、音效还原,代码量动辄上千行。但如果只保留最核心的玩法——移动、射击、躲避、消灭敌人——其实几百行代码就够了。

这个项目的目标很明确:用最少的代码,实现能玩的坦克大战,界面极简到极致。

二、设计思路

2.1 极简美学

整个游戏只用 4 个颜色:

颜色 用途 色值
纯黑 背景 #000
白色 玩家坦克、子弹、文字 #fff
灰色 敌方坦克 #888
深灰 墙壁、画布边框 #333

没有渐变、没有阴影、没有粒子特效、没有音效。等宽字体 Courier New 贯穿全局,营造出一种终端/复古的视觉气质。

2.2 玩法设计

只保留坦克大战最本质的元素:

  • 玩家:方向键/WASD 四向移动,空格射击
  • 敌人:3 辆敌方坦克,随机移动 + 周期射击
  • 墙壁:网格地图中的砖墙障碍,阻挡坦克和子弹
  • 胜负:消灭全部敌人 = 胜利;3 条命用完 = 游戏结束
  • HUD:顶部实时显示分数、剩余生命、剩余敌人数

三、技术实现

3.1 整体架构

index.html    ← 页面结构 + CSS 样式(602 字节)
game.js       ← 游戏全部逻辑(约 400 行)

零依赖、零构建工具。用 python3 -m http.server 8080 即可启动预览,浏览器打开直接游玩。

3.2 核心数据结构

方向系统——用 4 个向量描述上下左右:

var DIRS = [
  { x: 0, y: -1 },  // 上
  { x: 1, y: 0 },   // 右
  { x: 0, y: 1 },   // 下
  { x: -1, y: 0 }   // 左
];

地图——用字符串数组表示 20×20 网格,# 代表墙壁:

var mapStr = [
  "                    ",
  "  ##    ##    ##    ",
  "                    ",
  "    ##        ##    ",
  "        ####        ",
  // ...
];

这种设计的好处是:地图布局一目了然,修改关卡只需改字符串。

3.3 坦克对象

用构造函数 + 原型方法实现坦克实体:

function Tank(x, y, dir, isEnemy) {
  this.x = x;
  this.y = y;
  this.dir = dir;
  this.isEnemy = isEnemy;
  this.alive = true;
  this.cooldown = 0;           // 射击冷却
  this.changeDirTimer = ...;   // AI 换方向计时器
  this.shootTimer = ...;       // AI 射击计时器
}

每个坦克维护自己的位置、方向、存活状态和冷却计时器。敌方坦克额外有 changeDirTimer 和 shootTimer,用于控制 AI 行为节奏。

3.4 碰撞检测

采用 AABB(轴对齐包围盒)检测,一个函数搞定所有碰撞:

function overlap(ax, ay, aw, ah, bx, by, bw, bh) {
  return ax < bx + bw && ax + aw > bx 
      && ay < by + bh && ay + ah > by;
}

这个函数被复用于:

  • 坦克 vs 墙壁(移动前检测)
  • 坦克 vs 坦克(防止重叠)
  • 子弹 vs 墙壁(子弹销毁)
  • 子弹 vs 坦克(命中判定)

3.5 敌方 AI

敌方坦克的 AI 逻辑非常简单,但效果不错:

function updateEnemy(e) {
  // 1. 定时换方向
  e.changeDirTimer--;
  if (e.changeDirTimer <= 0) {
    e.dir = (Math.random() * 4) | 0;  // 随机方向
    e.changeDirTimer = 30 + ((Math.random() * 60) | 0);
  }
  
  // 2. 撞墙了也换方向
  if (!e.tryMove(e.dir)) {
    e.dir = (Math.random() * 4) | 0;
  }
  
  // 3. 定时射击
  e.shootTimer--;
  if (e.shootTimer <= 0) {
    e.shoot();
    e.shootTimer = 50 + ((Math.random() * 80) | 0);
  }
}

两个随机计时器控制行为节奏:一个管换方向(30~90 帧),一个管射击(50~130 帧)。撞墙时立即换方向,避免卡死。简单但有效——玩起来敌人确实像个"有想法的对手"。

3.6 游戏循环

标准的 requestAnimationFrame 循环:

function loop() {
  update();  // 处理输入、更新位置、碰撞判定
  draw();    // 清屏、画墙、画坦克、画子弹、画 HUD
  requestAnimationFrame(loop);
}

update() 和 draw() 完全分离,逻辑清晰。

3.7 状态管理

用简单的字符串状态机控制游戏流程:

var state = 'start';  // → 'playing' → 'win' / 'gameover'
  • start:显示标题画面和"开始游戏"按钮
  • playing:正常游戏循环
  • win:全部敌人消灭,显示胜利画面
  • gameover:生命归零,显示结束画面

每个状态在 draw() 中对应不同的渲染逻辑,点击按钮调用 startGame() 重置一切。

四、发布到 GitCode 开发者作品展览馆

项目完成后,通过 GitCode API 创建公开仓库并推送代码:

仓库地址: https://gitcode.com/2301_81769094/tank-battle

发布内容包含:

  • index.html — 页面入口
  • game.js — 游戏逻辑
  • README.md — 项目说明

整个过程通过 DevSpace 连接器的 GitCode API 完成,无需手动操作 Git 命令行。

五、总结与思考

这个项目的核心收获:

  1. 极简不等于简陋。去掉所有装饰后,游戏的核心乐趣——移动、瞄准、躲避、击杀——反而更加纯粹。
  2. AABB 碰撞检测足够用。对于网格类游戏,不需要物理引擎,一个 overlap 函数解决所有碰撞。
  3. 随机计时器是好用的 AI 骨架。两个 Math.random() 驱动的计时器,就能让敌人表现出"巡逻 + 交火"的行为模式。
  4. 单文件部署的威力。零依赖意味着任何能跑 HTTP 服务器的地方都能部署——python3 -m http.server 一行命令即可。

完整代码已在 GitCode 开源,欢迎 Fork、修改、扩展。下一步可以尝试加入:关卡系统、道具掉落、双人对战、音效……但那就不是"极简"了。


项目仓库:https://gitcode.com/2301_81769094/tank-battle
技术栈:HTML5 Canvas + 原生 JavaScript,零依赖


【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。