我正在写一个坦克游戏。我想要一种叫做射击的方法,当我按下太空时,坦克必须射击。我的问题是,当程序调用此方法时,它会通过while循环,然后打印出球的结束位置。我需要在while循环中实现一些东西,每次计算dx和dy时它都会转到paint方法并绘制球的新位置。我尝试添加paintImmediately()但它抛出stackoverflow错误。谢谢你的帮助。
实际上我正在改变dx和dy,我想让paint方法在那个地方画球... public void shoot(Image img, double fromx, double fromy, double ydestination, int speed) {
int time = 0;
double speedy, speedx;
while (dy!=ydestination) {
time++;
speedy = speed * Math.sin(Math.toRadians(angle));
speedx = speed * Math.cos(Math.toRadians(angle));
dy = (int) ((-5) * time * time + speedy * time + fromy);
dx = (int) (speedx * time + fromx);
// paintImmediately((int)dx,(int) dy, 10, 10);
try {
Thread.sleep(100);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
这是我的重写绘画方法,最后一行是针对我的问题的子弹:
@Override
public void paint(Graphics g) {
System.out.println("paint");
super.paint(g);
render(bufferedGraphics);
g.drawImage(bufferedScreen, 0, 0, null);
// System.out.println(x1);
BufferedImage buff = rotateImage(mile1, angle);
BufferedImage buf = rotateImage(mile2, angle);
g.drawImage(buff, mx1 - 40, my1, null);
g.drawImage(buf, mx2 , my2, null);
g.drawImage(bullet, (int) dx, (int) dy, null);
//setVisible(true);
}
答案 0 :(得分:1)
您使用的是错误的方法。你将3个事件捆绑在一起:用户输入(点击射击),游戏状态更新(子弹移动)和绘制刷新率(绘画)。
一般来说,尝试以相同的速度进行这些工作是一场噩梦,你永远无法实现它。最常见,最简单和最健壮的方法是使用事件循环。用户输入事件触发游戏状态的改变,游戏状态周期性地或者通过一些经过的时间周期性地更新(并且状态更新将取决于经过了多少时间),每次需要时绘制状态,这是定期,但也为一些其他事件,如最小化窗口等等...
对于Java,您可以为此here找到一个好的库。使用示例hello world显示不同的部分here。
P.S:另外,在手动发送线程进入睡眠状态时要非常小心。这可能会使整个程序无法响应。
答案 1 :(得分:0)
如果您的绘图代码中有sleep()
来引入等待,那么您确实做错了。你正试图在那里睡觉,因为你希望屏幕继续更新新的位置...但你实际上是让屏幕完全冻结,因为在Java Swing中只有一个线程绘制东西;如果你睡觉那个线程,没有被绘制(你甚至不能按键或使用鼠标)。
您应该做的是通过对paint()方法的多次调用来更新项目符号的位置。在伪代码中:
paint(Graphics g) {
// calls paint() on all objects in the game world
}
// you should call this once per frame
update(World w) {
// call update() on each game-world object
}
// in Tank
fire(Tank t, Point target) {
// creates a bullet at the tanks' position, and adds it to the World
}
// within Bullet
update() {
// moves this bullet along its path to its target;
// if target reached, add an explosion there and destroy the bullet
}
// within Explosion
update() {
// advance to next explosion frame;
// or if finished, destroy the explosion object
}