Я делаю приложение и мне нужен мяч, чтобы подпрыгивать под действием силы тяжести. Мяч хорошо отскакивает, но никогда не останавливается.
Я попытался распечатать координаты точек, где он остановился, и какова была скорость. Это результат одного из случаев:
Found it... line 24. (0.00)i + (-0.01)j {14.14(0.79)} (-1.79, 651.57)
Итак, мяч остановился на высоте 651,67, а граница была 600. Вот еще один случай:
Found it... line 24. (0.00)i + (-0.01)j {14.14(0.79)} (-1.79, 1624.58)
Вот код:
GUI.java
import java.util.Timer;
import java.util.TimerTask;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.stage.Stage;
public class GUI extends Application {
@Override
public void start(Stage theStage) throws Exception {
theStage.setTitle("Bouncy Ball");
Group root = new Group();
Scene theScene = new Scene(root);
theStage.setScene(theScene);
Canvas canvas = new Canvas(750, 600);
root.getChildren().add(canvas);
CircleSprite sprite = new CircleSprite(30, new Point(50, 50));
root.getChildren().add(sprite.image);
sprite.setVelocity(new Vector(new Point(10, 10)));
theStage.show();
theStage.setOnCloseRequest(e -> {
System.exit(0);
});
AnimationTimer gameLoop = new AnimationTimer() {
@Override
public void handle(long now) {
if (sprite.update(new Bounds(700, 600))) {
this.stop();
}
}
};
gameLoop.start();
new Timer().scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
Vector velocity = sprite.getVelocity();
velocity.setYComponent(velocity.getYComponent() + 1);
if (Math.abs(sprite.getVelocity().getYComponent()) <= 0.01
&& sprite.getCentre().getY() + 2 * sprite.getRadius() >= 500) {
System.out.println("Found it... line 55");
cancel();
}
}
}, 0, 100);
}
public static void main(String[] args) {
launch(args);
}
}
CircleSprite.java
public class CircleSprite extends Circle {
public javafx.scene.shape.Circle image;
public CircleSprite(long radius, Point centre) {
super(radius, centre);
image = new javafx.scene.shape.Circle(centre.getX(), centre.getY(), radius);
}
public boolean update(Bounds bounds) {
Point pos = this.getCentre();
Vector velocity = this.getVelocity();
Point finalPos = new Point(pos.getX() + velocity.getXComponent(), pos.getY() + velocity.getYComponent());
image.setLayoutX(finalPos.getX());
image.setLayoutY(finalPos.getY());
setCentre(finalPos);
if (finalPos.getX() <= 0 || finalPos.getX() + 2 * getRadius() >= bounds.maxX) {
velocity.setXComponent(velocity.getXComponent() * (-1) * 0.75);
}
if (finalPos.getY() <= 0 || finalPos.getY() + 2 * getRadius() >= bounds.maxY) {
velocity.setYComponent(velocity.getYComponent() * (-1) * 0.75);
}
if (Math.abs(velocity.getYComponent()) <= 0.01 && getCentre().getY() + 2 * getRadius() >= bounds.maxY) {
System.out.println("Found it... line 24" + velocity + " " + getCentre());
return true;
}
return false;
}
}
Границы.java
public class Bounds {
public double maxX;
public double maxY;
public Bounds(double maxX, double maxY) {
this.maxX = maxX;
this.maxY = maxY;
}
}
Circle.java
public class Circle extends Shape {
private long radius;
private Point centre;
public Circle(long radius, Point centre) {
this.radius = radius;
this.centre = centre;
this.setVelocity(new Vector(new Point(0.0d, 0.0d), new Point(0, 0)));
this.setMass(0);
this.setRestitution(1);
this.setAcceleration(new Vector(new Point(0, 0), new Point(0, 0)));
}
/*
* Testing for whether or not two circles intersect is very simple: take the
* radii of the two circles and add them together, then check to see if this sum
* is greater than the distance between the two circles.
*/
public boolean isColliding(Circle a, Circle b) {
long dist = a.getRadius() + b.getRadius();
// In general multiplication is a much cheaper operation than taking the square
// root of a value.
return ((dist * dist) < (a.getCentre().getX() - b.getCentre().getX())
* (a.getCentre().getX() - b.getCentre().getX())
+ (a.getCentre().getY() - b.getCentre().getY()) * (a.getCentre().getY() - b.getCentre().getY()));
}
public long getRadius() {
return this.radius;
}
public void setRadius(long radius) {
this.radius = radius;
}
public Point getCentre() {
return this.centre;
}
public void setCentre(Point centre) {
this.centre = centre;
}
}
Shape.java
public class Shape {
private Vector velocity;
private Vector acceleration;
private long mass;
private double invMass;
private float restitution;
public Vector getAcceleration() {
return this.acceleration;
}
public void setAcceleration(Vector acceleration) {
this.acceleration = acceleration;
}
public long getMass() {
return this.mass;
}
public void setMass(long mass) {
this.mass = mass;
this.setInvMass(mass);
}
public Vector getVelocity() {
return this.velocity;
}
public void setVelocity(Vector velocity) {
this.velocity = velocity;
}
public double getInvMass() {
return this.invMass;
}
private void setInvMass(long mass) {
if (mass == 0) {
invMass = Long.MAX_VALUE;
return;
}
this.invMass = 1.0d / (double) mass;
}
public float getRestitution() {
return this.restitution;
}
public void setRestitution(float restitution) {
this.restitution = restitution;
}
}
Вектор.java
public class Vector {
private Point p1;
private Point p2;
private double xComponent;
private double yComponent;
private double angle;
private double magnitude;
/*
* The constructor makes a vector crossing through two points p1 and p2.
*
* @param p1 The source point(x1, x2)
*/
public Vector(Point p1, Point p2) {
this.p1 = p1;
this.p2 = p2;
this.xComponent = this.p2.getX() - this.p1.getX();
this.yComponent = this.p2.getY() - this.p1.getY();
this.angle = Math.atan2(this.yComponent, this.xComponent);
this.magnitude = Math.sqrt(this.xComponent * this.xComponent + this.yComponent * this.yComponent);
}
public Vector(Point p2) {
Point p1 = new Point(0, 0);
this.p1 = p1;
this.p2 = p2;
this.xComponent = this.p2.getX() - this.p1.getX();
this.yComponent = this.p2.getY() - this.p1.getY();
this.angle = Math.atan2(this.yComponent, this.xComponent);
this.magnitude = Math.sqrt(this.xComponent * this.xComponent + this.yComponent * this.yComponent);
}
public Vector(double magnitude, Vector unitVector) {
scaledProduct(magnitude, unitVector);
}
private void scaledProduct(double magnitude, Vector unitVector) {
Point point = new Point(magnitude * unitVector.getXComponent(), magnitude * unitVector.getYComponent());
new Vector(point);
}
public static Vector scalarProduct(double magnitude, Vector unitVector) {
Point point = new Point(magnitude * unitVector.getXComponent(), magnitude * unitVector.getYComponent());
return new Vector(point);
}
public static double dotProduct(Vector v1, Vector v2) {
return (v1.xComponent * v2.xComponent + v1.yComponent * v2.yComponent);
}
public static Vector sum(Vector v1, Vector v2) {
return new Vector(new Point(v1.getXComponent() + v2.getXComponent(), v1.getYComponent() + v2.getYComponent()));
}
public static Vector difference(Vector from, Vector vector) {
return new Vector(new Point(from.getXComponent() - vector.getXComponent(),
from.getYComponent() - vector.getYComponent()));
}
public static double angleBetween(Vector v1, Vector v2) {
return Math.acos(Vector.dotProduct(v1, v2) / (v1.getMagnitude() * v2.getMagnitude()));
}
public Point getP1() {
return this.p1;
}
public void setP1(Point p1) {
this.p1 = p1;
}
public Point getP2() {
return this.p2;
}
public void setP2(Point p2) {
this.p2 = p2;
}
public double getXComponent() {
return this.xComponent;
}
public void setXComponent(double d) {
this.xComponent = d;
}
public double getYComponent() {
return this.yComponent;
}
public void setYComponent(double d) {
this.yComponent = d;
}
public double getAngle() {
return this.angle;
}
public void setAngle(double angle) {
this.angle = angle;
}
public double getMagnitude() {
return this.magnitude;
}
public void setMagnitude(double length) {
this.magnitude = length;
}
@Override
public boolean equals(Object v) {
Vector vector = (Vector) v;
return ((this.xComponent == vector.xComponent) && (this.yComponent == vector.yComponent));
}
@Override
public String toString() {
return String.format("(%.2f)i + (%.2f)j {%.2f(%.2f)}", this.xComponent, this.yComponent, this.magnitude,
this.angle);
}
}
Point.java
public class Point {
private double x;
private double y;
public Point(double x, double y) {
this.x = x;
this.y = y;
}
public static double distance(Point p1, Point p2) {
return Math.sqrt(
(p1.getX() - p2.getX()) * (p1.getX() - p2.getX()) + (p1.getY() - p2.getY()) * (p1.getY() - p2.getY()));
}
public double getX() {
return x;
}
public void setX(double x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
@Override
public String toString() {
return String.format("(%.2f, %.2f)", this.x, this.y);
}
}
Что не так с кодом? Я знаю, что что-то не так с условием выхода в GUI.java и CircleSprite.java, но не могу понять, что именно. Меня смущают две вещи:
1. Why is the height out of bound when it stops?
2. Why does the x goes negative?