YonderHiker

tank-battle

网页版秒玩解压小游戏

0.99

已售 0
25.92KB

数据标识:D17780526165042497

发布时间:2026/05/06

# 坦克大战 (Tank Battle) - 数据描述

## 1. 画布与渲染常量

| 常量名 | 值 | 说明 |
|--------|-----|------|
| COLS | 13 | 棋盘列数 |
| ROWS | 13 | 棋盘行数 |
| TILE | 40 | 每格像素大小 |
| HALF_TILE | 20 | 半格像素大小(TILE / 2) |

画布实际像素尺寸 = 13 × 40 = 520px × 520px

---

## 2. 地图图块类型

| 常量名 | 值 | 含义 | 可被子弹摧毁 |
|--------|-----|------|-------------|
| TILE_EMPTY | 0 | 空地 | - |
| TILE_BRICK | 1 | 砖墙 | ✅ 是 |
| TILE_STEEL | 2 | 钢墙 | ❌ 否 |
| TILE_BASE | 3 | 基地(大本营) | ✅ 是(基地被毁 → 游戏失败) |

### 图块渲染颜色

| 图块类型 | 主要颜色 | 辅助颜色 |
|----------|----------|----------|
| 砖墙 (TILE_BRICK) | #b5651d(棕色) | #8b4513(深棕十字线)、#6b3410(边框) |
| 钢墙 (TILE_STEEL) | #808080 / #b0b0b0 / #606060(三层灰度渐变) | - |
| 基地 (TILE_BASE) | #222(深色背景) | #ffd700(金色三角鹰徽)、#ffeb3b(亮黄圆心) |

---

## 3. 方向常量

| 常量名 | 值 | 数学角度 (rad) | 方向 |
|--------|-----|----------------|------|
| DIR_UP | 0 | -π/2 (−90°) | 上 |
| DIR_RIGHT | 1 | 0 (0°) | 右 |
| DIR_DOWN | 2 | π/2 (90°) | 下 |
| DIR_LEFT | 3 | π (180°) | 左 |

方向值对应车身旋转角度:direction × (π/2)

---

## 4. 全局游戏状态

| 变量名 | 类型 | 初始值 | 说明 |
|--------|------|--------|------|
| map | number[][] | [] | 13×13 棋盘数据,存储图块类型编号 |
| player | object | null | 玩家坦克对象 |
| enemies | object[] | [] | 活跃敌人坦克数组 |
| bullets | object[] | [] | 活跃子弹数组 |
| score | number | 0 | 当前累计分数 |
| lives | number | 3 | 玩家剩余生命数 |
| level | number | 1 | 当前关卡编号(从 1 开始) |
| totalEnemies | number | 20 | 本关敌人总数 |
| enemiesRemaining | number | 20 | 本关剩余敌人数 |
| enemiesSpawned | number | 0 | 已生成的敌人数量 |
| enemiesActive | number | 0 | 当前存活的敌人数量 |
| maxActiveEnemies | number | 4 | 同时在场上的敌人数量上限 |
| gameOver | boolean | false | 游戏是否结束 |
| gamePaused | boolean | false | 游戏是否暂停 |
| gameState | string | '' | 游戏结局状态:'playing' / 'win' / 'lose' |
| animationId | number | null | requestAnimationFrame 返回的 ID |
| isPlayerInvincible | boolean | false | 玩家是否处于无敌状态(受伤后短暂无敌) |
| invincibleTimer | number | 0 | 无敌剩余帧数(每帧 −1,归零后取消无敌) |

---

## 5. 输入状态

### 5.1 键盘输入

| 变量名 | 类型 | 说明 |
|--------|------|------|
| keys | object | 按键状态字典,keydown 设为 truekeyup 设为 false |

支持的按键:

| 按键 | 功能 |
|------|------|
| ArrowUp / w / W | 向上移动 |
| ArrowDown / s / S | 向下移动 |
| ArrowLeft / a / A | 向左移动 |
| ArrowRight / d / D | 向右移动 |
| Space(空格) | 发射子弹 |
| p / P | 暂停 / 继续 |
| r / R | 重新开始 |

### 5.2 鼠标输入

| 变量名 | 类型 | 初始值 | 说明 |
|--------|------|--------|------|
| mouseX | number | 0 | 鼠标在 Canvas 内的 X 坐标 |
| mouseY | number | 0 | 鼠标在 Canvas 内的 Y 坐标 |
| mouseOnCanvas | boolean | false | 鼠标是否在 Canvas 区域内 |
| mouseClickPending | boolean | false | 是否有待处理的鼠标点击射击 |

---

## 6. 射击冷却时间

| 常量名 | 值(毫秒) | 说明 |
|--------|-----------|------|
| PLAYER_SHOT_COOLDOWN | 400 | 玩家两次射击的最小间隔 |
| ENEMY_SHOT_COOLDOWN | 1200 | 敌人基础射击间隔(实际会加随机偏移 Math.random() × 800ms,即 1200~2000ms) |
| lastPlayerShot | 0(初始) | 上次玩家射击的时间戳(Date.now()) |

