所以我现在有一个程序可以使用JavaFX在屏幕上移动一个弹跳球,现在我已经尝试在我的时间轴动画中重新格式化Duration.millis()下的某些值,并且我把它放得越快,球就越快然而,有人告诉我这不是最好的方式而是我应该问一下动态速度来添加到我的程序这里是我的球运动代码:
public class BallPane extends Pane {
public final double radius = 5;
public double x = radius, y = radius;
public double dx = 1, dy = 1;
public Circle circle = new Circle(x, y, radius);
public Timeline animation;
public BallPane(){
circle.setFill(Color.BLACK); // Set ball color
getChildren().add(circle); // Place ball into Pane
// Create animation for moving the Ball
animation = new Timeline(
new KeyFrame(Duration.millis(10), e -> moveBall() ));
animation.setCycleCount(Timeline.INDEFINITE);
animation.play();
}
public void moveBall() {
// Check Boundaries
if (x < radius || x > getWidth() - radius) {
dx *= -1; //change Ball direction
}
if (y < radius || y > getHeight() - radius) {
dy *= -1; //change Ball direction
}
x += dx;
y += dy;
circle.setCenterX(x);
circle.setCenterY(y);
} }
反过来,它将成为一个乒乓球比赛,所以我将有5个级别,在每个级别,我希望球移动得更快我可以通过降低持续时间来实现这一目标。 ()但我被告知这不是最好的方式而不是添加速度我怎么能这样做而不降低我的时间线动画参数中的Duration.millis?我应该添加另一个参数还是另一种速度方法?
答案 0 :(得分:2)
我想提出另一种方法:使用AnimationTimer,Vector calculation和Forces。
球/精灵有属性:
PVector location;
PVector velocity;
PVector acceleration;
通过对加速度加速,加速到速度和速度到位置来完成运动:
public void applyForce(PVector force) {
// Making a copy of the PVector before using it!
PVector f = PVector.div(force, mass);
acceleration.add(f);
}
public void move() {
// set velocity depending on acceleration
velocity.add(acceleration);
// limit velocity to max speed
velocity.limit(maxSpeed);
// change location depending on velocity
location.add(velocity);
// clear acceleration
acceleration.mult(0);
}
这是在每个精灵的游戏循环中完成的:
gameLoop = new AnimationTimer() {
@Override
public void handle(long now) {
// physics: apply forces
allSprites.forEach(s -> s.applyForce(Settings.FORCE_GRAVITY));
allSprites.forEach(s -> s.applyForce(Settings.FORCE_WIND));
// move
allSprites.forEach(Sprite::move);
// check boundaries
allSprites.forEach(Sprite::checkBounds);
// update in fx scene
allSprites.forEach(Sprite::display);
}
};
您可以在gist找到完整的示例。根据重力,球在地板上反弹。风从左向右吹,所以球在那里移动。但您可以在设置属性中轻松更改它。
别担心,代码不多,只是通用的Vector计算类很冗长。但你只需要知道一些方法。
该例子使用了力量和重力。无论你想要实现什么,只需施加它的力量。当然,对于你的问题,你可以简单地增加速度而不用力。这一切都取决于你想玩的东西。
截图:
关于如何因摩擦而改变球弹跳的示例在chapter 2.7。这是Daniel Shiffman在他的书中使用的处理代码,但是你看到它很容易翻译成JavaFX:
for (int i = 0; i < movers.length; i++) {
float c = 0.01;
PVector friction = movers[i].velocity.get();
friction.mult(-1);
friction.normalize();
friction.mult(c);
movers[i].applyForce(friction);
movers[i].applyForce(wind);
movers[i].applyForce(gravity);
movers[i].update();
movers[i].display();
movers[i].checkEdges();
}
我将JavaFX实现留给您。
你可能也对a video about how chapter 2.10(一切都吸引一切)感兴趣。如果你想要实现这样的东西,那么编码真的不多。那code is also available。它使用Point2D类,如果你更熟悉它。但是,您不应该使用Point2D,因为它有一些限制,您必须始终创建新的Point2D对象,这可以通过自定义Vector类实现来避免。
答案 1 :(得分:0)
我会以物理为中心:当你做这样的动态时,你应该从你的加速度中获得你的速度和坐标。
每个程序刻度计算新的加速度(使用球的质量,重力常数,各种系数,如弹性系数或与空气的摩擦力),所有这些都是矢量。
然后你基本上将这些向量集成:acceleration - &gt;速度 - &gt;坐标。
完成此操作后,您所需要的只是调整加速度,仅在该矢量上,使您的球移动得更快/更慢,反弹更高或更高,等等。
您可能需要检查Euler integration才能完成工作
Vector position, velocity, acceleration;
public void eulerIntegration(double dt){
//TODO create the calculate acceleration method using your ball model
acceleration = calculateAcceleration();
velocity = acceleration * dt;
position = velocity * dt;
}