Tick 方法无法识别变量变化

Tick Method not Recognizing Variable Change

我目前正在 Java 重制《吃豆人》,我遇到了玩家移动的问题。我使用 KeyListener 来检测何时按下 W A S 或 D 键,并将变量设置为真或假。变量是上、下、左、右。这工作正常,但 "tick" 方法无法识别值更改,几乎就像有两个变量一样。例如,我将按下 W 键并将 up 设置为 true。然而,在 tick 方法中,up 不是真的。获取玩家位置时也会发生这种情况。它只会获取播放器的第一个位置,但我在 KeyListener 方法中编辑位置后,tick 方法将无法识别位置已更改。

我还发现,当我直接从 KeyListener 方法移动位置并将其打印到控制台时,它可以正常工作。但是当我从 tick 方法打印位置时,它总是打印原始位置。如果我打印两者,好像有两个变量,因为 KeyListener 方法将始终打印正确的值,而 tick 方法将始终打印原始值,但不会重置 KeyListener 值。

抱歉,如果这听起来令人困惑,请询问您是否需要我以不同的方式描述它。

无论如何,tick 方法每秒被调用 60 次。

有人可以帮我解决这个问题吗?感谢帮助。

这是 Player 的 class,包含 tick 和 KeyListener 方法。

package com.graysullivan.entities;

import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.util.ArrayList;

import com.graysullivan.main.Location;

public class Player implements KeyListener {

Location pos;
private int width = 80;
private int height = 80;
private boolean up, down, left, right;

public Player() {
    pos = new Location(360, 701);
}

public void init() {
}

public void tick(double deltaTime) {
//System.out.println(pos.y);
    if(up) {
        System.out.println("up");
        pos.y--;
    } 

    if(down) {
        pos.y++;
    }

    if(left) {
        pos.x--;
    }

    if(right) {
        pos.x++;
    }
}

public void render(Graphics2D g) {
    g.fillRect((int)pos.x,(int)pos.y, 40, 40);
}

@Override
public void keyPressed(KeyEvent e) {
    int key = e.getKeyCode();

    if(key == KeyEvent.VK_W) {
        up = true;
        System.out.println(up);
    }

    if(key == KeyEvent.VK_S) {
        down = true;
    }

    if(key == KeyEvent.VK_A) {
        left = true;
    }

    if(key == KeyEvent.VK_D) {
        right = true;
    }

    if(key == KeyEvent.VK_DELETE) {
        System.exit(0);
    }

}

@Override
public void keyReleased(KeyEvent e) {
    int key = e.getKeyCode();

    if(key == KeyEvent.VK_W) {
        up = false;
    }

    if(key == KeyEvent.VK_S) {
        down = false;
    }

    if(key == KeyEvent.VK_A) {
        left = false;
    }

    if(key == KeyEvent.VK_D) {
        right = false;
    }
}

@Override
public void keyTyped(KeyEvent e) {

}

我认为您需要在操作 updownrightleft 的方法上声明 synchronized 以避免内存一致性错误和线程干扰。

像这样:

public synchronized void tick(double deltaTime) {
    ...
}

编辑:您可能希望使用 volatile 声明成员,以确保 keyPressed 方法中的更改发生在 tick.

之前

查看您的代码,有一部分看起来很可疑。

Game.java 中,您创建了 Player

的实例
frame.addKeyListener(new Player());

Player 的另一个实例也在 LevelLoader.java

中创建
Player player = new Player();

...这是触发 tick 方法的方法。

它们是两个不同的对象,彼此没有任何关系(除了它们来自同一个 class)。改变一个对象的状态不会改变另一个对象的状态。在您的情况下发生的情况是第一个 Player 实例监听按键,但第二个实例正在触发 tick 方法。

您需要做的是在 Game.java 中创建一个播放器实例并将对象传递给 LevelLoader.java(通过 StateManager.java?),而不是在 [=15] 中创建另一个实例=]本身。