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) {
}
我认为您需要在操作 up
、down
、right
和 left
的方法上声明 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] 中创建另一个实例=]本身。
我目前正在 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) {
}
我认为您需要在操作 up
、down
、right
和 left
的方法上声明 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] 中创建另一个实例=]本身。