我目前正在创建一个非常简单的JavaFX程序,模拟城市之间运送乘客的飞机和船只。到目前为止,我已经能够让飞机在几个城市进行短途飞行,但问题是,当我添加超过3或4架飞机时,动画速度非常慢。
我正在做的是使用Timeline类作为我的主游戏循环,清除并重新绘制画布上每帧60帧的平面图像。以下是时间表部分:
Timeline gameLoop = new Timeline();
gameLoop.setCycleCount( Timeline.INDEFINITE );
KeyFrame keyFrame = new KeyFrame(
Duration.seconds(0.017),
new EventHandler<ActionEvent>()
{
public void handle(ActionEvent ae)
{
dynamicGC.clearRect(0, 0, 1280, 800);
for (Plane plane : Spawner.planeList)
{
if(plane.isInFlight()) plane.Draw(dynamicGC);
}
}
});
gameLoop.getKeyFrames().add(keyFrame);
gameLoop.play();
以下是我如何为平面创建新线程:
//plane initalization
Thread t = new Thread(plane);
t.setDaemon(true);
t.start();
这是Plane类中定义的run()方法:
public void run() {
int routeCounter = 0;
int direction = 1;
boolean active = true;
double recordedTime = 0.0;
double aParameter = 0.0;
while(active) {
if (inFlight) {
double tmpTime = System.currentTimeMillis();
double timeDifference = tmpTime - recordedTime;
recordedTime = tmpTime;
double change = planeVelocity * (timeDifference) * direction;
xCoordinate += change;
yCoordinate += change * aParameter;
if ( Math.abs(xCoordinate - Spawner.airportList.get(nextAirport).getXCoordinate()) < Spawner.airportList.get(nextAirport).getDetectionPrecision()
&& Math.abs(yCoordinate - Spawner.airportList.get(nextAirport).getYCoordinate()) < Spawner.airportList.get(nextAirport).getDetectionPrecision()) {
inFlight = false;
routeCounter++;
}
} else {
if(routeCounter < plannedRoute.size() ) {
nextAirport = plannedRoute.get(routeCounter);
aParameter = (Spawner.airportList.get(nextAirport).getYCoordinate() - this.yCoordinate)/
(Spawner.airportList.get(nextAirport).getXCoordinate() - this.xCoordinate);
if (Spawner.airportList.get(nextAirport).getXCoordinate() < this.xCoordinate) {
direction = -1;
} else direction = 1;
recordedTime = System.currentTimeMillis();
inFlight = true;
}
else active = false;
}
}
}
我知道代码非常混乱,但现在我想知道为什么动画速度会如此缓慢。我不确定我是否正确使用了线程。我还尝试了一些解决方案,比如在回答这个问题时缓存画布和组节点,但什么也没做。
编辑:似乎是线程减慢了程序的执行速度。
每次用JavaFX应用程序线程中的这个处理程序按下某个按钮时,我都会创建一个新平面(以及一个新线程):
@FXML
private void handleNewPassengerPlaneCreated(ActionEvent event) {
ArrayList<Integer> route = new ArrayList<>();
int startingAirport = Spawner.randomNumberGenerator.nextInt(Spawner.airportList.size());
for(int i = 0; i < 3; i++) {
int addedAirport = Spawner.randomNumberGenerator.nextInt(Spawner.airportList.size());
if ( addedAirport != startingAirport)
route.add(addedAirport);
}
System.out.println(Spawner.airportList.get(startingAirport).xCoordinate + " " + Spawner.airportList.get(startingAirport).yCoordinate );
PassengerPlane plane = new PassengerPlane(Spawner.airportList.get(startingAirport).xCoordinate,
Spawner.airportList.get(startingAirport).yCoordinate, "ID", 10, 1000, route, 300);
Spawner.planeList.add(plane);
new Thread(plane).start();
}
我想知道你为什么要用画布来达到这个目的。可能只是因为您已经习惯了AWT或类似的框架。场景图更适合这种问题。只需将场景图中的一些对象放置在它们的初始位置,然后在一个AnimationTimer中更新它们的位置和方向以及其他内容,就完成了。
我有一个类似的问题,但是您可能需要考虑一些事情,它们可以极大地提高代码的性能:
路径转换
从你的代码中我可以看到,你正在为每个平面创建一个单独的线程。线程是昂贵的对象,尤其是对于每次运行线程时只需要几个cpu周期的任务。然后,您必须考虑线程切换在实际计算时间内的成本。因此,在使用线程时,请确保将其用于长时间运行的任务。
你应该使用不同的方法。看看“在JavaFX中,如何在屏幕上移动精灵?”中的答案。
你应该使用AnimationTimer来更新画布,而不是时间线。
关于您的问题:一个问题可能是您将线程与JavaFX线程混合在一起,这可能会导致问题,如果没有看到完整的代码,就无法判断。
我想知道为什么我的图表每次移动后屏幕都不清晰。这是我的代码: MainClass,我想删除其中的“时间”,并将其放在绘图方法updateScene中的lambda表达式中,但还不知道如何做到这一点:/ Axes类描述如何绘制轴: 缩放和绘制图表中我需要的一切。 绘图课负责制作动画,精确绘制我想要的图形。 屏幕显示我编译后得到的内容。就像我自上而下的问题一样,不知道是什么原因导致在每个时间线阶段后不
我一直试图在我的UI中添加一个动画到我的气泡图中,但遇到了一些问题。我试图在不同的阶段增加气泡的大小,以显示渐变,但它只是画出它的全部大小,而不是在每个阶段。 体育推特计数是泡沫的最终值,我将其除以不同的数量,以显示最终值的建立。 有人有什么想法为什么这不像我期望的那样工作吗?
在一个区域表面上有很多图像。我把它们分成小组。它们应该水平滚动成链。在这里输入图像描述 我写了一些方法来工作。例如。在左边切换位置。(rects-rectangles。早先是rectangles)。 例如。将元素从中心移到左边。 等等。
我是JavaFX新手,我确信我在这里遗漏了一些明显的东西。我试图制作一个汽车的动画,它从左到右穿过一扇窗户,到达那里时绕着右边。用户应该能够点击up/down来调整动画的速度。当我使用一个对象时,动画开始运行,但发现你无法调整的,所以我在一个中重新编辑了它。 然而,随着时间的推移,我被卡住了。当我启动应用程序时,汽车不会显示在屏幕上。以下是我希望的一段简洁的代码片段: 还有消旋果烷: 编辑:根据@
我想创建一个可滚动的时间线控制器,其中圆圈连接到填充有数字(圆的大小对应于包含数字)和尾随图标的基线。 因为我是JavaFX的新手,所以我不知道如何开始。在中,我将例如使用并使用其方法来绘制圆形、线条和图标... 在JavaFX中,我考虑过使用水平的和定制的,但我不确定它是否可以作为基线。所以我在寻找如何实现这种控制的想法。。。