You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java原生Pac-Man游戏中间墙体精准碰撞检测问题求助

解决Pac-Man精准碰撞检测问题的方案

原代码的核心问题

  1. 仅检测目标位置对应的单个tile,忽略了角色碰撞盒可能覆盖多个tile的情况,导致部分墙体未被识别,出现轻微穿墙。
  2. 边界计算逻辑冗余且不准确,未基于角色实际碰撞范围做判断。
  3. 移动时直接跳步到速度叠加后的位置,未处理“不可移动时精准停在墙前”的逻辑。

修正后的碰撞检测方案

1. 基于碰撞盒的canMove函数

角色是有体积的,需检测碰撞盒覆盖的所有tile是否均可通行。以下是修正后的函数:

// 31行,28列的地图
public static boolean canMove(int centerX, int centerY, String direction) {
    int tileSize = 16;
    // 设置碰撞盒半宽高:比tile半尺寸小2,避免卡墙且贴合原版手感
    int collisionHalf = 6;
    // 计算碰撞盒的四个边界
    int left = centerX - collisionHalf;
    int right = centerX + collisionHalf;
    int top = centerY - collisionHalf;
    int bottom = centerY + collisionHalf;

    // 先判断碰撞盒是否超出地图整体边界
    if (left < 0 || right >= tileSize * 28 || top < 0 || bottom >= tileSize * 31) {
        return false;
    }

    // 获取碰撞盒覆盖的所有tile的行列范围
    int startRow = top / tileSize;
    int endRow = bottom / tileSize;
    int startCol = left / tileSize;
    int endCol = right / tileSize;

    // 遍历所有覆盖的tile,只要有一个不可通行就返回false
    for (int row = startRow; row <= endRow; row++) {
        for (int col = startCol; col <= endCol; col++) {
            // 防止行列越界
            if (row < 0 || row >= 31 || col < 0 || col >= 28) {
                return false;
            }
            // 仅1、3、4为可通行tile
            if (map[row][col] != 1 && map[row][col] != 3 && map[row][col] != 4) {
                return false;
            }
        }
    }
    return true;
}

2. 精准停墙的移动逻辑

不能直接禁止移动,而是当检测到不可移动时,将角色定位到墙体边缘:

int speed = 4;
int tileSize = 16;
int collisionHalf = 6;
int currentX = // 角色当前X坐标
int currentY = // 角色当前Y坐标

switch(direction) {
    case "LEFT":
        int newXLeft = currentX - speed;
        if (canMove(newXLeft, currentY, direction)) {
            currentX = newXLeft;
        } else {
            // 计算左侧墙体的右侧边缘,将角色贴墙放置
            int currentCol = currentX / tileSize;
            currentX = currentCol * tileSize + (tileSize - collisionHalf);
        }
        break;
    case "RIGHT":
        int newXRight = currentX + speed;
        if (canMove(newXRight, currentY, direction)) {
            currentX = newXRight;
        } else {
            int currentCol = currentX / tileSize;
            currentX = (currentCol + 1) * tileSize - collisionHalf;
        }
        break;
    case "UP":
        int newYUp = currentY - speed;
        if (canMove(currentX, newYUp, direction)) {
            currentY = newYUp;
        } else {
            int currentRow = currentY / tileSize;
            currentY = currentRow * tileSize + (tileSize - collisionHalf);
        }
        break;
    case "DOWN":
        int newYDown = currentY + speed;
        if (canMove(currentX, newYDown, direction)) {
            currentY = newYDown;
        } else {
            int currentRow = currentY / tileSize;
            currentY = (currentRow + 1) * tileSize - collisionHalf;
        }
        break;
}

关键逻辑说明

  • 碰撞盒覆盖所有可能接触的tile,彻底避免漏检墙体。
  • 移动时优先尝试完整速度位移,不可行时计算墙体边缘坐标,让角色精准停在墙前,消除穿墙现象。
  • 碰撞盒尺寸留有余量,避免角色被墙体卡住,同时贴合原版Pac-Man的移动手感。

内容的提问来源于stack exchange,提问作者user22495401

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 22:42:10