我的目标
我是java中的多线程新手,我正在尝试创建pong。我只会在这里提供一些与问题相关的代码。
问题
我希望能够通过按空格键暂停游戏,然后再按空格键再次恢复。以下代码用于暂停游戏,但无法恢复。未来的所有按键都无法识别。好像主线程暂停了。
代码
主要类
public class MainManager {
private Ticker ticker;
private Thread tickerThread;
private boolean active;
public MainManager() {
ticker = new Ticker(this,10);
tickerThread = new Thread(ticker);
tickerThread.start();
}
public synchronized void tick() {
// Does necesary things for each game tick
}
public void toggleState() {
if (this.active) {
ticker.pause();
} else {
this.setActive(true);
notify();
}
}
public void setActive(boolean b) {
this.active = b;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
MainManager manager = new MainManager();
}
});
}
}
Ticker Class
public class Ticker implements Runnable {
private MainManager manager;
private int tick;
public Ticker(MainManager manager,int tick) {
this.manager = manager;
this.tick = tick;
}
@Override
public void run() {
manager.setActive(true);
while (true) {
try {
Thread.sleep(this.tick);
} catch (InterruptedException e) {
e.printStackTrace();
}
manager.tick();
}
}
public void setTickSpeed(int speed) {
this.tick = speed;
}
public synchronized void pause() {
synchronized(manager) {
try {
System.out.println("Waiting for Manager");
manager.setActive(false);
manager.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
KeyListener类
注意: 此类添加到在MainManager构造函数内构造的JFrame中。如果这个JFrame类对我的问题很重要,我会发布代码,让我知道
public class KeyboardListener implements KeyListener {
private MainManager manager;
public KeyboardListener(MainManager manager) {
this.manager = manager;
}
@Override
public void keyPressed(KeyEvent e) {
System.out.println("KeyPressed);
//This line only prints on the first spacebar.
//After the game is paused, it never prints again. Despite me spamming spacebar
if (e.getKeyCode() == KeyEvent.VK_SPACE) {
manager.toggleState();
}
}
}
如何通过按键让tickerThread
暂停和恢复?任何其他批评都是受欢迎的。
答案 0 :(得分:2)
你从未离开过Swing Event Dispatch Thread。
你的股票代码正在另一个线程中快速地打勾,工作正常。但是,如果我们按照您的切换调用的路径,它永远不会到达另一个线程。
你的太空键被按下了 - > Swing EDT巫术 - > keyPressed-> manager.toggleState() - > ticker.pause()现在我们与Manager同步,这并不困难。我们还在主线上!然后我们等。
按下空格键 - > Swing EDT暂停。您在另一个线程中运行的自动收报机的唯一部分是run方法。
您希望运行与您的游戏逻辑关闭 EDT相关的所有内容。在与JFrame和事件处理程序不同的线程中运行MainManager和Ticker,并同步或使用锁定的布尔值将数据从IO线程发送到逻辑线程。