gpt4 book ai didi

JavaFX 小行星游戏克隆 : Having trouble bouncing asteroids off eachother

转载 作者:行者123 更新时间:2023-12-02 07:51:56 25 4
gpt4 key购买 nike

我正在尝试在 JavaFX 中制作 Asteroids 游戏克隆。到目前为止,我已经能够将飞船和小行星绘制到屏幕上(目前用矩形代表它们)。我还实现了飞船的运动和小行星的随机运动。

我在实现小行星相互弹开所需的代码时遇到了麻烦。当前执行碰撞检查的方法(名为 checkAsteroidCollisions)存在缺陷,因为所有小行星都会开始原地卡顿。它们不会移动,而是在原地快速来回 Swing 。如果不调用此方法,所有小行星都会开始按预期正常移动。

相反,我希望每颗小行星都能自由移动,并且在与另一颗小行星接触时,像在实际的小行星游戏中一样相互弹开。

MainApp.java

    import java.util.ArrayList;
import java.util.HashSet;

import javafx.animation.AnimationTimer;
import javafx.application.Application;
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.input.KeyEvent;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class MainApp extends Application {
private static final int WIDTH = 700;
private static final int HEIGHT = 900;

private static final int NUM_OF_ASTEROIDS = 12;
private static final Color ASTEROID_COLOR = Color.GRAY;

private static final Color PLAYER_COLOR = Color.BLUE;

private Player player;
private ArrayList<Entity> asteroids;

long lastNanoTime; // For AnimationTimer

HashSet<String> inputs; // For inputs

private static final int MAX_SPEED = 150;
private static final int SPEED = 10;
private static final int ASTEROID_SPEED = 150;

private StackPane background;

/*
* Generates a random number between min and max, inclusive.
*/
private float genRandom(int min, int max) {
return (float) Math.floor(Math.random() * (max - min + 1) + min);
}

/*
* Initializes the asteroids
*/
private void initAsteroids() {
this.asteroids = new ArrayList<Entity>();
for (int i = 0; i < NUM_OF_ASTEROIDS; i++) {
Entity asteroid = new Entity(50, 50, ASTEROID_COLOR, EntityType.ASTEROID);
float px = (float) genRandom(200, WIDTH - 50);
float py = (float) genRandom(200, HEIGHT - 50);
asteroid.setPos(px, py);

// Keep recalculating position until there are no collisions
while (asteroid.intersectsWith(this.asteroids)) {
px = (float) genRandom(200, WIDTH - 50);
py = (float) genRandom(200, HEIGHT - 50);
asteroid.setPos(px, py);
}

// Randomly generate numbers to change velocity by
float dx = this.genRandom(-ASTEROID_SPEED, ASTEROID_SPEED);
float dy = this.genRandom(-ASTEROID_SPEED, ASTEROID_SPEED);
asteroid.changeVelocity(dx, dy);

this.asteroids.add(asteroid);
}
}

/*
* Initializes the player
*/
private void initPlayer() {
this.player = new Player(30, 30, PLAYER_COLOR, EntityType.PLAYER);
this.player.setPos(WIDTH / 2, 50);
}

/*
* Checks collisions with screen boundaries
*/
private void checkOffScreenCollisions(Entity e) {
if (e.getX() < -50)
e.setX(WIDTH);
if (e.getX() > WIDTH)
e.setX(0);
if (e.getY() < -50)
e.setY(HEIGHT);
if (e.getY() > HEIGHT)
e.setY(0);
}

/*
* Controls speed
*/
private void controlSpeed(Entity e) {
if (e.getDx() < -MAX_SPEED)
e.setDx(-MAX_SPEED);
if (e.getDx() > MAX_SPEED)
e.setDx(MAX_SPEED);
if (e.getDy() < -MAX_SPEED)
e.setDy(-MAX_SPEED);
if (e.getDy() > MAX_SPEED)
e.setDy(MAX_SPEED);
}

/*
* Controls each asteroid's speed and collision off screen
*/
private void controlAsteroids(ArrayList<Entity> asteroids) {
for (Entity asteroid : asteroids) {
this.checkOffScreenCollisions(asteroid);
this.controlSpeed(asteroid);
}
}

/*
* Checks an asteroid's collision with another asteroid
*/
private void checkAsteroidCollisions() {
for (int i = 0; i < NUM_OF_ASTEROIDS; i++) {
Entity asteroid = this.asteroids.get(i);
if (asteroid.intersectsWith(this.asteroids)){
float dx = (float) asteroid.getDx();
float dy = (float) asteroid.getDy();
asteroid.setDx(0);
asteroid.setDy(0);
asteroid.changeVelocity(-dx, -dy);
}
}
}

@Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("Hello World!");

this.initAsteroids();
this.initPlayer();

background = new StackPane();
background.setStyle("-fx-background-color: pink");

this.inputs = new HashSet<String>();

Group root = new Group();
Scene scene = new Scene(root);
primaryStage.setScene(scene);

scene.setOnKeyPressed(new EventHandler<KeyEvent>() {

@Override
public void handle(KeyEvent e) {
String code = e.getCode().toString();
inputs.add(code);
}

});

scene.setOnKeyReleased(new EventHandler<KeyEvent>() {

@Override
public void handle(KeyEvent e) {
String code = e.getCode().toString();
inputs.remove(code);
}

});

Canvas canvas = new Canvas(WIDTH, HEIGHT);
GraphicsContext gc = canvas.getGraphicsContext2D();

background.getChildren().add(canvas);
root.getChildren().add(background);

lastNanoTime = System.nanoTime();

new AnimationTimer() {
@Override
public void handle(long currentNanoTime) {
float elapsedTime = (float) ((currentNanoTime - lastNanoTime) / 1000000000.0);
lastNanoTime = currentNanoTime;

/* PLAYER */
// Game Logic
if (inputs.contains("A"))
player.changeVelocity(-SPEED, 0);
if (inputs.contains("D"))
player.changeVelocity(SPEED, 0);
if (inputs.contains("W"))
player.changeVelocity(0, -SPEED);
if (inputs.contains("S"))
player.changeVelocity(0, SPEED);
// Collision with edge of map
checkOffScreenCollisions(player);
// Control speed
controlSpeed(player);
player.update(elapsedTime);

/* ASTEROIDS */
gc.setFill(ASTEROID_COLOR);

for(int i = 0; i < NUM_OF_ASTEROIDS; i++) {
checkAsteroidCollisions(i); // BUGGY CODE
}
controlAsteroids(asteroids);

gc.clearRect(0, 0, WIDTH, HEIGHT);

for (Entity asteroid : asteroids) {
asteroid.update(elapsedTime);
asteroid.render(gc);
}

gc.setFill(PLAYER_COLOR);
player.render(gc);
}

}.start();

primaryStage.show();
}

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

}

