我目前正在使用Java进行Pac-Man翻拍,我遇到了玩家移动问题。我使用KeyListener来检测何时按下W A S或D键,并将变量设置为true或false。变量是向上,向下,向左,向右。这工作正常,但“tick”方法无法识别值的变化,几乎就像有两个变量一样。例如,我将按下W键,将up设置为true。然而,在tick方法中,up不是真的。获得玩家的位置时也会发生这种情况。它只会获得播放器的第一个位置,但在我在KeyListener方法中编辑位置后,tick方法将无法识别位置是否已更改。
我还发现,当我直接从KeyListener方法移动位置并将其打印到控制台时,它可以正常工作。但是当我从tick方法打印位置时,它总是打印原始位置。如果我同时打印两个,似乎有两个变量,因为KeyListener方法将始终打印正确的值,并且tick方法将始终打印原始,但不会重置KeyListener值。
很抱歉,如果这听起来很混乱,请询问您是否需要我以不同的方式对其进行描述。
无论如何,tick方法每秒被调用60次。
有人可以帮我解决这个问题吗?感谢帮助。
这是Player的类,包含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) {
}
答案 0 :(得分:0)
我认为您需要在操作synchronized
,up
,down
和right
的方法上声明left
以避免内存一致性错误和线程干扰。
这样的事情:
public synchronized void tick(double deltaTime) {
...
}
编辑:您可能希望使用volatile声明成员,以确保keyPressed
方法中的更改发生在tick
之前。
答案 1 :(得分:0)
查看您的代码,有一部分看起来很可疑。
在Game.java
中,您创建了Player
frame.addKeyListener(new Player());
另一个Player
实例也在LevelLoader.java
Player player = new Player();
...这是触发tick
方法的那个。
它们是两个不同的对象,彼此无关(除了它们来自同一个类的事实)。更改一个对象的状态不会更改另一个对象的状态。在您的情况下发生的情况是第一个Player
实例听取按键操作但第二个实例是触发tick
方法。
您需要做的是在Game.java
中创建一个播放器实例,并将该对象传递给LevelLoader.java
(通过StateManager.java
?)而不是在LevelLoader.java
中创建另一个实例本身。