gpt4 book ai didi

java - 我的 javafx 动画计时器似乎没有改变我正在更新的圆圈的位置?

转载 作者:行者123 更新时间:2023-12-01 09:06:49 25 4
gpt4 key购买 nike

因此,我受到 Daniel Shiffman 的编码挑战视频 ( https://www.youtube.com/watch?v=17WoOqgXsRM&t=328s ) 和新星球大战之一的启发,用 Java 制作了某种超空间模拟动画。我是一名初学者到中级程序员,我确实研究了我遇到的问题,但似乎找不到答案,但如果其他人发现类似的问题和答案,请随时链接到它。无论如何,我已经建立了一个已知的类作为这里的明星。

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.scene.paint.Color;
import javafx.scene.Group;
import javafx.scene.shape.Circle;
import java.util.Timer;
import java.util.TimerTask;
import javafx.application.Platform;
import javafx.scene.canvas.Canvas;
import javafx.animation.AnimationTimer;
/**
* @author (Richard Zins)
* @version (1)
*/
public class Star extends Circle
{
double x = 0;
double y = 0;
double z = 0;
public Star()
{
x = Math.random()*800;
y = Math.random()*800;
z = Math.random()*800;
}

public void update(){
z = z - 10 ;
}

我使用它为 800X800 空间中的星星创建随机起始位置,并稍后更改这些值。另外,是的,我确实知道我没有将实例字段设为私有(private),因此当我在主程序中将星星创建为圆圈时,我可以轻松地引用它们,而无需使用我知道这不是惯例但我可以稍后更改的方法。无论如何,我的问题是在我创建星星并创建相应的圆圈之后,当我尝试通过使用我编写的更新方法更改我的 z 值来更新它们的位置,然后获取圆圈 x 值并减去新的 z 我认为它们都应该移动但他们没有。我也知道,目前如果这可行的话,它不会在视频中产生相同的效果,但我只是想让他们现在全部移动。我认为应该执行此操作的代码位于位于我的主类波纹管中的匿名内部类动画计时器中。

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.scene.paint.Color;
import javafx.scene.Group;
import javafx.scene.shape.Circle;
import java.util.Timer;
import java.util.TimerTask;
import javafx.application.Platform;
import javafx.scene.canvas.Canvas;
import javafx.animation.AnimationTimer;
/**
* @author (Richard Zins)
* @version (1)
*/
public class Starfield extends Application
{


public static void main(String[]args)
{
launch(args);
}

@Override
public void start(Stage primaryStage) throws Exception{
primaryStage.setTitle("Starfield Simulation");
Group layout = new Group();
Canvas canvas = new Canvas(800,800);
layout.getChildren().add(canvas);

//puts all the stars onto the scene
Star[] stars = new Star[100];
for(int i = 0;i < stars.length;i++){
stars[i] = new Star();
}
Circle[] circles = new Circle[100];
for(int i = 0;i < stars.length;i++){
for(int r = 0;r < circles.length;r++){
layout.getChildren().add(circles[r] = new Circle(stars[i].x,stars[i].y,5,Color.WHITE));
}
}

//going to handle moving the stars with animation timer
final long startNanoTime = System.nanoTime();
new AnimationTimer(){
public void handle(long currentNanoTime){
for(int i = 0;i < stars.length;i++){
for(int r = 0;r < circles.length;r++){
stars[i].update();
circles[r].setCenterX(stars[i].x - stars[i].z);
circles[r].setCenterY(stars[i].y - stars[i].z);
}
}
}
} .start();

Scene sim = new Scene(layout,800,800,Color.BLACK);
primaryStage.setScene(sim);
primaryStage.show();

}


}

我将不胜感激任何有关此问题的帮助或其他方法的建议或只是对我的代码的总体建议。

最佳答案

JavaFX 使用的默认相机是 ParallelCamera 。如果在使用平行相机时更新 z 坐标,用户将无法感知和移动。

  1. 对于深度感知,PerspectiveCamera应该用过的。
  2. 您不需要像您一样在代码中定义 Canvas不要使用一个。
  3. 您的 Star 继承自 Circle,因此您无需定义额外的圆形数组。
  4. 您使用嵌套循环为 100 个星星定义 100 个圆圈,创建 10000 个圆圈,而每个星星只需要 1 个圆圈。
  5. 您不需要为星星定义 x,y,z 成员,因为它们是圆圈,并且圆圈已经有 translateX、translateY 和 translateZ 的成员。
  6. 您应该检查您的环境是否支持 SCENE3D .
  7. 使用 3D 时,您应该在场景中打开深度缓冲区(对于此模拟不会产生真正的影响,但对于其他模拟会产生影响)。
  8. 不要使用注释,而是将代码拆分为命名方法(只是一种样式建议)。

对于一般代码审查,http://codereview.stackexchange.com更好(请确保您在发布之前阅读 asking)。

output

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.PerspectiveCamera;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;

public class Starfield extends Application {
public static void main(String[] args) {
launch(args);
}

@Override
public void start(Stage stage) throws Exception {
Group layout = new Group();

Star[] stars = createStars(layout);
animateStars(stars);

Scene sim = new Scene(layout, 800, 800, true);
sim.setFill(Color.BLACK);
sim.setCamera(new PerspectiveCamera());

stage.setScene(sim);
stage.show();
}

private void animateStars(final Star[] stars) {
new AnimationTimer() {
public void handle(long currentNanoTime) {
for (Star star : stars) {
star.update();
}
}
}.start();
}

private Star[] createStars(Group layout) {
Star[] stars = new Star[100];
for (int i = 0; i < stars.length; i++) {
stars[i] = new Star();
layout.getChildren().add(
stars[i]
);
}
return stars;
}

public class Star extends Circle {
public Star() {
super(5, Color.WHITE);
setTranslateX(Math.random() * 800);
setTranslateY(Math.random() * 800);
setTranslateZ(Math.random() * 800);
}

public void update() {
double newTranslateZ = getTranslateZ() - 10;
if (newTranslateZ < -2000) {
newTranslateZ = Math.random() * 800;
}

setTranslateZ(newTranslateZ);
}
}
}

我添加了 -2000 z 的模糊因子,以便在星星靠近相机时回收它们。这不是很精确,可以使用一些数学来 determine if the point remains within the field of view在它被回收之前。一些math for such calculations记录在 Camera 类中。 node.computeAreaInScreen()应该能够帮助进行这样的计算,但它没有像我预期的那样工作。

其他问题的答案

follow up question this might be a silly question but why did you make the animateStars method and createStars method private?

只是习惯,在这种情况下,方法是否私有(private)并不重要。对于较大的程序,它可以使代码更容易推理和分析,因为在检查公共(public)接口(interface)时可以忽略私有(private)细节。这是information hiding的OOP原则。其他原则如immutable objects还可以使事情更容易推理(特别是在编写并发代码时)。

注意Java的默认设置很差,项目默认应该是私有(private)的和最终的,这将使Java程序不那么冗长,也鼓励人们编写更容易推理的程序。较新的语言,例如 Ceylon使用更合理的默认值。

关于java - 我的 javafx 动画计时器似乎没有改变我正在更新的圆圈的位置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41203121/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com