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

Java版Pacman游戏碰撞异常问题求助

修复Pacman碰撞与反向移动问题的方案

咱们先拆解你遇到的问题根源,再一步步给出落地的修复方案:

1. 先修正collide()方法的低级错误

你现在的collide()方法里,处理y轴碰撞时错误地把xMovement设为0了——这会导致上下撞墙时连左右移动都被锁死,这是第一个要紧急修复的bug:

public void collide(boolean isX) {
    if (isX) { // 左右移动撞墙,只锁x轴移动
        this.xMovement = 0;
    } else { // 上下移动撞墙,锁y轴移动(之前写错成xMovement了)
        this.yMovement = 0;
    }
}

2. 改进碰撞检测逻辑:不要直接锁死移动,而是回退位置

当前的碰撞处理只是把移动设为0,但角色可能已经部分嵌入墙体,这会导致后续位置判断出错,甚至卡在角落。正确的做法是检测到碰撞时,将角色位置回退到碰撞前的合法位置,而不是直接停止移动:

修改tick()方法,先记录移动前的位置,执行移动后再检测碰撞,碰撞则回退:

public void tick() {
    if (!this.isLiving) return;
    
    // 记录移动前的合法位置
    float prevX = this.x_ord;
    float prevY = this.y_ord;
    
    // 先执行移动操作
    this.x_ord += this.xMovement;
    this.y_ord += this.yMovement;
    
    // 检测碰撞并标记方向
    boolean collidedX = false;
    boolean collidedY = false;
    
    for (Walls w : this.wallLocations) {
        // 检测x轴碰撞(左右方向)
        if ((this.x_ord + 2 == w.x_pos + 16 && this.y_ord + 4 == w.y_pos) || 
            (this.x_ord + 2 + 16 == w.x_pos && this.y_ord + 4 == w.y_pos)) {
            collidedX = true;
        }
        // 检测y轴碰撞(上下方向)
        if ((this.y_ord + 4 == w.y_pos + 16 && this.x_ord + 2 == w.x_pos) || 
            (this.y_ord + 4 + 16 == w.y_pos && this.x_ord + 2 == w.x_pos)) {
            collidedY = true;
        }
    }
    
    // 碰撞则回退位置并重置对应方向的移动
    if (collidedX) {
        this.x_ord = prevX;
        this.xMovement = 0;
    }
    if (collidedY) {
        this.y_ord = prevY;
        this.yMovement = 0;
    }
}

这样修改后,角色撞墙时会被拉回合法位置,不会卡在墙里,也为后续反向移动提供了基础。

3. 调整转向条件:允许反向移动与角落转向

当前的转向逻辑要求角色必须在(x_ord+2)%16==0和(y_ord+4)%16==0的位置才能转向,这会导致在角落或者已经撞墙时无法反向移动。我们需要允许用户输入反向方向时,即使不在对齐位置也能切换方向:

修改App.java中的draw()方法里的按键判断逻辑,新增反向输入的特殊处理:

public void draw() {
    mapDraw();
    this.player.tick();
    
    if (keyPressed) {
        // 判断是否是反向移动请求(比如当前向左,用户按向右)
        boolean isReverse = false;
        if ((this.direction == 'a' && key == 'd') || 
            (this.direction == 'd' && key == 'a') || 
            (this.direction == 'w' && key == 's') || 
            (this.direction == 's' && key == 'w')) {
            isReverse = true;
        }
        
        // 反向移动时,跳过位置对齐的限制;正常转向仍需对齐
        boolean canTurn = isReverse || ((this.player.x_ord + 2) % 16 == 0 && (this.player.y_ord + 4) % 16 == 0);
        
        if (key == 's' && this.direction != 's' && canTurn) {
            this.player.p = this.loadImage("src/main/resources/playerDown.png");
            this.player.yMovement = this.player.speed;
            this.player.xMovement = 0;
            this.direction = 's';
        } else if (key == 'w' && this.direction != 'w' && canTurn) {
            this.player.p = this.loadImage("src/main/resources/playerUp.png");
            this.player.yMovement = -this.player.speed;
            this.player.xMovement = 0;
            this.direction = 'w';
        } else if (key == 'd' && this.direction != 'd' && canTurn) {
            this.player.p = this.loadImage("src/main/resources/playerRight.png");
            this.player.xMovement = this.player.speed;
            this.player.yMovement = 0;
            this.direction = 'd';
        } else if (key == 'a' && this.direction != 'a' && canTurn) {
            this.player.p = this.loadImage("src/main/resources/playerLeft.png");
            this.player.xMovement = -this.player.speed;
            this.player.yMovement = 0;
            this.direction = 'a';
        }
    }
    
    this.player.draw(this);
}

这里的核心是新增了isReverse判断,当用户输入反向方向时,直接允许转向,不需要等待位置对齐,这样就能实现“向左走后直接向右”的反向移动。

4. 额外优化:角落碰撞的细节处理

如果角色在角落(同时触发x和y轴碰撞),上述逻辑已经能处理位置回退,再结合反向转向的允许,就能顺利从角落转向。你还可以在碰撞检测时,优先处理反向输入的移动请求,确保反向移动的优先级高于当前方向。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 20:57:52