JavaFX - 如何在不扩大对象的命中框的情况下旋转可移动对象

Posted

技术标签:

【中文标题】JavaFX - 如何在不扩大对象的命中框的情况下旋转可移动对象【英文标题】:JavaFX - How to rotate a moveable object without enlarging the hitbox of the object 【发布时间】:2021-11-29 22:53:49 【问题描述】:

所以我在 javafx 中制作了一个非常基本的 2D 停车游戏(比如 Parking Mania),但我的汽车旋转有问题。它可以很好地旋转,但是当汽车旋转时,汽车的碰撞箱不会旋转,而是会在汽车对象周围变成一个更大的非旋转矩形,因此我无法准确跟踪碰撞。我尝试到处寻找解决方案,但没有成功。 我真的是 java 新手,所以我会很感激任何简单的帮助。

代码如下:

Main.java

 

    package sample;

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Point2D;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;

import javafx.scene.layout.Pane;


import java.awt.*;
import java.util.ArrayList;
import java.util.List;


public class Main extends Application 


    private Pane root;
    private List<GameObject> walls = new ArrayList<>();
    private GameObject wall;
    private GameObject player;
    private GameObject park;
    private GameObject ok;

    private Parent createContent()
        /*private GameObject wall;
        private GameObject player;*/
            root = new Pane();
            root.setPrefSize(1380, 720);

        BackgroundImage myBI= new BackgroundImage(new Image("parkovisko.png",1380,720,false,true),
                BackgroundRepeat.REPEAT, BackgroundRepeat.NO_REPEAT, BackgroundPosition.DEFAULT,
                BackgroundSize.DEFAULT);

        root.setBackground(new Background(myBI));

            ImageView bg = new ImageView();



            player = new Player();
            wall = new Wall();
            park = new Park();
            ok = new Ok();

            /*player.setVelocity(new Point2D(1, 0));*/

            addGameObject(park, 385, 0);
            addGameObject(player, 610, 245);
            player.rotateStart();
            //addGameObject(wall, 250, 330);



        AnimationTimer timer = new AnimationTimer() 
                @Override
                public void handle(long now) 
                    onUpdate();
                
            ;
            timer.start();


            return root;
    

    private void addGameObject(GameObject object, double x, double y) 
        object.getView().setTranslateX(x);
        object.getView().setTranslateY(y);
        root.getChildren().add(object.getView());
    
    public int h = 0;
    Rectangle rectangle = new Rectangle();

    private void addWall(GameObject wall, double x, double y)
        walls.add(wall);
        addGameObject(wall, x, y);
    
    private void onUpdate() 
            for (GameObject wall : walls) 
                if (player.isColliding(wall)) 
                    // player.setAlive(false);
                    //System.exit(1);
                    addGameObject(ok, 350, 175);
                 else if (park.isContaining(player) && h == 0) 
                    addGameObject(ok, 350, 175);
                    h++;
                

                
                player.update();
            
        

    private static class Player extends GameObject 
        Player() super(new ImageView("caarr.png"));
       //Player() super(new Polygon( ));
        


    
    private static class Wall extends GameObject 
        Wall() 
            super(new Rectangle(150, 300));
        
    
    private static class Park extends GameObject 
        Park() 
            super(new Rectangle(50, 100, Color.RED));
        
    
    private static class Ok extends GameObject 
        Ok() 

            super(new ImageView("levelcomp.png"));
        
    



    @Override
    public void start(Stage stage) throws Exception

        StackPane root = new StackPane();
        Scene scene = new Scene(root, 300, 250);
        stage.setScene(scene);
        
        stage.setTitle("Parking :)");
        stage.setScene(new Scene(createContent()));

        ArrayList<String> input = new ArrayList<String>();

        Wall car = new Wall();
       /* Wall car1 = new Wall();
        Wall car2 = new Wall();
*/
        addWall( car, 800, 350);
