JavaFx 上随机移动对象不会因边界而停止

问题描述 投票:0回答:1

有两个主要问题,其中之一是代码总是检测到敌人角色几乎所有时间都在 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 位置来查看是否真的一直存在碰撞,并且它们都向左移动。通过尽可能多地分离代码来解决这个问题,我遇到了形状没有停止到右侧和底部边界的原始问题。

java javafx collision
1个回答
0
投票

这是一个示例,显示球(圆)在接触墙壁(矩形)时停止。关键是要理解,一旦检测到碰撞,球可能已经进入墙壁。您应该确定球是否已进入墙壁,并将其移回到撞墙之前的位置。

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

输出

© www.soinside.com 2019 - 2024. All rights reserved.