我目前正在用 java 创建 Flappy Bird 克隆,但在重新打印管道时遇到问题。我的意思是,在 while 循环中,我在右侧打印管道图像,然后打印旧管道(如果有)(在第一个循环中没有任何管道)。然后将第一个管道的 X 和 Y 坐标添加到两个单独的列表(用于存储管道坐标),然后我使用 for 循环更改列表中的所有 x 坐标,并留下 50 个像素。下一步是转到循环的顶部并删除所有管道并重新开始。问题是我无法删除使用 for 循环添加的所有管道。这是我使用的 while 循环中的代码(有两个词 frame.remove(pipeOld); 不是删除所有旧管道,而是删除第一个管道。):
while (true) {
frameCounter++;
int curentFrame = animationFrame;
animationFrame = calculateAnimationFrame(curentFrame);
frame.remove(pipe);
frame.remove(pipeOld);
pipeY = rnd.nextInt(100); //declared already
pipe = showPipes(pipeX,pipeY,animationFrame); // method
frame.add(pipe); // printing pipe
for (int i = 0; i < pipeListX.size(); i++) {
pipeOld = showPipes(pipeListX.get(i),pipeListY.get(i),animationFrame);
frame.add(pipeOld);
}
pipeListX.add(pipeX); // adding current pipe X to list
pipeListY.add(pipeY); // adding current pipe y to list
for (int i = 0; i < pipeListX.size(); i++) { // declaring new x for all the pipes, so they can move
int pipeNew = pipeListX.get(i);
pipeListX.set(i, pipeNew - 50);
}
frame.validate(); // Validates the window
frame.repaint(); // Repaints the window
Thread.sleep(15); // Game speed setting
}
最佳答案
以下来自metaSO的建议:
回答您的特定问题
pipeOld
仅存储最后一个管道。您在 for 循环中覆盖它,因此它只包含最后添加的管道,因此这就是在下一个循环迭代中被删除的内容。如果要跟踪所有旧管道,则应该使用集合而不是单个管道引用,并在循环中删除所有旧管道。
for (JComponent pipe : oldPipes) {
frame.remove(pipe);
}
oldPipes.clear();
<other code>
for (int i = 0; i < pipeListX.size(); i++) {
pipeOld = showPipes(pipeListX.get(i), pipeListY.get(i), animationFrame);
frame.add(pipeOld);
oldPipes.add(pipeOld);
}
但是您根本不应该这样做!
在循环中添加和删除组件以及在 EDT 中使用 Thread.sleep 都是极其糟糕的做法!
- 正如评论中已经提到的,在 EDT 中使用 Thread.sleep 将意味着 GUI 卡住和无响应。 Andrew Thompson 说
Timer
或SwingWorker
对此要好得多,这是完全正确的。我将在这里重新发布他的链接,以免丢失:Concurrency in Swing 。您还应该考虑切换到 MVC 架构,以便您的游戏速度不受帧速率的影响。 - 添加和删除组件是非常昂贵的操作!每次执行此操作时,父组件都会完全重新计算其布局。大多数实时游戏(因此具有移动对象并需要一致的帧速率)使用 Canvas 进行自定义绘画。
关于java - 使用 for 循环将多个 Jlabel 添加到 Jframe,删除它们并将它们打印在新位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23757050/