简体   繁体   中英

How do I make bouncing ball move quicker? dynamic velocity?

So I had a program to move a bouncing ball across the screen using JavaFX now, Now I've tried reformatting certain values under Duration.millis() in my Timeline Animation and the lower I put it the faster the ball goes but, someone has told me that is not the best way to go instead I should ask about dynamic velocity to add to my program here's my code for movement of my ball:

    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);
} }

In turn, it's going to be a pong game so I'm going to have 5 levels and in each level, I want the ball to move faster I can do this by lowering the Duration.millis() but I am told that is not the greatest way instead to add velocity how may I go about doing this without lowering my Duration.millis in my Time line animation parameters? Is there another parameter I should add or another method of velocity?

I'd like to suggest another approach: Use an AnimationTimer , Vector calculation and Forces .

The balls / sprites have attributes:

PVector location;
PVector velocity;
PVector acceleration;

The movement is done by applying forces to acceleration, acceleration to velocity and velocity to location:

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);
}

And this is done in a game loop for every sprite:

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);

    }
};

You can find a complete example on this gist . The balls bounce on the floor, depending on the gravity. Wind blows from left to right, so the balls move there. But you can easily change that in the settings attributes.

Don't worry, it's not much code, just the general purpose Vector calculation class is lengthy. But you only have to know a few methods of it.

The example uses the forces wind and gravity. Whatever you want to achieve, just apply the force of it. Of course for your question you could simply increase the velocity without applying a force. It all depends on what you want to toy around with.

Screenshot:

在此处输入图片说明

Example about how you could change the bouncing of the balls because of friction is in chapter 2.7 . Here's the processing code that Daniel Shiffman uses in his book, but you see it's very easy to translate to 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();
  }

I leave the JavaFX implementation to you.

You may also be interested in a video about how chapter 2.10 (everything attracts everything) looks like. It's really not much to code if you want to achieve something like this. That code is also available . It uses the Point2D class, if you are more comfortable with that. However, you shouldn't use Point2D since there are limitations with it and you have to create new Point2D objects all the time which can be avoided by a custom Vector class implementation.

I would do it physics centered : When you do dynamics like this you should get your velocity and coordinates out of your accelerations.

Each program tick calculates new acceleration (using the mass of the ball, the gravity constant, various coefficients such as the elasticity coefficient or friction with air one), all of these being vectors.

Then you would basically integrate these vectors : acceleration -> velocity -> coordinates.

After this being done, all you need is to tweak your acceleration, on only that vector, to make your ball move faster/slower, bounce higher or not, and such.

You might want to check Euler integration to do the job

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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM