Java/FX 和 Scenebuilder;碰撞检测和停止运动

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

我是 java 和 OOP 的初学者,我正在尝试创建一个迷宫游戏,目前我正在使用动画计时器,以便玩家可以顺利移动。我创建了一个碰撞检测方法,当玩家遇到一堵牢不可破的墙时,该方法返回 true 并打印出存在碰撞,但玩家继续在其上移动。需要帮助和建议,谢谢!

这是我的玩家类别

package application;

import java.util.ArrayList;

import javafx.animation.AnimationTimer;
import javafx.beans.binding.BooleanBinding;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.fxml.FXML;
import javafx.geometry.Bounds;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.shape.Rectangle;

public class Player{
    @FXML private ImageView player;
    @FXML AnchorPane scene;
    private double x;
    private double y;
    private int lives;
    private int scoreCounter;
    private BooleanProperty upPressed = new SimpleBooleanProperty();
    private BooleanProperty leftPressed = new SimpleBooleanProperty();
    private BooleanProperty rightPressed = new SimpleBooleanProperty();
    private BooleanProperty downPressed = new SimpleBooleanProperty();
    
    private BooleanBinding keyPressed = upPressed.or(leftPressed).or(rightPressed).or(downPressed);
    
    private boolean left, up, right, down;
    boolean canMove = true;
    
    private double movementVariable = 0.75;
    
    CollisionHandler collisionHandler = new CollisionHandler();

        
    public Player(ImageView player, double x, double y, int lives, int scoreCounter) {
        this.player = player;
        this.x = x;
        this.y = y;
        this.lives = lives;
        this.scoreCounter = scoreCounter;
    }
    
 
    public void makeMovable(ImageView player, AnchorPane scene, ArrayList<Rectangle> unbreakableObjects) {
        this.player = player;
        this.scene = scene;
        
        movementSetup();
        
        keyPressed.addListener(((observableValue, aBoolean, t1) -> {
            if (!aBoolean) {
                timer.start();
                canMove = false;
            } else {
                timer.stop();
            }
        }));
    }
    
    AnimationTimer timer = new AnimationTimer() {
//      double currentX = player.getLayoutX();
//      double currentY = player.getLayoutY();
//      
        @Override
        public void handle(long timestamp) {
//          double currentX = player.getLayoutX();
//          double currrentY = player.getLayoutY();
            if(upPressed.get()) {
                player.setLayoutY(player.getLayoutY() - movementVariable);
            }
            if(downPressed.get()){
                player.setLayoutY(player.getLayoutY() + movementVariable);
            }
            if(leftPressed.get()){
                player.setLayoutX(player.getLayoutX() - movementVariable);
            }
            if(rightPressed.get()){
                player.setLayoutX(player.getLayoutX() + movementVariable);
            }
            
        }
    };
    
    public boolean playerCollidesWithUnbreakable(double x, double y, ArrayList <Rectangle> unbreakables) {
        if (collisionHandler.checkCollisionUnbreakables(this, unbreakables)) {
            if(upPressed.get()) {
                player.setLayoutY(player.getLayoutY() + movementVariable);
            }
            if(downPressed.get()){
                player.setLayoutY(player.getLayoutY() - movementVariable);
            }
            if(leftPressed.get()){
                player.setLayoutX(player.getLayoutX() + movementVariable);
            }
            if(rightPressed.get()){
                player.setLayoutX(player.getLayoutX() - movementVariable);
            }
                return true;
            } else {
                return false;
            }
    }
    
    private void movementSetup(){
        scene.setOnKeyPressed(e -> {
            if(e.getCode() == KeyCode.W) {
                upPressed.set(true);
                up = true;
            }
            if(e.getCode() == KeyCode.A) {
                leftPressed.set(true);
                left = true;
            }
            if(e.getCode() == KeyCode.S) {
                downPressed.set(true);
                down = true;
            }
            if(e.getCode() == KeyCode.D) {
                rightPressed.set(true);
                right = true;
            }
        });
        scene.setOnKeyReleased(e ->{
            if(e.getCode() == KeyCode.W) {
                upPressed.set(false);
                up = true;
            }
            if(e.getCode() == KeyCode.A) {
                leftPressed.set(false);
                left = true;
            }
            if(e.getCode() == KeyCode.S) {
                downPressed.set(false);
                down = true;
            }
            if(e.getCode() == KeyCode.D) {
                rightPressed.set(false);
                right = true;
            }
        });
    }
    public int getScore() {
            return this.scoreCounter;
    }
    
