我正在做一个项目,在这个项目中我创建了一个简单的乒乓球游戏。如果玩家赢了,我希望弹出一个JOptionPane询问用户是想玩新游戏还是停止游戏。当我添加JOptionPane时,该方法不会等待用户选择按钮,而是继续运行并继续创建JOptionPane,直到它返回堆栈溢出错误。控制它的代码是
int rightMinLeft = Right_Player_Score.getNumber()-Left_Player_Score.getNumber();
boolean rightWon = Right_Player_Score.getNumber() > 20 && rightMinLeft > 1;
if(rightWon)
{
Object[] options = {"New Game", "Finish"};
int i = JOptionPane.showOptionDialog(null, "Right Player has won", "Game Over", JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE, null, options, options[0]);
if(i == 0)
{
reset();
}
else
{
GameOver = true;
}
}
else if(Left_Player_Score.getNumber() > 20 && Left_Player_Score.getNumber()-Right_Player_Score.getNumber()>1)
{
Object[] options = {"New Game", "Finish"};
int i = JOptionPane.showOptionDialog(null, "Right Player has won", "Game Over", JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE, null, options, options[0]);
if(i == 0)
{
reset();
}
else
{
GameOver = true;
}
}
有什么建议吗?
编辑:下面是完整的方法:
public void update(Graphics window)
{
paint(window);
}
public void paint(Graphics window)
{
try{
if(pause)
{
Right_Player_Score.draw("Right Player Score", window, 600, 20);
Left_Player_Score.draw("Left Player Score", window, 0, 20);
leftPaddle.draw(window);
rightPaddle.draw(window);
if(U.LELatch(keys[4]))
{
pause = false;
}
}
else
{
ball.moveAndDraw(window);
leftPaddle.draw(window);
Right_Player_Score.draw("Right Player Score", window, Color.WHITE, 600, 20);
Left_Player_Score.draw("Left Player Score", window, Color.WHITE, 0, 20);
int LeftPaddleBottom = leftPaddle.getY()+(leftPaddle.getHeight());
int RightPaddleBottom = rightPaddle.getY()+(rightPaddle.getHeight());
int LeftPaddleTop = leftPaddle.getY();
int RightPaddleTop = rightPaddle.getY();
boolean inRangeLeft = ball.getY() > LeftPaddleTop && ball.getY() < LeftPaddleBottom;
boolean inRangeRight = ball.getY() > RightPaddleTop && ball.getY() < RightPaddleBottom;
if(ball.getX()<=10)
{
ball.setXSpeed(-ball.getXSpeed());
Right_Player_Score.increment();
}
else if(ball.getX()>=790)
{
ball.setXSpeed(-ball.getXSpeed());
Left_Player_Score.increment();
}
else if((inRangeLeft && ball.getX()<=leftPaddle.getX()+leftPaddle.getWidth()))
{
ball.setXSpeed(-ball.getXSpeed());
numTimes ++;
}
else if(inRangeRight && ball.getX()>=rightPaddle.getX())
{
ball.setXSpeed(-ball.getXSpeed());
numTimes ++;
}
if(!(ball.getY()>=10 && ball.getY()<=450))
{
ball.setYSpeed(-ball.getYSpeed());
}
if(keys[0] == true)
{
leftPaddle.moveUpAndDraw(window);
}
else if(keys[1] == true)
{
leftPaddle.moveDownAndDraw(window);
}
else
{
leftPaddle.draw(window);
}
if(keys[2] == true)
{
rightPaddle.moveUpAndDraw(window);
}
else if(keys[3] == true)
{
rightPaddle.moveDownAndDraw(window);
}
else
{
rightPaddle.draw(window);
}
int rightMinLeft = Right_Player_Score.getNumber()-Left_Player_Score.getNumber();
boolean rightWon = Right_Player_Score.getNumber() > 20 && rightMinLeft > 1;
if(rightWon)
{
Object[] options = {"New Game", "Finish"};
int i = JOptionPane.showOptionDialog(frame, "Right Player has won", "Game Over", JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE, null, options, options[0]);
//window.setColor(Color.BLACK);
//window.drawString("Right Player has won",200,400);
//Thread.currentThread().sleep(2000);
//int i = 1;
if(i == 0)
{
reset();
}
else
{
GameOver = true;
}
}
else if(Left_Player_Score.getNumber() > 20 && Left_Player_Score.getNumber()-Right_Player_Score.getNumber()>1)
{
Object[] options = {"New Game", "Finish"};
int i = JOptionPane.showOptionDialog(frame, "Left Player has won", "Game Over", JOptionPane.DEFAULT_OPTION, JOptionPane.PLAIN_MESSAGE, null, options, options[0]);
//window.setColor(Color.BLACK);
//window.drawString("Left Player has won",200,400);
//Thread.currentThread().sleep(2000);
//int i = 1;
if(i == 0)
{
reset();
}
else
{
GameOver = true;
}
}
Right_Player_Score.draw("Right Player Score", window, 600, 20);
Left_Player_Score.draw("Left Player Score", window, 0, 20);
if(numTimes == 10)
{
numTimes = 0;
if(ball.getXSpeed() == Math.abs(ball.getXSpeed()))
{
ball.setXSpeed(ball.getXSpeed() + 1);
}
else
{
ball.setXSpeed(ball.getXSpeed() - 1);
}
if(ball.getXSpeed()>MAXSPEED)
{
ball.setXSpeed(MAXSPEED);
}
}
pause = U.LELatch(keys[4]);
}
}
catch(Exception e)
{
}
}
这是用在"公共类GUI_Controller extends Canvas implements KeyListener, Runnable"
注意:注释部分是让用户至少看到一些东西的权宜之计。
您看到的行为是因为您重载了paint(Graphics g)
方法。
来自paint(Graphics g)
JavaDoc
该方法在需要绘制组件内容时调用;这样的当组件第一次被展示或损坏和需要时修复。
在您的情况下,可能发生的情况是对JOptionPane.showOptionDialog()
的调用导致JDialog
显示在您的Canvas
之上,从而触发对paint()
的另一个调用。这反过来导致另一个调用JOptionPane.showOptionDialog()
触发另一个调用paint()
,等等…这将继续,直到您得到StackOverflowError
或OutOfMemoryError
。
在实践中,paint()
被频繁调用,所以它应该是非常有效的。通常只有您的自定义绘图应该在paint()
方法中完成。
其他逻辑应该存在于不同的方法中。您应该将评分和用户交互的逻辑移到paint()
方法之外,只保留绘图。
Edit: 在没有看到更多代码的情况下,我不能给你一个具体的建议,告诉你在哪里移动与绘画不直接相关的逻辑。您可能会发现,回顾一下Java Swing教程中关于执行自定义绘画的部分会有所帮助。
将JOptionPane
作为您当前帧的第一个参数而不是null
可能会有所帮助。