---

## 7. 实体数据结构

### 7.1 玩家坦克 (player)

js
{
    x: number,        // 中心 X 坐标(像素),初始 = 4.5 × TILE = 180
    y: number,        // 中心 Y 坐标(像素),初始 = 12.5 × TILE = 500
    direction: 0|1|2|3,  // 车身朝向(DIR_UP/DIR_RIGHT/DIR_DOWN/DIR_LEFT),初始 = DIR_UP(0)
    speed: 3,         // 移动速度(像素/帧)
    size: 16,         // 碰撞半径(像素)
    alive: boolean,   // 是否存活
}

初始生成位置:第 4 列、第 12 行的格子中心 (180, 500)

玩家坦克渲染颜色:
- 车身外框:#4caf50(绿色)
- 车身内层:darken(#4caf50, 30)#2e7d32
- 炮塔:#4caf50(绿色,尺寸 14×6px),朝向鼠标位置
- 中心圆:#111

### 7.2 敌人坦克 (enemies[i])

js
{
    x: number,            // 中心 X 坐标(像素)
    y: number,            // 中心 Y 坐标(像素)
    direction: 0|1|2|3,  // 移动方向,初始 = DIR_DOWN(2)
    speed: number,        // 移动速度(像素/帧),见下方类型表
    size: 16,             // 碰撞半径(像素)
    alive: boolean,       // 是否存活
    color: string,        // 坦克颜色(十六进制),见下方类型表
    points: number,       // 击杀得分
    moveTimer: 0,         // 移动计时器(帧计数)
    moveDuration: number, // 更换方向的间隔(60 + random×60 帧)
    shotTimer: 0,         // 射击计时器(帧计数)
}

#### 敌人类型表

| 类型 | 速度 | 颜色 | 得分 |
|------|------|------|------|
| 轻型坦克 | 1.2 | #aaa(灰色) | 100 |
| 快速坦克 | 1.8 | #ff9800(橙色) | 200 |
| 重型坦克 | 1.2 | #ff5252(红色) | 300 |
| 精英坦克 | 2.2 | #e040fb(紫色) | 400 |

敌人坦克渲染:
- 车身颜色:对应类型颜色
- 车身内层:darken(颜色, 30)
- 炮塔:#ff5252(红色,尺寸 14×6px),与车身方向一致
- 中心圆:#111

### 7.3 子弹 (bullets[i])

js
{
    x: number,       // 中心 X 坐标(像素)
    y: number,       // 中心 Y 坐标(像素)
    angle: number,   // 飞行方向角度(弧度),0 = 右,π/2 = 下,-π/2 = 上
    speed: number,   // 飞行速度(像素/帧),玩家=5,敌人=3.5
    size: 3,         // 碰撞半径(像素)
    isPlayer: boolean,  // true = 玩家子弹,false = 敌人子弹
    alive: boolean,  // 是否存活
}

子弹渲染颜色:
- 玩家子弹:外圈 #fff(白色),内芯 #ffeb3b(亮黄)
- 敌人子弹:外圈 #ff5252(红色),内芯 #ff8a80(浅红)

---

## 8. 关卡地图数据

游戏共有 3 张预设关卡地图,每张为 13×13 的二维数组。超过 3 关后循环复用 (level - 1) % 3

### 第 1 关地图

[0,0,0,0,0,0,0,0,0,0,0,0,0]
[0,0,0,0,0,0,0,0,0,0,0,0,0]
[0,0,1,1,0,0,1,1,0,0,1,1,0]
[0,0,1,1,0,0,1,1,0,0,1,1,0]
[0,0,1,1,0,0,0,0,0,0,1,1,0]
[0,0,0,0,0,0,1,1,0,0,0,0,0]
[0,0,0,0,0,0,1,1,0,0,0,0,0]
[0,0,0,0,0,0,0,0,0,0,0,0,0]
[0,0,0,0,0,0,0,0,0,0,0,0,0]
[0,0,1,1,0,0,0,0,0,0,1,1,0]
[0,0,1,1,0,0,1,1,0,0,1,1,0]
[0,0,0,0,0,0,1,1,0,0,0,0,0]
[0,0,0,0,0,1,3,3,1,0,0,0,0]
- 基地位置:(6, 12) 和 (7, 12) - 地图元素:仅砖墙和基地

### 第 2 关地图

[1,0,0,0,0,0,0,0,0,0,0,0,1]
[0,1,0,0,0,0,0,0,0,0,0,1,0]
[0,0,1,1,0,0,0,0,0,0,1,1,0]
[0,0,1,1,0,0,2,0,0,0,1,1,0]
[0,0,0,0,0,0,0,0,0,0,0,0,0]
[0,0,0,1,1,0,0,0,0,1,1,0,0]
[0,0,0,0,0,0,1,1,0,0,0,0,0]
[0,0,0,0,0,0,0,0,0,0,0,0,0]
[0,0,0,0,0,0,0,0,0,0,0,0,0]
[0,0,0,1,1,0,0,2,0,1,1,0,0]
[0,0,1,1,0,0,0,0,0,0,1,1,0]
[0,0,0,0,0,0,0,0,0,0,0,0,0]
[0,0,0,0,0,1,3,3,1,0,0,0,0]
- 新增元素:钢墙(2),位于 (6, 3) 和 (7, 9) - 对角砖墙形成通道

### 第 3 关地图

[0,2,0,0,0,0,0,0,0,0,0,2,0]
[0,0,0,1,1,0,0,0,0,1,1,0,0]
[0,0,0,1,1,0,1,1,0,1,1,0,0]
[0,0,0,0,0,0,1,1,0,0,0,0,0]
[0,1,1,0,0,0,0,0,0,0,1,1,0]
[0,0,0,0,0,1,1,1,1,0,0,0,0]
[0,0,0,0,0,0,0,0,0,0,0,0,0]
[0,0,0,0,0,0,0,0,0,0,0,0,0]
[0,0,1,1,0,0,0,0,0,0,1,1,0]
[0,0,1,1,0,2,0,0,2,0,1,1,0]
[0,0,0,0,0,0,1,1,0,0,0,0,0]
[0,0,0,0,0,0,0,0,0,0,0,0,0]
[0,0,0,0,0,1,3,3,1,0,0,0,0]
- 钢墙位置:(1, 0)、(11, 0)、(5, 9)、(8, 9) - 密集的砖墙布局,增加难度

---

## 9. 敌人出生点

| 索引 | 坐标 (col, row) | 像素位置 (x, y) |
|------|-------------------|-------------------|
| 0 | (0, 0) | (20, 20) |
| 1 | (6, 0) | (260, 20) |
| 2 | (12, 0) | (500, 20) |

三个出生点均在棋盘顶部(第 0 行),随机选择。

---

## 10. 关卡参数

每关的参数通过 startLevel(lvl) 设定:

| 参数 | 计算公式 | 第 1 关 | 第 2 关 | 第 3 关 |
|------|----------|---------|---------|---------|
| totalEnemies | 16 + lvl × 2 | 18 | 20 | 22 |
| maxActiveEnemies | min(6, 3 + lvl) | 4 | 5 | 6 |
| 每关开局无敌帧数 | 固定 | 90 | 90 | 90 |

---

## 11. 计分规则

| 事件 | 得分 |
|------|------|
| 击杀轻型坦克(灰) | 100 |
| 击杀快速坦克(橙) | 200 |
| 击杀重型坦克(红) | 300 |
| 击杀精英坦克(紫) | 400 |

分数实时显示在右侧面板。

---

## 12. 生命系统

| 属性 | 值 |
|------|-----|
| 初始生命数 | 3 |
| 受伤后无敌帧数 | 120 帧 |
| 受伤后重生位置 | (180, 500),朝向 DIR_UP |
| 生命归零 | 游戏失败 |

无敌状态下,坦克每 4 帧闪烁一次(交替隐藏/显示)。

---

## 13. 碰撞检测参数

### 地图碰撞
- 以坦克中心为原点,size(16px)为半径作包围盒
- 检测包围盒四个角点所在格子是否包含砖墙/钢墙/基地

### 坦克间碰撞
- 两个坦克中心距离 < sizeA + sizeB(均为 16,即 < 32px)视为碰撞

### 子弹碰撞
- 子弹与敌人:|dx| < enemy.size(16)|dy| < enemy.size(16)
- 子弹与玩家:同上
- 子弹间碰撞(仅限两发敌方子弹):|dx| < 6|dy| < 6

---

## 14. 胜利/失败条件

| 条件 | 结果 |
|------|------|
| 消灭本关所有敌人 | 进入下一关(level++) |
| 通过所有 3 关后消灭全部敌人 | 胜利 🎉 |
| 玩家生命归零 | 失败 💥 |
| 基地(TILE_BASE)被子弹击中 | 失败 💥 |

---

## 15. 敌方 AI 行为

| 行为 | 触发条件 | 说明 |
|------|----------|------|
| 直线移动 | 每帧 moveTimer++ | 朝当前方向持续前进 |
| 更换方向 | moveTimer >= moveDuration(40~120 帧) | 60%概率掉头,25%概率随机选方向,15%不动 |
| 射击 | shotTimer > 1200 + random×800 ms | 向当前 direction 方向发射子弹 |

看了又看

数据加载中

验证报告

目前该文件尚无匹配的数据质量验证程序。我们将在后续版本中提供相应的验证支持,敬请谅解。

data icon
tank-battle
0.99
已售 0
25.92KB
申请报告