目前我正在尝试构建一个蛇游戏作为我在java中的第一个项目,并且正在使用线程。我希望对象在到达屏幕边框时等待,然后在键输入进入时继续向另一个方向移动。 在底部我调用notify()函数但没有任何反应,并且线程继续处于wait()状态。任何帮助将不胜感激。
package com.foreverblu.snake;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class snakeobject extends JPanel{
int x = 0;
int y = 0;
int z = 0;
int a = 0;
Thread animationThread;
Thread notifyThread;
public void paintComponent(Graphics g) {
super.paintComponents(g);
this.setBackground(Color.black);
g.setColor(Color.GREEN);
g.fill3DRect(x, y, 30, 30, true);
}
public void keepGoing() {
animationThread = new Thread(create);
notifyThread = new Thread(create2);
}
Runnable create = new Runnable() {
public void run() {
synchronized(this) {
while(z>=0 || z<=3) {
if(z==2 && y>0) {
y-=30;
repaint();
try{Thread.sleep(500);} catch (Exception ex) {}
}else if(z==1 && y<=450) {
y+=30;
repaint();
try {Thread.sleep(500);} catch (Exception ex) {}
}else if(z==0 && x<=450) {
x+=30;
repaint();
try{Thread.sleep(500);} catch (Exception ex) {}
}else if(z==3 && x>0) {
x-=30;
repaint();
try{Thread.sleep(500);} catch (Exception ex) {}
}else{
notifyThread.notify();
}
}
}
}
};
Runnable create2 = new Runnable() {
public void run() {
synchronized(this) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
animationThread.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
do{try{Thread.sleep(500);} catch (Exception ex) {}
continue;
}while(a==0);
if(a==1) {
System.out.println("Notified");
a=0;
animationThread.notifyAll();
}
}
}
};
}
另一堂课: 包com.foreverblu.snake;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class snakeframe extends JFrame{
int z = 0;
snakeobject swag = new snakeobject();
public snakeframe() {
super("The Great Title");
swag.keepGoing();
swag.notifyThread.start();
swag.animationThread.start();
addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
if(swag.animationThread.getState()==Thread.State.WAITING) {
swag.a=1;
System.out.println("Swag");
}
if(swag.animationThread.getState()==Thread.State.RUNNABLE) {
System.out.println("RUNNABLE");
}
if(e.getExtendedKeyCode()==e.VK_DOWN) {
swag.z=1;
}else if(e.getExtendedKeyCode()==e.VK_UP) {
swag.z=2;
}else if(e.getExtendedKeyCode()==e.VK_LEFT) {
swag.z=3;
}else if(e.getExtendedKeyCode()==e.VK_RIGHT) {
swag.z=0;
}
}
});
add(swag);
}
}
答案 0 :(得分:0)
目前我正在尝试构建一个蛇游戏作为我在java中的第一个项目,并且正在使用线程。
你试图同时学习太多东西;
慢下来。一次带一个。
我希望对象在到达屏幕边框时等待,然后在键输入进入时通知......
这听起来不像是一个帖子。将线程专用于游戏中的每个移动对象是一个非常有限的设计选择,并且根据其状态等待不同的东西的线程听起来像一个糟糕的设计(IMO)。例如,当蛇正在移动时,我不会编写等待实时时钟的线程(即,调用sleep()
),然后在处于其他状态时等待按键。
已经有一个等待按键的线程:它被称为事件调度线程(EDT),它会在任何Swing程序中自动为您创建。并且,如果您想等待时钟(例如,为游戏中的对象制作动画),那么最好使用Swing Timer
。
您应该知道大多数 Swing方法(例如,repaint()
)可能只能从EDT中调用。只有极少数,例如可以从其他线程调用的SwingUtilities.invokeLater()
。
o.wait()
,o.notify()
和o.notifyAll()
方法是低级基元,旨在以非常特定的模式使用,以实现更高级别的同步classess。 Java标准库已在java.util.concurrent
包中定义了许多有用的同步类。任何时候你认为你想使用wait / notify,你应该先检查java.util.concurrent
中是否存在可以省去一些努力的东西。
如果您必须使用wait / notify,那么您应该阅读Oracle&#34; Guarded Blocks&#34;教程,并按照它的使用方式使用它:https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html