文章配图:碰撞检测与重力下落

页面预览

前言

在「猫猫大作战」中,猫咪从棋盘顶部落下,碰到已停落的猫咪或棋盘底部时停止。碰撞检测决定了猫咪的下落路径和最终位置,是物理模拟的核心。

一、重力下落

private readonly GRAVITY_SPEED = 1;  // 每帧下落 1 行

updateCatPosition(cat: Cat): void {
  if (!cat.falling) return;

  const targetY = this.findLandingY(cat.x, cat.y);
  if (cat.y < targetY) {
    cat.y += this.GRAVITY_SPEED;  // 下落
  } else {
    cat.falling = false;  // 着陆
  }
}

二、碰撞检测算法

private findLandingY(x: number, startY: number): number {
  // 从 startY 开始向下查找第一个空位
  for (let y = startY; y < GameConfig.BOARD_HEIGHT; y++) {
    if (this.board[y][x] !== null) {
      return y - 1;  // 被挡住,停在上一行
    }
  }
  return GameConfig.BOARD_HEIGHT - 1;  // 到底部
}

// 水平碰撞(合并检测)
private findSameLevelNeighbors(x: number, y: number, level: CatLevel): { x: number; y: number }[] {
  const neighbors: { x: number; y: number }[] = [];
  const directions = [[-1,0], [1,0], [0,-1], [0,1]];  // 上下左右

  for (const [dx, dy] of directions) {
    const nx = x + dx;
    const ny = y + dy;
    if (nx >= 0 && nx < 5 && ny >= 0 && ny < 8) {
      const cat = this.board[ny][nx];
      if (cat && cat.level === level) {
        neighbors.push({ x: nx, y: ny });
      }
    }
  }
  return neighbors;
}

三、配置参数

参数说明
GRAVITY_SPEED1每 100ms 下落 1 行
BOARD_WIDTH5棋盘宽度(列)
BOARD_HEIGHT8棋盘高度(行)
CELL_SIZE60vp每格像素大小
UPDATE_INTERVAL100ms物理更新周期

四、四种碰撞场景

场景检测结果行为
底部空y === HEIGHT-1停在底部
下方有猫board[y+1][x] !== null停在当前行
左右同级邻居 level 相同触发合并
已在行内board[y][x] !== null游戏结束

五、优化建议

  1. 从下往上扫描:碰撞检测从下往上更快
  2. 缓存落点:同一列多次计算落点时缓存结果
  3. 只更新移动中的猫咪:已着陆的猫跳过物理计算

总结

碰撞检测通过从当前位置向下查找空位,确定猫咪的最终着陆位置。核心要点:findLandingY 查找落点、 GRAVITY_SPEED=1 逐行下落、 四方向邻居检测合并、 着陆后 falling=false

如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!


相关资源:

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