Tick方法无法识别变量

时间:2015-07-02 17:51:07

标签: java game-physics

我目前正在使用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) {

}

2 个答案:

答案 0 :(得分:0)

我认为您需要在操作synchronizedupdownright的方法上声明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中创建另一个实例本身。