    public void incrementScore() {
            this.scoreCounter++;
    }
    
    public double returnX() {
            return player.getX();
    }
    
    public double returnY() {
            return player.getY();
    }
    
    public void newX(double x) {
            player.setX(x);
    }
    
    public void newY(double y) {
            player.setY(y);
    }
    
    public Bounds getPlayerBounds() {
        return player.getBoundsInParent();
    }

  
    public ImageView getPlayerImageView() {
        return player;
    }

}

这是我的控制器类

package application;

import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.ResourceBundle;

import javafx.animation.AnimationTimer;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Bounds;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Text;


public class PlayerController implements Initializable{
    
    @FXML
    private ImageView player;
    private Player playerComponent;
    
    @FXML private AnchorPane scene;
    
    
    private double x = 0;
    private double y = 0;
    private int scoreCounter = 0;
    
    @FXML private int lives;
    @FXML private Text score;
    
    @FXML private Rectangle Bed;
    @FXML private Rectangle Plant;
    @FXML private Rectangle Shelf1;
    @FXML private Rectangle Shelf2;
    @FXML private Rectangle Box1;
    @FXML private Rectangle Box2;
    @FXML private Rectangle Box3;
    @FXML private Rectangle Box4;
    @FXML private Rectangle Cabinet1;
    @FXML private Rectangle TVset;
    @FXML private Rectangle chair1;
    @FXML private Rectangle chair2;
    @FXML private Rectangle Table1;
    @FXML private Rectangle Desk1;
    @FXML private Rectangle Desk2;
    @FXML private Rectangle Box5;
    @FXML private Rectangle Box6;
    @FXML private Rectangle Cabinet2;
    @FXML private Rectangle RightWall;
    @FXML private Rectangle TopWall;
    @FXML private Rectangle LeftWall;
    @FXML private Rectangle BottomWall;
    
    @FXML private ImageView breakable1;
    @FXML private ImageView breakable2;
    @FXML private ImageView breakable3;
    @FXML private ImageView breakable4;
    @FXML private ImageView breakable5;
    @FXML private ImageView breakable6;
    @FXML private ImageView breakable7;
    @FXML private ImageView breakable8;
    @FXML private ImageView breakable9;
    @FXML private ImageView breakable10;
    @FXML private ImageView breakable11;
    @FXML private ImageView breakable12;
    @FXML private ImageView breakable13;
    @FXML private ImageView breakable14;
    @FXML private ImageView breakable15;
    @FXML private ImageView breakable16;
    @FXML private ImageView breakable17;
    @FXML private ImageView breakable18;
    @FXML private ImageView breakable19;
    @FXML private ImageView breakable20;
    @FXML private ImageView breakable21;
    @FXML private ImageView breakable22;
    @FXML private ImageView breakable23;
    @FXML private ImageView breakable24;

    private ArrayList<Rectangle> unbreakableObjects = new ArrayList();
    
    private ArrayList<ImageView> breakableObjects;
    
    Unbreakable unbreakable = new Unbreakable();
    
    CollisionHandler collisionHandler = new CollisionHandler();
    
