多个球 - 弹跳球 - Java

时间:2016-01-30 20:45:46

标签: java

我正在使用java中的弹跳球程序。而我现在有一个弹跳球,我想至少有五个弹跳球。我已经尝试了几种方法来做到这一点,但是,我最终只得到一个球或错误。

您对如何进行有任何建议吗?在用于单球的代码片段中,是否可以重写这段代码以便以简洁的方式获得多个球?

import javafx.scene.shape.Rectangle;

public class World {

private final double width, height; 

private Ball[] balls; 
private final Rectangle pad; 

public World(double width, double height) {
    this.width = width;
    this.height = height;

    balls = new Ball[1];
    balls[0] = new Ball(10, 10); 
    balls[0].setVelocity(75.0, 100.0);




    pad = new Rectangle(width / 2, 0.9 * height, 
            width / 8, height / 32);
}


public void move(long elapsedTimeNs) {
    balls[0].move(elapsedTimeNs);
    constrainBall(balls[0]);
    checkForCollisionWithPad(balls[0]);
}


public Ball[] getBalls() {
    return (Ball[]) balls.clone();
}


public Rectangle getPad() {
    return pad;
}


public void setPadX(double x) {
    if (x > width) {
        x = width;
    }
    if (x < 0) {
        x = 0;
    }

    pad.setX(x);
}


private void constrainBall(Ball ball) {
    double x = ball.getX(), y = ball.getY();
    double dx = ball.getDx(), dy = ball.getDy();
    double radius = ball.getRadius();


    if (x < radius) {
        dx = Math.abs(dx);
    } else if (x > width - radius) {
        dx = -Math.abs(dx);
    }
    if (y < radius) {
        dy = Math.abs(dy);
    } else if (y > height - radius) {
        dy = -Math.abs(dy);
    }

    ball.setVelocity(dx, dy);
}


private void checkForCollisionWithPad(Ball ball) {
    if (ball.intersectsArea(
            pad.getX(), pad.getY(), pad.getWidth(), pad.getHeight())) {
        double dx = ball.getDx();
        // set dy negative, i.e. moving "up"
        double newDy = -Math.abs(ball.getDy()); 
        ball.setVelocity(dx, newDy);
    }
 }
}

主要

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Alert;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;


public class Bounce extends Application {

private World world;

private Canvas canvas; 
private AnimationTimer timer;

protected class BounceTimer extends AnimationTimer {

    private long previousNs = 0;


    @Override
    public void handle(long nowNs) {

        if (previousNs == 0) {
            previousNs = nowNs;
        }


        world.move(nowNs - previousNs); 

        previousNs = nowNs;


        GraphicsContext gc = canvas.getGraphicsContext2D();


        gc.setFill(Color.WHITESMOKE);
        gc.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());


        Rectangle pad = world.getPad();
        gc.setFill(Color.BLACK);
        double x = pad.getX(), y = pad.getY(),
                w = pad.getWidth(), h = pad.getHeight();
        gc.fillRoundRect(x, y, w, h, h, h);


        for (Ball b : world.getBalls()) {
            b.paint(gc);
        }



    }
}



@Override
public void start(Stage stage) {
    Group root = new Group();
    Scene scene = new Scene(root, 300, 300, Color.WHITESMOKE);

    canvas = new Canvas(scene.getWidth(), scene.getHeight());
    root.getChildren().add(canvas);

    stage.setTitle("Bounce");
    stage.setScene(scene);
    stage.setResizable(false);
    stage.sizeToScene();
    stage.show();

    world = new World(canvas.getWidth(), canvas.getHeight());

    timer = new BounceTimer();
    timer.start();

    canvas.addEventHandler(MouseEvent.MOUSE_DRAGGED,
            new EventHandler<MouseEvent>() {
                @Override
                public void handle(MouseEvent me) {
                    world.setPadX(me.getX());
                }
            });
}


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

private void showAlert(String message) {
    alert.setHeaderText("");
    alert.setTitle("Alert!");
    alert.setContentText(message);
    alert.show();
}

private final Alert alert = new Alert(Alert.AlertType.INFORMATION);
}

import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;



public class Ball {

public static final double BILLION = 1_000_000_000.0;

private double x, y; // position of the balls center
private double dx, dy; // velocity measured in pixels/second
private double radius;
private Color color;




    public Ball(double x0, double y0) {


    x = x0;
    y = y0;
    radius = 10;
    color = Color.MAGENTA;
}


public Ball(double x0, double y0, double rad, Color col) {


    x = x0;
    y = y0;
    radius = rad;
    color = col;

}

Ball(int i, int i0, Color BLUEVIOLET) {
    throw new UnsupportedOperationException("Not supported yet."); 
}

  public void setColor(Color col) { // setColor
    color = col; }

public double getX() {
    return x;
}


public double getY() {
    return y;
}


public void setX(double newX) {
    x = newX;
}


public void setY(double newY) {
    y = newY;
}


public double getRadius() {
    return radius;
}


public double getDx() {
    return dx;
}


public double getDy() {
    return dy;
}


public void setVelocity(double newDx, double newDy) {
    dx = newDx;
    dy = newDy;
}


public void moveTo(double newX, double newY) {
    x = newX;
    y = newY;
}



public void move(long elapsedTimeNs) {
    x += dx * elapsedTimeNs / BILLION;
    y += dy * elapsedTimeNs / BILLION;
}


public void paint(GraphicsContext gc) {
    gc.setFill(color);
    // arguments to fillOval: see the javadoc for GraphicsContext
    gc.fillOval(x - radius, y - radius, radius * 2, radius * 2);
}


public boolean intersectsArea(
        double rectX, double rectY,
        double rectWidth, double rectHeight) {


    double closestX = clamp(x, rectX, rectX + rectWidth);
    double closestY = clamp(y, rectY, rectY + rectHeight);


    double distanceX = x - closestX;
    double distanceY = y - closestY;


    return (distanceX * distanceX) + (distanceY * distanceY)
            < (radius * radius);
}


private double clamp(double value, double lower, double upper) {
    if (value < lower) {
        return lower;
    }
    if (value > upper) {
        return upper;
    }
    return value;
}
}

1 个答案:

答案 0 :(得分:1)

正如Stormblessed所说,你只是在move方法中定位一个球。 你应该这样做:

public void move(Ball ball, long elapsedTimeNs) {
    ball.move(elapsedTimeNs);
    constrainBall(ball);
    checkForCollisionWithPad(ball);
}

编辑:由于您希望处理程序方法只接受elapsedTimeNs参数,请执行:

public void move(long elapsedTimeNs) {
    for (Ball ball : balls) {
        ball.move(elapsedTimeNs);
        constrainBall(ball);
        checkForCollisionWithPad(ball);
    }
}

编辑2:为方便起见,您可能应该有一个创建新球的方法:

public Ball newBall(double x, double y, double velocity1, double velocity2) {
    Ball tmp = new Ball(x, y);
    tmp.setVelocity(velocity1, velocity2);
    balls.add(tmp);
    return tmp;
}

编辑3:它抛出错误的原因是您使用balls 1 balls = new Ball[指定]只有一个索引位置。您应该使用ArrayListjava.util.ArrayList),如下所示:

import java.util.ArrayList;

ArrayList<Ball> balls = new ArrayList<>;

您现在应该使用balls.addballs.get代替=[]。参考文献已相应更新。