有两个主要问题,其中之一是代码总是检测到敌人角色几乎所有时间都在 x 轴上发生碰撞。另一个问题是,在我尝试的代码中,不会始终在 x 轴上发生碰撞,敌人的移动不遵循游戏区域内的限制规则。
private void randomMovement(Rectangle enemy) {
double currX = enemy.getX();
double currY = enemy.getY();
double randX = random.nextInt(5) * (random.nextBoolean() ? 1 : -1) *(this.playerComponent.returnX()>enemy.getX() ? 2.5 : -2.5);
double randY = random.nextInt(5) * (random.nextBoolean() ? 1 : -1) * (this.playerComponent.returnY()>enemy.getY() ? 2.5 : -2.5);
double newX = enemy.getX() + randX;
double newY = enemy.getY() + randY;
enemy.setX(newX);
enemy.setY(newY);
double enemyMaxX = newX + enemy.getWidth();
double enemyMaxY = newY + enemy.getHeight();
double xmin = this.playArea.getX();
double xmax = this.playArea.getX() + this.playArea.getWidth();
double ymin = this.playArea.getY();
double ymax = this.playArea.getY() + this.playArea.getHeight();
if(newX < xmin) {
enemy.setX(xmin);
}
if(enemyMaxX > xmax) {
enemy.setX(xmax-enemy.getWidth());
}
if(newY < ymin) {
enemy.setY(ymin);
}
if(enemyMaxY > ymax) {
enemy.setY(ymax-enemy.getHeight());
}
}
我试图通过减少碰撞检测时敌人形状的 x 位置来查看是否真的一直存在碰撞,并且它们都向左移动。通过尽可能多地分离代码来解决这个问题,我遇到了形状没有停止到右侧和底部边界的原始问题。
这是一个示例,显示球(圆)在接触墙壁(矩形)时停止。关键是要理解,一旦检测到碰撞,球可能已经进入墙壁。您应该确定球是否已进入墙壁,并将其移回到撞墙之前的位置。
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Shape;
import javafx.stage.Stage;
import javafx.util.Duration;
public class App extends Application {
Circle ball = new Circle(100, 375, 10, Color.GREEN);
Rectangle wall = new Rectangle(365, 325, 20, 100);
Timeline gameLoop;
@Override
public void start(Stage stage) {
wall.setFill(Color.BLUE);
gameLoop = new Timeline(
new KeyFrame(Duration.millis(25), (ActionEvent event) -> {
moveBall();
checkCollision();
}));
gameLoop.setCycleCount(Timeline.INDEFINITE);
Pane middleRoot = new Pane(ball, wall);
middleRoot.setStyle("-fx-background-color: yellow;");
middleRoot.setPrefSize(750, 750);
Button btnStart = new Button("Start");
btnStart.setOnAction((event) -> {
if(gameLoop.getStatus() == Timeline.Status.STOPPED)
{
gameLoop.play();
}
});
Button btnReset = new Button("Reset");
btnReset.setOnAction((event) -> {
if(gameLoop.getStatus() == Timeline.Status.RUNNING)
{
gameLoop.stop();
ball.setCenterX(100);
}
});
HBox bottomRoot = new HBox(btnStart, btnReset);
VBox root = new VBox(middleRoot, bottomRoot);
var scene = new Scene(root, 800, 800);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
public void moveBall()
{
ball.setCenterX(ball.getCenterX() + 3);
}
public void checkCollision()
{
//If you find a collision, find out how far past the wall boundary did the ball go. Once you have that distance, move the ball back to that distance amount.
if(Shape.intersect(ball, wall).getBoundsInLocal().getWidth() != -1)
{
double xDelta = wall.getLayoutBounds().getMinX() - (ball.getCenterX() + ball.getRadius());
ball.setCenterX(ball.getCenterX() + xDelta);
}
}
}
输出