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

如何在Player子类中调用主类GameManager的KeyEvents实现玩家移动

解决Player子类中按键控制移动/停止的问题

我来帮你搞定这个按键控制的难题!你当前的核心困境是:Player类没法直接获取GameManager里的实时按键状态——KeyEvent只是按键触发时的临时事件对象,不能用来持续检测按键是否处于按下状态。我们可以通过维护按键状态变量+让Player持有GameManager引用的方式解决,具体步骤如下:


步骤1:在GameManager中添加按键状态变量

首先在GameManager类的成员变量区域,添加布尔变量记录按键的按下/松开状态:

// GameManager类的成员变量区
private boolean leftPressed = false;
private boolean rightPressed = false;
// 如果需要上下移动,可额外添加upPressed、downPressed

步骤2:在KeyListener方法中更新状态

修改GameManager里的keyPressed和keyReleased方法,根据事件更新上面的布尔变量:

@Override
public void keyPressed(KeyEvent e) {
    int keyCode = e.getKeyCode();
    if (keyCode == KeyEvent.VK_LEFT) {
        leftPressed = true;
    } else if (keyCode == KeyEvent.VK_RIGHT) {
        rightPressed = true;
    }
    // 如需上下控制,在这里添加VK_UP/VK_DOWN的判断
}

@Override
public void keyReleased(KeyEvent e) {
    int keyCode = e.getKeyCode();
    if (keyCode == KeyEvent.VK_LEFT) {
        leftPressed = false;
    } else if (keyCode == KeyEvent.VK_RIGHT) {
        rightPressed = false;
    }
    // 上下控制同理
}

// 必须实现的keyTyped方法(空实现即可,我们不需要处理字符输入)
@Override
public void keyTyped(KeyEvent e) {
    // 无需任何操作
}

步骤3:让Player持有GameManager的引用

你的Enemy类已经通过构造方法接收了GameManager的引用,我们给Player也做同样的处理:

先修改Player类的构造和成员变量

public class Player {
    private GameManager gameManager; // 添加GameManager引用
    private int x, y;
    private int velX = 0; // 初始速度设为0,默认不移动
    // 你的其他成员变量(比如图片、velY等)

    // 修改构造方法,接收GameManager引用
    public Player(GameManager gameManager, int initialX, int initialY) {
        this.gameManager = gameManager;
        this.x = initialX;
        this.y = initialY;
    }

    // 你的其他方法...
}

然后修改GameManager中创建Player的代码

把原来的Player实例化代码改成:

// GameManager类中创建Player的部分
this.player = new Player(
    this, 
    this.canvasWidth - (Math.abs(rng.nextInt()) % (this.canvasWidth / 2)), 
    (Math.abs(rng.nextInt()) % this.canvasHeight)
);

步骤4:给GameManager添加按键状态的Getter方法

为了让Player能安全访问按键状态,在GameManager中添加Getter:

// GameManager类中添加
public boolean isLeftPressed() {
    return leftPressed;
}

public boolean isRightPressed() {
    return rightPressed;
}

// 如果有上下控制,添加对应的isUpPressed()、isDownPressed()
// 另外可以添加获取画布宽度的方法,用于边界检测
public int getCanvasWidth() {
    return canvasWidth;
}

步骤5:在Player的performAction中实现移动逻辑

现在就可以在Player的performAction方法里,根据按键状态设置速度,实现按下移动、松开停止:

public void performAction() {
    // 根据按键状态设置水平速度
    if (gameManager.isLeftPressed()) {
        velX = -6; // 向左移动的速度,数值可根据游戏节奏调整
    } else if (gameManager.isRightPressed()) {
        velX = 6; // 向右移动的速度
    } else {
        velX = 0; // 无按键按下时,速度归0,停止移动
    }

    // 更新玩家位置
    x += velX;

    // 可选:添加边界检测,防止玩家移出屏幕
    int playerWidth = getCurrentImage().getWidth(); // 假设你有获取玩家图片的方法
    if (x < 0) {
        x = 0;
    } else if (x > gameManager.getCanvasWidth() - playerWidth) {
        x = gameManager.getCanvasWidth() - playerWidth;
    }
}

为什么原来的方法行不通?

KeyEvent是一次性事件对象,只有在按键按下/松开的瞬间才会被创建,没法在Player的performAction循环中持续获取按键状态。我们需要用布尔变量来持续记录按键的状态,这样每一帧更新时都能检查当前的按键情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:59:14