/*
        addWall( car1, 150, 150);
        addWall(car2, 350, 350);
*/
        stage.getScene().setOnKeyPressed(
                new EventHandler<KeyEvent>() 
                    @Override
                    public void handle(KeyEvent e) 
                        String code = e.getCode().toString();
                        if ( !input.contains(code) )
                            input.add( code );
                    
                );
        stage.getScene().setOnKeyReleased(
                new EventHandler<KeyEvent>()
                
                    public void handle(KeyEvent e)
                    
                        String code = e.getCode().toString();
                        input.remove( code );
                        if (e.getCode() == KeyCode.UP) 
                            player.setVelocity(new Point2D(0, 0));
                        
                        if (e.getCode() == KeyCode.DOWN) 
                            player.setVelocity(new Point2D(0, 0));
                        
                    
                );
        new AnimationTimer()
        
            public void handle(long currentNanoTime)
            
                if (input.contains("UP"))
                    player.move();
                if
                (input.contains("LEFT") && input.contains("UP"))
                player.rotateLeft();
                if (input.contains("RIGHT") && input.contains("UP"))
                    player.rotateRight();
                if (input.contains("DOWN"))
                    player.moveback();
                if (input.contains("RIGHT") && input.contains("DOWN"))
                    player.rotateLeft();
                if (input.contains("LEFT") && input.contains("DOWN"))
                    player.rotateRight();
            
        .start();
        stage.show();
    
    public static void main(String[] args) 
        launch(args);
    

GameObject.java

package sample;
import javafx.geometry.Point2D;
import javafx.scene.Node;


import java.util.ArrayList;


public class GameObject 

    private Node view;


    private Point2D velocity = new Point2D(0, 0);


    public GameObject(Node view)
        this.view = view;
    




    public void update()
        view.setTranslateX(view.getTranslateX() + velocity.getX());
        view.setTranslateY(view.getTranslateY() + velocity.getY());
    

    public void setVelocity(Point2D velocity) 
        this.velocity = velocity;
    

    public Point2D getVelocity() 
        return velocity;
    

    public Node getView() 
        return view;
    


    public double getRotate()
        return view.getRotate();
    
    public void rotateRight() 
        view.setRotate(view.getRotate() + 0.9);
    
    public void rotateLeft() 
        view.setRotate(view.getRotate() - 0.9);
    
    public void rotateStart() 
        view.setRotate(view.getRotate() - 90);
    
    public void rotate()
        view.setRotate(view.getRotate() - 90);
    


    public boolean isColliding(GameObject other)
        return getView().getBoundsInParent().intersects(other.getView().getBoundsInParent());

    
    public boolean isContaining(GameObject other)
        return getView().getBoundsInParent().contains(other.getView().getBoundsInParent());

    
    public void move()
        setVelocity(new Point2D(Math.cos(Math.toRadians(getRotate())), Math.sin(Math.toRadians(getRotate()))));
    
    public void moveback()
        setVelocity(new Point2D(0 - Math.cos(Math.toRadians(getRotate())), 0 - Math.sin(Math.toRadians(getRotate()))));
    
    public void moves(GameObject obj, ArrayList<String> i)
        if (i.contains("UP"))
            setVelocity(new Point2D(Math.cos(Math.toRadians(getRotate())), Math.sin(Math.toRadians(getRotate()))));
        


    

【问题讨论】:

相关Checking Collision of Shapes 要使您的代码更像minimal reproducible example,请使用encrypted-tbn0.gstatic.com/… 等互联网图片或将您的图片上传到imgur.com 并使用它们。 【参考方案1】:

您可以尝试将 pickOnBounds 属性设置为 false。见:https://docs.oracle.com/javase/8/javafx/api/javafx/scene/Node.html#pickOnBoundsProperty

【讨论】:

我应该在哪里设置该属性?也不是属性的默认值 false 吗? 我的错。我认为默认情况下是这样的。

以上是关于JavaFX - 如何在不扩大对象的命中框的情况下旋转可移动对象的主要内容,如果未能解决你的问题,请参考以下文章

如何在不禁用列表项的命中测试的情况下启用对列表项的选择?

如何在不添加新行的情况下在文本框的边界之外编写文本?

如何在不使用数据框的情况下将一行分解为多行?

如何在不丢失setfocus的情况下将光标设置到文本框的末尾?

是否可以在不做任何更改的情况下在 Android 手机中运行 JavaFX 桌面应用程序? [复制]

ccache 在不删除 CMake 文件的情况下不会命中缓存