Я пробую симуляцию с Verlet Integration, но после двух или около того столкновений шары ускоряются. Нужен совет, как это реализовать, и, возможно, объяснение, почему это происходит. Спасибо!
BouncingPane.java - обрабатывает поведение шаров.
import java.util.ArrayList;
import java.util.Iterator;
import javafx.scene.layout.Pane;
public class BouncingPane extends Pane{
private ArrayList<Ball> balls;
public BouncingPane() {
super();
balls = new ArrayList<Ball>();
this.setPrefSize(300, 300);
}
public void addBall(Ball b) {
balls.add(b);
}
public ArrayList<Ball> getBallsCollection() {
return balls;
}
public void render() {
this.getChildren().addAll(balls);
}
public void updatePos() {
Iterator<Ball> it = this.getBallsCollection().listIterator();
Ball b;
double x_new, y_new;
while(it.hasNext()) {
b = it.next();
x_new = b.getCenterX();
x_new += b.getCenterX() - b.getPX();
if(x_new - b.getRadius() < 0) {
x_new = b.getRadius();
b.setPX(b.getRadius() - (b.getPX() - b.getCenterX()));
x_new = b.getRadius();
}
else if(x_new + b.getRadius() >= getWidth()) {
x_new = getWidth() - b.getRadius();
b.setPX(getWidth() - b.getRadius() + (b.getCenterX() - b.getPX()));
x_new = getWidth() - b.getRadius();
}
else {
b.setPX(b.getCenterX());
b.setCenterX(x_new);
}
y_new = b.getCenterY();
y_new += b.getCenterY() - b.getPY();
if(y_new - b.getRadius() < 0) {
y_new = b.getRadius();
b.setPY(b.getRadius() - (b.getPY() - b.getCenterY()));
y_new = b.getRadius();
}
else if(y_new + b.getRadius() >= getHeight()) {
y_new = getHeight() - b.getRadius();
b.setPY(getHeight() - b.getRadius() + (b.getCenterY() - b.getPY()));
y_new = getHeight() - b.getRadius();
}
else {
b.setPY(b.getCenterY());
b.setCenterY(y_new);
}
}
}
}
Ball.java - просто класс Circle, который отслеживает предыдущую позицию
import javafx.scene.shape.Circle;
import javafx.scene.paint.Color;
public class Ball extends Circle{
private double prevX;
private double prevY;
public Ball(double x, double y, double rad, Color col) {
super(x, y, rad, col);
prevX = 0;
prevY = 0;
}
public void setPX(double x) {prevX = x;}
public void setPY(double y) {prevY = y;}
public double getPX() {return prevX;}
public double getPY() {return prevY;}
}
Main.java - Где инициализируется пользовательский интерфейс. Некоторые операции импорта не использовались (я просто скопировал из моих предыдущих кодов)
import java.util.Iterator;
import javafx.animation.AnimationTimer;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.geometry.Bounds;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class Main extends Application{
public static void main(String[] args) {
launch();
}
public void start(Stage stage) {
BouncingPane canvas = new BouncingPane();
Pane main = new Pane(canvas);
Scene scene = new Scene(main, 300, 300);
Ball ball = new Ball(100, 100, 5, Color.RED);
Ball ball1 = new Ball(50, 50, 5, Color.YELLOW);
canvas.addBall(ball);
canvas.addBall(ball1);
ball.setPX(99.0);
ball.setPY(98.0);
ball1.setPX(49.0);
ball1.setPY(51.0);
canvas.render();
stage.setTitle("Moving Ball");
stage.setScene(scene);
stage.show();
startAnimation(canvas);
}
public void startAnimation(final BouncingPane canvas) {
final AnimationTimer timer = new AnimationTimer() {
long lastTime = 0;
public void handle(long now) {
if(lastTime > 0) {
canvas.updatePos();
}
lastTime = now;
}
};
timer.start();
}
}