    AnimationTimer gameLoop;
    
    
    @Override
    public void initialize(URL arg0, ResourceBundle arg1) {
        this.scene = scene;
        playerComponent = new Player(player, x, y, lives, scoreCounter);        
        gameLoop = new AnimationTimer() {

            @Override
            public void handle(long arg0) {
                double currentX = player.getX();
                double currentY = player.getY();
                
                playerComponent.makeMovable(player, scene, unbreakableObjects);
                if(collisionHandler.checkCollisionUnbreakables(playerComponent, unbreakableObjects)) {
                    player.setX(currentX);
                    player.setY(currentY);
                }
            
            }   
        };
                
        gameLoop.start();
        
        unbreakableObjects.add(Bed);
        unbreakableObjects.add(Cabinet1);
        unbreakableObjects.add(Shelf1);
        unbreakableObjects.add(Shelf2);
        unbreakableObjects.add(Box1);
        unbreakableObjects.add(Box2);
        unbreakableObjects.add(Box3);
        unbreakableObjects.add(Box4);
        unbreakableObjects.add(Plant);
        unbreakableObjects.add(TVset);
        unbreakableObjects.add(chair1);
        unbreakableObjects.add(chair2);
        unbreakableObjects.add(Table1);
        unbreakableObjects.add(Desk1);
        unbreakableObjects.add(Desk2);
        unbreakableObjects.add(Box5);
        unbreakableObjects.add(Box6);
        unbreakableObjects.add(Cabinet2);
        unbreakableObjects.add(RightWall);
        unbreakableObjects.add(TopWall);
        unbreakableObjects.add(LeftWall);
        unbreakableObjects.add(BottomWall);
        
        breakableObjects = new ArrayList<>();

        breakableObjects.add(breakable1);
        breakableObjects.add(breakable2);
        breakableObjects.add(breakable3);
        breakableObjects.add(breakable4);
        breakableObjects.add(breakable5);
        breakableObjects.add(breakable6);
        breakableObjects.add(breakable7);
        breakableObjects.add(breakable8);
        breakableObjects.add(breakable9);
        breakableObjects.add(breakable10);
        breakableObjects.add(breakable11);
        breakableObjects.add(breakable12);
        breakableObjects.add(breakable13);
        breakableObjects.add(breakable14);
        breakableObjects.add(breakable15);
        breakableObjects.add(breakable16);
        breakableObjects.add(breakable17);
        breakableObjects.add(breakable18);
        breakableObjects.add(breakable19);
        breakableObjects.add(breakable20);
        breakableObjects.add(breakable21);
        breakableObjects.add(breakable22);
        breakableObjects.add(breakable23);
        breakableObjects.add(breakable24);
    }
    
    
    private void pointChecker() {
        playerComponent.incrementScore();       score.setText(String.valueOf(playerComponent.getScore()));
        System.out.println("PLAYER SCORE: " + playerComponent.getScore());
        
    }
}

这是我的碰撞处理程序

package application;

import java.util.ArrayList;

import javafx.geometry.Bounds;
import javafx.scene.image.ImageView;
import javafx.scene.shape.Rectangle;

public class CollisionHandler {
    public boolean checkCollisionUnbreakables(Player player, ArrayList<Rectangle> unbreakableObjects) {
        Bounds playerBounds = player.getPlayerBounds();
        
        for (Rectangle rectangle : unbreakableObjects) {
                
            Bounds rectangleBounds = rectangle.getBoundsInParent();

            if (playerBounds.intersects(rectangleBounds)) {
                System.out.println("You can't go there!");
                return true;
            } 
        }
        return false;
    }
    public boolean checkCollisionBreakables(Player player, ArrayList<ImageView> breakableObjects) {
        Bounds playerBounds = player.getPlayerBounds();
        
        for (ImageView breakable : breakableObjects) {
            Bounds breakableBounds = breakable.getBoundsInParent();
            if (playerBounds.intersects(breakableBounds)) {
                if (breakable.getImage() == null) {
//                  System.out.println("Cleared already");
                    // Cleared already
                    return false;
                } else {

                    System.out.println("Picked up trash");
                breakable.setImage(null);
                return true;
                }
            }
        }
        return false;
    }
}

尝试在移动之前存储玩家的当前位置,移动后我检查是否有碰撞,如果发生碰撞,我将玩家设置为存储的位置。

java oop javafx scenebuilder
1个回答
0
投票

一旦检测到碰撞就尝试打破循环。

public boolean checkCollisionUnbreakables(Player player, ArrayList<Rectangle> unbreakableObjects) {
    Bounds playerBounds = player.getPlayerBounds();
    Boolean collide = false;
    for (Rectangle rectangle : unbreakableObjects) {
            
        Bounds rectangleBounds = rectangle.getBoundsInParent();

        if (playerBounds.intersects(rectangleBounds)) {
            System.out.println("You can't go there!");
            collide = true;
        } 
    }
    return collide;
}

您的循环仍然继续迭代所有不可破坏的对象,如果该不可破坏的对象不在玩家范围内,则将返回 false。当然它会打印出警告,但你没有打破循环,导致它返回所有迭代结果。

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