简体   繁体   English

刻度线方法不能识别变量变化

[英]Tick Method not Recognizing Variable Change

I am currently working on a Pac-Man remake in Java, and I am having a problem with player movement. 我目前正在用Java进行吃豆人翻拍,但播放器移动存在问题。 I use a KeyListener to detect when the WAS or D keys are pressed, and sets a variable as true or false. 我使用KeyListener来检测何时按下WAS或D键,并将变量设置为true或false。 The variables are up, down, left, right. 变量为上,下,左,右。 This works fine, but the "tick" method does not recognize the value change, almost as if there are two variables. 这可以正常工作,但是“ tick”方法无法识别值变化,几乎就像有两个变量一样。 For example, I will press the W key and up is set to true. 例如,我将按W键并将up设置为true。 In the tick method, however, up is not true. 但是,在滴答方法中,up不是正确的。 This also happens when getting the position of the player. 获取玩家位置时也会发生这种情况。 It will only get the first position of the player, but after I edit the position in the KeyListener method, the tick method will not recognize that the position has been changed. 它只会获得播放器的第一个位置,但是在KeyListener方法中编辑位置后,tick方法将无法识别该位置已更改。

I have also found that when I move the position directly from the KeyListener method and print it to the console, it works correctly. 我还发现,当我直接从KeyListener方法移动位置并将其打印到控制台时,它可以正常工作。 But when I print the position from the tick method, it always prints the original position. 但是,当我从tick方法打印位置时,它始终会打印原始位置。 If I print both, it seems as if there are two variables, because the KeyListener method will always print the correct value, and the tick method will always print the original, but does not reset the KeyListener value. 如果同时打印两个变量,则好像有两个变量,因为KeyListener方法将始终打印正确的值,而tick方法将始终打印原始值,但不会重置KeyListener值。

Sorry if this sounds confusing, please ask if you need me to describe it in a different way. 抱歉,这听起来令人困惑,请询问是否需要我以其他方式描述它。

Anyway, the tick method is being called 60 times every second. 无论如何,滴答方法每秒被调用60次。

Can someone please help me fix this problem? 有人可以帮我解决这个问题吗? Help is appreciated. 感谢帮助。

Here is the class for the Player, containing the tick and KeyListener methods. 这是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) {

}

I think what you need is to declare synchronized on the method which manipulate up , down , right , and left to avoid memory consistency error and thread interference. 我认为您需要在操作updownrightleft的方法上声明synchronized ,以避免内存一致性错误和线程干扰。

Something like this: 像这样:

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

Edit: you might want to declare the members with volatile to ensure that the changes in keyPressed method happens before the tick . 编辑:您可能想用volatile声明成员,以确保keyPressed方法中的更改发生在tick之前。

Looking at your code, there is a part that look suspicious. 查看您的代码,其中一部分看起来可疑。

In Game.java you created an instance of Player Game.java您创建了Player的实例

frame.addKeyListener(new Player());

Another instance of Player is also created in LevelLoader.java LevelLoader.java也创建了Player另一个实例。

Player player = new Player();

...which is the one that getting the tick method triggered. ...这是触发tick方法的方法。

They are two different objects which has nothing to do with each other (other than the fact that they are from the same class). 它们是两个彼此无关的对象(除了它们来自同一类之外)。 Changing a state of one object doesn't change the state of another. 更改一个对象的状态不会更改另一个对象的状态。 What happen in your case is that the first Player instance listen to key press but the second instance is getting the tick method triggered. 您遇到的情况是,第一个Player实例监听按键,但是第二个实例触发了tick方法。

What you need to do is to create a player instance in Game.java and pass the object to LevelLoader.java (via StateManager.java ?) instead of creating another instance in LevelLoader.java itself. 您需要做的是在Game.java创建一个玩家实例,然后将该对象传递给LevelLoader.java (通过StateManager.java ?),而不是在LevelLoader.java本身中创建另一个实例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM