我可能做错了,所以请你好。 我正在开发一个Java游戏,我正处于测试角色移动/动画的阶段。
“人”可以在网格上向左和向下移动。 绘制网格的类是gamePanel类。 这些按钮位于gameControlPanel类中。
我有一个按钮,可以在网格上生成一个人。 然后我有一个按钮可以左右移动这个人。
按下向上移动按钮时,它会调用person类中的move up方法。 (目前,我一次只测试一个“人”。) 在该方法中是以下代码......
int move = 10;
while(move!=0)
{
setTopLeftPoint(new Point((int)getTopLeftPoint().getX(),
(int)getTopLeftPoint().getY() - 3));
try
{
Thread.sleep(300);
} catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
move-=1;
}
问题是我似乎无法从Person类中调用gamePanel类的重绘方法。 为了解决这个问题,我在gamePanel类中创建了一个计时器,它每20ms重新绘制一次。
当我产生人物后按下向上按钮时,按钮保持按下直到while循环完成循环,然后人物的圆圈表示显示在上面的网格方格中。
我会尽力回答有关此事的任何问题。
答案 0 :(得分:2)
repaint()不会立即重新绘制GUI。相反,它向AWT线程发布消息,告诉它在下一个方便的机会画画。当它有机会时,它会重新绘制你的应用程序。但是,如果在事件处理程序中执行此操作,则AWT线程已经忙,您需要退出处理程序以将控制权交还给AWT处理程序。
作为一般经验法则, 想要在AWT线程(包括事件处理程序)中进行任何长时间运行的计算,因为这会阻止应用程序响应其他事件直到你的计算完成。对于用户来说,这通常会显示为您所描述的卡住按钮。要解决此问题,请使用SwingWorker,它可以在单独的线程上进行计算。
最后,需要注意的事情(但不一定要改变)是定时器和睡眠并不能保证什么时候它们会被唤醒。相反,他们保证在经过一段时间之前不会唤醒,但理论上可以无限期地睡觉。此外,并非所有机器都具有1 ms定时器分辨率。特别是,在许多Windows机器上,定时器只有55毫秒的分辨率,所以一个20毫秒的定时器可能会产生奇怪的结果。
答案 1 :(得分:1)
如果您想以特定间隔重新粉饰,javax.swing.Timer
可能适合您。在repaint
的特定情况下,您可以从非EDT线程调用它,但是您可能会遇到困难,因为您现在处理多个线程。
答案 2 :(得分:0)
我没有太多制作游戏的经验,但拥有控制所有动画的循环是游戏编程的一个基本方面。大多数简单的2D游戏只有1个循环来渲染它的大部分动画。
根据我的经验,渲染大量内容的好方法是在一个地方拥有游戏中所有实体的集合,然后循环遍历此集合,将Graphics对象传递给每个实体。
这将允许每个实体将自己绘制到图形对象上。虽然这只是一种方法。
synchronized ( entities ) {
for ( Entity e : entities ) {
e.draw( g );
e.doAction();
}
}
答案 3 :(得分:0)
按下按钮是否由GUI的事件派发线程处理?
如果是这种情况,那么GUI上的重绘方法将不会触发,直到事件发送线程结束(即当按钮被释放并且它突然出现循环时)。我最近遇到了这个问题,我建议的最好的解决方案是使用移动算法的类可以线程化,并在检测到按键时触发线程。这允许事件派发线程完成,因此允许gui重绘。
有关线程的详细信息,请参阅Starting a thread。