我正在编写一个突破游戏,除一件小事外,其他一切都正常。
我有一个从线程和RepainterThread扩展的球对象,该对象可以实现Runnable或扩展Thread,后者调用paint方法,该方法使用砖块,球拍和Ball重新渲染游戏领域
我有一个连接所有东西的Singelton GameController。
我有一个带有isActive布尔值的GameState来决定是否应该暂停游戏。
我开始游戏,我可以玩,程序的行为应达到预期。 当球碰到一切都很好时,框架被吸引,球移动砖块破裂。
然后,我通过将“活动”设置为“假”的按钮暂停游戏。 球停了,应该停下来。然后,我点击继续按钮,isActive再次成立。球对象再次开始运行,并且重新触发了Repainter Thread的运行方法,但“摆动框架”完全冻结。
我尝试了各种方法,这些是我最近的方法。
我花了几天时间来帮助
public class Ball extends MovingObject {
private double hSpeed; // Horizontal velocity
private double vSpeed; // Vertical velocity
public Ball() {
this.color = Color.MAGENTA;
this.height = GameSettings.ballSize;
this.width = GameSettings.ballSize;
this.position = new Point2D.Double(GameSettings.defaultBallX, GameSettings.defaultBallY);
this.hSpeed = GameSettings.ballHSpeed;
this.vSpeed = GameSettings.ballYSpeed;
}
public Ball(Ball ball) {
color = ball.color;
height = ball.height;
width = ball.width;
position = ball.position;
hSpeed = ball.hSpeed;
vSpeed = ball.vSpeed;
}
public double getHSpeed() {
return this.hSpeed;
}
public double getVSpeed() {
return this.vSpeed;
}
public void run() {
try {
while (GameController.getInstance().getGameState().isActive()) {
System.out.println("Ich run im Ball");
Thread.sleep(10);
this.meetingWall();
this.meetingBrick();
this.position.setLocation(this.getPosition().getX() + this.hSpeed,
this.getPosition().getY() + this.vSpeed);
if (this.meetingPaddle()) {
this.newDirection();
}
if (this.out()) {
GameController.getInstance().stopGame();
this.stopThread();
}
this.position = this.getPosition();
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void stopThread() {
GameController.getInstance().getGameState().setActive(false);
}
public void startThreadAgain() {
this.run();
}
@Override
public synchronized void start() {
this.position.setLocation(GameSettings.defaultBallX, GameSettings.defaultBallY);
super.start();
}
class GamePanel extends JPanel {
private static final long serialVersionUID = 1L;
private final Color backgroundColor = Color.BLACK;
GameState gameState = GameController.getInstance().getGameState();
public GamePanel() {
super();
this.addKeyListener(new KeyListener() {
// Dieser KeyListener soll auf Inputs der Pfeiltasten nach links
// <- und rechts -> hoeren und eine entsprechende Bewegung des
// Schlaegers erwirken, aber nur, wenn das Spiel nicht
// pausiert/gestoppt ist.
public void keyPressed(KeyEvent keyEvent) {
if (gameState.isActive()) {// gameState.isActive()
if (keyEvent.getKeyCode() == KeyEvent.VK_RIGHT) {
gameState.getPaddle().setPositionRigth();
}
if (keyEvent.getKeyCode() == KeyEvent.VK_LEFT) {
gameState.getPaddle().setPositionLeft();
}
}
}
public void keyReleased(KeyEvent keyEvent) {
// TODO
}
public void keyTyped(KeyEvent arg0) {
}
});
}
public void paint(Graphics g) {
Graphics2D graphics2D = (Graphics2D) g;
graphics2D.setColor(this.backgroundColor);
graphics2D.fillRect(0, 0, this.getWidth(), this.getHeight());
for (int i = 0; i < gameState.getBricks().length; i++) {
for (int j = 0; j < gameState.getBricks()[i].length; j++) {
if ((gameState.getBricks()[i][j] != null)) {
graphics2D.setColor(gameState.getBricks()[i][j].getColor());
graphics2D.fillRect(
(i * GameSettings.brickWidth) + (i + 1) * (GameSettings.spaceAroundBrick + 1),
(j * GameSettings.brickHeight) + (j + 1) * GameSettings.spaceAroundBrick,
GameSettings.brickWidth, GameSettings.brickHeight);
}
scoreLabel.setText(this.gameState.getScore() + "");
gameState.getPaddle().draw(graphics2D);
gameState.getBall().draw(graphics2D);
}
}
}
}
// First Approach
private class RepainterThread implements Runnable {
public RepainterThread() {
System.out.println("RepainThreadCOntructor");
}
private void updateGUI() {
System.out.println("before invoke later");
System.out.println("repaint");
getGamePanel().requestFocus();
getGamePanel().repaint();
}
@Override
public void run() {
System.out.println("Repainter run");
System.out.println(GameController.getInstance().getGameState().isActive());
while (GameController.getInstance().getGameState().isActive()) {
System.out.println("inside while");
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
updateGUI();
}
}
}
// Second Approach
private class RepainterThread implements Runnable {
public RepainterThread() {
System.out.println("RepainThreadCOntructor");
}
private void updateGUI(){
SwingUtilities.invokeLater(new Runnable() {
public void run() {
System.out.println("repaint");
getGamePanel().requestFocus();
getGamePanel().repaint();
}
});
}
@Override
public void run() {
System.out.println("Repainter run");
System.out.println(GameController.getInstance().getGameState().isActive());
while (GameController.getInstance().getGameState().isActive()) {
System.out.println("inside while");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
updateGUI();
}
}
}
框架不再冻结
请帮助
答案 0 :(得分:1)
这是一个疯狂的猜测,但是由于根据您的描述,程序可以正常工作,直到您暂停并取消暂停它为止,问题可能出在startThreadAgain
方法上:
public void startThreadAgain() {
this.run();
}
您的代码没有显示如何调用此方法,但是在该方法中您只是调用this.run()
,即您将run
方法作为常规的阻塞方法进行调用,而可能仍在UI线程中。相反,您应该调用start()
以启动执行run
方法的适当的新线程。
public void startThreadAgain() {
super.start(); // not this start, otherwise it resets the ball's location
}