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

键盘输入驱动的Updater方法调用Player类绘图无响应问题求助

问题排查与修复方案

我帮你梳理下代码里的几个核心问题,这些就是导致调用Player绘图方法没反应的关键原因:

1. Player构造函数的变量覆盖陷阱

你的Player构造函数里犯了一个常见的新手错误:

public Player(int xPos, int yPos) {
    int x = xPos;
    int y = yPos;
}

这里的int x和int y是局部变量,完全覆盖了类成员的x和y,导致成员变量一直是默认值0,根本没被初始化!改成用this指代成员变量就好了:

public Player(int xPos, int yPos) {
    this.x = xPos;
    this.y = yPos;
}

2. Player的Graphics对象是空的

Player类里的Graphics g一直是null,调用drawPlayer()的时候肯定会抛出空指针异常(你可以看看控制台有没有报错)。正确的做法是把绘图需要的Graphics对象作为参数传给drawPlayer方法,而不是让Player自己持有一个g:
修改Player的drawPlayer方法:

public void drawPlayer(Graphics g) {
    g.setColor(Color.BLACK);
    g.fillRect(40*x, 40*y, 40, 40);
}

之后在Game里调用时,把当前的Graphics传进去就行:p.drawPlayer(g);

3. 游戏线程根本没跑起来

你的Game类线程实现有问题:

if (loopThread == null) {
    loopThread = new Thread();
    loopThread.start();
}

创建Thread时没有传入Runnable对象,这个线程的run方法是空的,不会执行你写的while循环!首先要让Game实现Runnable接口:

public class Game extends Applet implements Runnable {
    // ... 原有代码
}

然后创建线程时把this传进去:

loopThread = new Thread(this);

这样线程才会调用Game的run方法,循环才能正常执行。

4. 坐标系逻辑搞反了

AWT的坐标系里,左上角是(0,0),y轴是向下增长的,所以:

  • 向上移动应该是y--(y坐标减小)
  • 向下移动应该是y++(y坐标增大)
    但你的Player类里完全搞反了,修正一下:
public void goU() {
    y--;
}

public void goD() {
    y++;
}

5. 绘图逻辑的正确姿势

AWT里的update方法默认会清屏然后调用paint,你应该把绘图逻辑放在paint方法里,每次绘图前先清掉之前的图像,不然会留下轨迹。修改Game的update和paint方法:

public void update(Graphics g) {
    // 先更新玩家位置
    if(left) {
        p.goL();
        left = false;
    } else if(right) {
        p.goR();
        right = false;
    } else if(up) {
        p.goU();
        up = false;
    } else if(down) {
        p.goD();
        down = false;
    }
    // 调用paint绘图
    paint(g);
}

public void paint(Graphics g) {
    // 清屏,用背景色填充整个区域
    g.setColor(Color.WHITE);
    g.fillRect(0, 0, getWidth(), getHeight());
    // 绘制玩家
    p.drawPlayer(g);
}

另外,Game里的Graphics g成员变量完全没必要,直接用方法参数里的g就行。

6. 初始状态的小调整

你把down初始设为true,会导致程序启动就自动向下移动,如果你不需要这个初始行为,改成boolean down = false;


修复后的完整代码示例

Game类

import java.applet.Applet;
import java.awt.Color;
import java.awt.Event;
import java.awt.Graphics;

public class Game extends Applet implements Runnable {
    Thread loopThread;
    boolean left = false;
    boolean right = false;
    boolean up = false;
    boolean down = false; // 修正初始值
    Player p = new Player(0, 0);

    @Override
    public void start() {
        if (loopThread == null) {
            loopThread = new Thread(this);
            loopThread.start();
        }
    }

    @Override
    public void run() {
        Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
        while (Thread.currentThread() == loopThread) {
            try {
                // 控制帧率,约每秒60帧
                Thread.sleep(16);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            repaint(); // 触发update和paint
        }
    }

    @Override
    public void update(Graphics g) {
        // 更新玩家位置
        if (left) {
            p.goL();
            left = false;
        } else if (right) {
            p.goR();
            right = false;
        } else if (up) {
            p.goU();
            up = false;
        } else if (down) {
            p.goD();
            down = false;
        }
        paint(g);
    }

    @Override
    public void paint(Graphics g) {
        // 清屏
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, getWidth(), getHeight());
        // 绘制玩家
        p.drawPlayer(g);
    }

    @Override
    public boolean keyDown(Event e, int key) {
        if (key == Event.LEFT) {
            left = true;
        }
        if (key == Event.RIGHT) {
            right = true;
        }
        if (key == Event.UP) {
            up = true;
        }
        if (key == Event.DOWN) {
            down = true;
        }
        return true;
    }
}

Player类

import java.awt.Color;
import java.awt.Graphics;

public class Player {
    private int x;
    private int y;

    public Player(int xPos, int yPos) {
        this.x = xPos;
        this.y = yPos;
    }

    public void drawPlayer(Graphics g) {
        g.setColor(Color.BLACK);
        g.fillRect(40 * x, 40 * y, 40, 40);
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public void goL() {
        x--;
    }

    public void goR() {
        x++;
    }

    public void goU() {
        y--;
    }

    public void goD() {
        y++;
    }
}

这样修改后,你的盒子应该就能通过方向键正常移动了。虽然Applet是比较老旧的技术,但既然你偏好使用它,这些修改应该能解决你的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:54:34