我有两个使用java swing的游戏板按钮监听器。
最初创建一个tetris网格,然后在每个按钮监听器中添加功能。
我在Play.java中设置了这样的板子:
final TetrisGame g = new TetrisGame(11,1);
final BoardGraphics graphics = new BoardGraphics(TetrisBoard.BOARD_WIDTH, 40, g);
然后在同一个Play.java中创建按钮侦听器:
graphics.btnStart.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
Action arc = p.getAction(g);
g.update(arc);
graphics.colours.clear();
graphics.setColor(g.getBoard().getGrid());
while (arc instanceof Store){
arc = p.getAction(g);
g.update(arc);
graphics.colours.clear();
graphics.setColor(g.getBoard().getGrid());
}
graphics.tiles.redraw();
System.out.println();
System.out.println(g.toString());
System.out.println();
}
});
graphics.btnAuto.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
while (!g.gameEnded()){
Action arc = p.getAction(g);
g.update(arc);
graphics.colours.clear();
graphics.setColor(g.getBoard().getGrid());
while (arc instanceof Store){
arc = p.getAction(g);
g.update(arc);
//graphics.colours.clear();
graphics.setColor(g.getBoard().getGrid());
}
graphics.tiles.redraw();
System.out.println();
System.out.println(g.toString());
System.out.println();
/*try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}*/
}
}
});
btnStart工作正常,按下一次,根据AI代理给出的下一步动作绘制tetrisboard。
我希望btnAuto能够在没有用户按下btnStart的情况下播放每个移动,直到结束。但是,我的btnAuto不会在网格上绘制任何东西,而是游戏的最终状态,即完成状态。
有人可以看到为什么在while循环中生成每个移动后,这可能不会重新绘制网格吗?
答案 0 :(得分:3)
在Swing事件线程上调用了while循环,因此阻止线程执行必要的操作,包括呈现GUI并与用户交互:
while (!g.gameEnded()){
Action arc = p.getAction(g);
// ....
}
我会在这里使用Swing Timer而不是while (true)
循环。另一种选择是使用后台线程,但是因为你想要的只是一个非常简单的游戏循环而且不需要在后台运行一些长时间运行,我认为第二种选择会更复杂,没有额外的好处。
顺便说一句,我很好奇你是如何做你的绘图以及你如何让你的Graphics对象绘制的。您没有在某个组件上调用getGraphics()
,是吗?
编辑您在评论中说明:
我目前有一个带有嵌套类的类,它扩展了JPanel。 grid和getGraphics()的绘制是在嵌套类中完成的。父类创建组件并将GUI的布局设置为一个整体
不要通过在GUI组件上调用getGraphics()
来获取Graphics对象,因为获得的Graphics对象不会持久存在。要看到这一点,只需最小化然后恢复您的应用程序,并告诉我在执行此操作后图形会发生什么。你应该在JPanel的paintComponent覆盖中完成所有绘图。一种选择是在BufferedImage上调用getGraphics()
并使用它绘制到BufferedImage,然后在paintComponent覆盖中显示BufferedImage。如果您使用第二种技术,请不要忘记在完成使用后丢弃BufferedImage的Graphics对象,这样就不会占用系统资源。