实体.java:

    import java.util.ArrayList;

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

public class Entity {
private Color color;
private double x, y, width, height, dx, dy;
private EntityType entityType; // ID of this Entity

public Entity(float width, float height, Color color, EntityType type) {
this.x = this.dx = 0;
this.y = this.dy = 0;
this.width = width;
this.height = height;
this.color = color;
this.entityType = type;
}

/*
* Getters and setters
*/
public Color getColor() {
return color;
}

public void setColor(Color color) {
this.color = color;
}

public double getX() {
return x;
}

public void setX(float x) {
this.x = x;
}

public double getY() {
return y;
}

public void setY(float y) {
this.y = y;
}

public double getDx() {
return dx;
}

public void setDx(float dx) {
this.dx = dx;
}

public double getDy() {
return dy;
}

public void setDy(float dy) {
this.dy = dy;
}

public EntityType getEntityType() {
return entityType;
}

/*
* Adds to dx and dy (velocity)
*/
public void changeVelocity(float dx, float dy) {
this.dx += dx;
this.dy += dy;
}

/*
* Sets position
*/
public void setPos(float x, float y) {
this.setX(x);
this.setY(y);
}

/*
* Gets new position of the Entity based on velocity and time
*/
public void update(float time) {
this.x += this.dx * time;
this.y += this.dy * time;
}

/*
* Used for collisions
*/
public Rectangle2D getBoundary() {
return new Rectangle2D(this.x, this.y, this.width, this.height);
}

/*
* Checks for intersections
*/
public boolean intersectsWith(Entity e) {
return e.getBoundary().intersects(this.getBoundary());
}

/*
* If any of the entities in the passed in ArrayList
* intersects with this, then return true;
*/
public boolean intersectsWith(ArrayList<Entity> entities) {
for(Entity e : entities) {
if(e.getBoundary().intersects(this.getBoundary()))
return true;
}
return false;
}


/*
* Draws the shape
*/
public void render(GraphicsContext gc) {
gc.fillRoundRect(x, y, width, height, 10, 10);
}

@Override
public String toString() {
return "Entity [x=" + x + ", y=" + y + ", width=" + width + ", height=" + height + ", entityType=" + entityType
+ "]";
}

}

最佳答案

我认为你需要稍微改变两个碰撞小行星的位置,这样它们的状态就不再是碰撞了。

现在发生的情况是,您在碰撞后更改了它们的运动,但我猜您的算法注意到它们仍在接触,因此它将尝试再次更改运动,并获得与之前相同的结果。

您现在需要实现的是改变两颗小行星的位置,这样您的碰撞检测就不会在第一次调用后立即再次启动。

希望能帮到你。

关于JavaFX 小行星游戏克隆 : Having trouble bouncing asteroids off eachother,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45856001/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com