如何通过改变方向,即旋转物体,来避免与边界或彼此发生碰撞。

huangapple 未分类评论43阅读模式
英文:

How to avoid collision with the border or with each other by changing the heading i.e. rotate the object

问题

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Bounds;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Duration;

public class Car extends Application {

    public static Pane canvas;

    @Override
    public void start(final Stage primaryStage) throws FileNotFoundException {

        canvas = new Pane();
        final Scene scene = new Scene(canvas, 800, 600);
        scene.setFill(Color.LIGHTGREEN);

        primaryStage.setTitle("Car");
        primaryStage.setScene(scene);

        primaryStage.show();

        Image car1 = new Image(new FileInputStream("src/car2.png"));
        Image car2 = new Image(new FileInputStream("src/car1.png"));

        ImageView c1 = new ImageView(car1);
        ImageView c2 = new ImageView(car2);

        c1.setFitHeight(100);
        c1.setFitWidth(100);
        c1.relocate(100, 100);

        c2.setFitHeight(100);
        c2.setFitWidth(100);
        c2.relocate(600, 100);

        c2.setImage(car2);
        c2.setVisible(true);

        canvas.getChildren().add(c1);
        canvas.getChildren().add(c2);

        final Timeline loop = new Timeline(new KeyFrame(Duration.millis(10), new EventHandler<ActionEvent>() {

            double deltaX = 3;
            double deltaY = 3;

            @Override
            public void handle(final ActionEvent t) {
                c1.setLayoutX(c1.getLayoutX() + deltaX);
                c1.setLayoutY(c1.getLayoutY() + deltaY);

                c2.setLayoutX(c2.getLayoutX() + deltaX);
                c2.setLayoutY(c2.getLayoutY() + deltaY);

                final Bounds bounds = canvas.getBoundsInLocal();
                final boolean atRightBorder = c1.getLayoutX() >= (bounds.getMaxX() - c1.getRadius());
                final boolean atLeftBorder = c1.getLayoutX() <= (bounds.getMinX() + c1.getRadius());
                final boolean atBottomBorder = c1.getLayoutY() >= (bounds.getMaxY() - c1.getRadius());
                final boolean atTopBorder = c1.getLayoutY() <= (bounds.getMinY() + c1.getRadius());

                if (atRightBorder || atLeftBorder) {
                    deltaX *= -1;
                }
                if (atBottomBorder || atTopBorder) {
                    deltaY *= -1;
                }
            }
        }));

        loop.setCycleCount(Timeline.INDEFINITE);
        loop.play();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
英文:
  • The task is actually, two cars moving, the cars must be able to avoid
    collision with the border or with each other by changing the heading
    for example: rotate the object. **
    >I got an error for this
    > getRadius()

     import java.io.FileInputStream;
     import java.io.FileNotFoundException;
     import javafx.animation.KeyFrame;
     import javafx.animation.Timeline;
     import javafx.application.Application;
     import javafx.event.ActionEvent;
     import javafx.event.EventHandler;
     import javafx.geometry.Bounds;
     import javafx.scene.Scene;
     import javafx.scene.image.Image;
     import javafx.scene.image.ImageView;
     import javafx.scene.layout.Pane;
     import javafx.scene.paint.Color;
     //import javafx.scene.shape.Circle;
     import javafx.stage.Stage;
     import javafx.util.Duration;
    
     public class Car extends Application {
    
         //public static Image car;
         public static Pane canvas;
    
         @Override
         public void start(final Stage primaryStage) throws FileNotFoundException {
    
             canvas = new Pane();
             final Scene scene = new Scene(canvas, 800, 600);
             scene.setFill(Color.LIGHTGREEN);
    
             primaryStage.setTitle(&quot;Car&quot;);
             primaryStage.setScene(scene);
    
             primaryStage.show();
    
             //export image
             Image car1 = new Image(new FileInputStream(&quot;src/car2.png&quot;));
             Image car2 = new Image(new FileInputStream(&quot;src/car1.png&quot;));
    
             ImageView c1 = new ImageView(car1);
             ImageView c2 = new ImageView(car2);
    
             c1.setFitHeight(100);//Resize image
             c1.setFitWidth(100);
             c1.relocate(100,100);
    
             c2.setFitHeight(100);//Resize image
             c2.setFitWidth(100);
             c2.relocate(600,100);
    
             c2.setImage(car2);
             c2.setVisible(true);
    
             //add to stage
             canvas.getChildren().add(c1);
             canvas.getChildren().add(c2);
    
             final Timeline loop = new Timeline(new KeyFrame(Duration.millis(10), new EventHandler&lt;ActionEvent&gt;() {
    
                 double deltaX = 3;
                 double deltaY = 3;
    
                 @Override
                 public void handle(final ActionEvent t) {
                     c1.setLayoutX(c1.getLayoutX() + deltaX);
                     c1.setLayoutY(c1.getLayoutY() + deltaY);
    
                     c2.setLayoutX(c2.getLayoutX() + deltaX);
                     c2.setLayoutY(c2.getLayoutY() + deltaY);
    
    
                     final Bounds bounds = canvas.getBoundsInLocal();
                     final boolean atRightBorder = c1.getLayoutX() &gt;= (bounds.getMaxX() - c1.getRadius());
                     final boolean atLeftBorder = c1.getLayoutX() &lt;= (bounds.getMinX() + c1.getRadius());
                     final boolean atBottomBorder = c1.getLayoutY() &gt;= (bounds.getMaxY() - c1.getRadius());
                     final boolean atTopBorder = c1.getLayoutY() &lt;= (bounds.getMinY() + c1.getRadius());
    
    
    
                     if (atRightBorder || atLeftBorder) {
                         deltaX *= -1;
                     }
                     if (atBottomBorder || atTopBorder) {
                         deltaY *= -1;
                     }
                 }
             }));
    
             loop.setCycleCount(Timeline.INDEFINITE);
             loop.play();
    
    
         }
    
         /**
          * @param args the command line arguments
          */
         public static void main(String[] args) {
             launch(args);
         }
    
     }
    

答案1

得分: 2

import java.io.FileNotFoundException;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Bounds;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Duration;

public class Car extends Application {

    private Pane canvas;
    private static final String[] CIRCLES_128 = {
            "https://cdn3.iconfinder.com/data/icons/softwaredemo/PNG/128x128/Circle_Green.png",
            "https://cdn3.iconfinder.com/data/icons/softwaredemo/PNG/128x128/Circle_Red.png",
    };

    private double car1DeltaX = 3, car2DeltaX = 3;  
    private double car1DeltaY = 3, car2DeltaY = 3;  

    @Override
    public void start(final Stage primaryStage) throws FileNotFoundException {

        canvas = new Pane();
        final Scene scene = new Scene(canvas, 800, 600);
        scene.setFill(Color.LIGHTGREEN);

        primaryStage.setTitle("Car");
        primaryStage.setScene(scene);

        Image car1Image = new Image(CIRCLES_128[0]);
        Image car2Image = new Image(CIRCLES_128[1]);

        ImageView car1 = new ImageView(car1Image);
        ImageView car2 = new ImageView(car2Image);

        car1.setFitHeight(100);
        car1.setFitWidth(100);
        car1.relocate(100,100);

        car2.setFitHeight(100);
        car2.setFitWidth(100);
        car2.relocate(600,100);

        canvas.getChildren().addAll(car1, car2);

        final Timeline loop = new Timeline(new KeyFrame(Duration.millis(10), t -> {

            positionNode(car1, car1DeltaX, car1DeltaY);
            positionNode(car2, car2DeltaX, car2DeltaY);

            final Bounds canvasBounds = canvas.getBoundsInLocal();
            final Bounds car1Bounds = car1.getBoundsInParent();
            final Bounds car2Bounds = car2.getBoundsInParent();

            if(collisionDetected(car1Bounds, car2Bounds)){
                handleCollision();
            }

            if(atHorizontalEdge(canvasBounds,car1Bounds)){
                 car1DeltaX *= -1;
            }

            if(atVerticalEdge(canvasBounds,car1Bounds)){
                 car1DeltaY *= -1;
            }

            if(atHorizontalEdge(canvasBounds,car2Bounds)){
                 car2DeltaX *= -1;
            }

            if(atVerticalEdge(canvasBounds,car2Bounds)){
                 car2DeltaY *= -1;
            }

        }));

        primaryStage.show();
        loop.setCycleCount(Timeline.INDEFINITE);
        loop.play();
    }

    private void positionNode(Node node, double deltaX, double deltaY) {
        node.setLayoutX(node.getLayoutX() + deltaX);
        node.setLayoutY(node.getLayoutY() + deltaY);
    }

    private boolean collisionDetected(Bounds b1, Bounds b2) {
        return b1.intersects(b2);
    }

    private boolean atHorizontalEdge(Bounds enclosing, Bounds enclosed) {  
        return enclosed.getMaxX() >= enclosing.getMaxX() || enclosed.getMinX() <= enclosing.getMinX() ;
    }

    private boolean atVerticalEdge(Bounds enclosing, Bounds enclosed) {  
        return enclosed.getMaxY() >= enclosing.getMaxY() || enclosed.getMinY() <= enclosing.getMinY() ;
    }

    private void handleCollision() {
        car1DeltaX *= -1;  car1DeltaY *= -1;
        car2DeltaX *= -1;  car2DeltaY *= -1;
    }

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

First thing, get the movement of the two cars fixed, so they stay withing canvas bounds. <br/>

import java.io.FileNotFoundException;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Bounds;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Duration;

public class Car extends Application {

    private Pane canvas;
	private static final String[] CIRCLES_128 = {
			&quot;https://cdn3.iconfinder.com/data/icons/softwaredemo/PNG/128x128/Circle_Green.png&quot;,
			&quot;https://cdn3.iconfinder.com/data/icons/softwaredemo/PNG/128x128/Circle_Red.png&quot;,
	};

    @Override
    public void start(final Stage primaryStage) throws FileNotFoundException {

        canvas = new Pane();
        final Scene scene = new Scene(canvas, 800, 600);
        scene.setFill(Color.LIGHTGREEN);

        primaryStage.setTitle(&quot;Car&quot;);
        primaryStage.setScene(scene);

        Image car1Image = new Image(CIRCLES_128[0]);
        Image car2Image = new Image(CIRCLES_128[1]);

        ImageView car1 = new ImageView(car1Image);
        ImageView car2 = new ImageView(car2Image);

        car1.setFitHeight(100);//Resize image
        car1.setFitWidth(100);
        car1.relocate(100,100);

        car2.setFitHeight(100);//Resize image
        car2.setFitWidth(100);
        car2.relocate(600,100);

         //add to stage
         canvas.getChildren().addAll(car1, car2);

        final Timeline loop = new Timeline(new KeyFrame(Duration.millis(10), new EventHandler&lt;ActionEvent&gt;() {

            double car1DeltaX = 3, car2DeltaX = 3;  //each car must have its own deltaX and Y because
            double car1DeltaY = 3, car2DeltaY = 3;  //only one car has to change direction when hitting the edge

            @Override
            public void handle(final ActionEvent t) {
                car1.setLayoutX(car1.getLayoutX() + car1DeltaX);
                car1.setLayoutY(car1.getLayoutY() + car1DeltaY);

                car2.setLayoutX(car2.getLayoutX() + car2DeltaX);
                car2.setLayoutY(car2.getLayoutY() + car2DeltaY);

                final Bounds bounds = canvas.getBoundsInLocal();
                final Bounds car1Bounds = car1.getBoundsInParent();
                final Bounds car2Bounds = car2.getBoundsInParent();

                //check car1
                final boolean car1AtRightBorder = car1Bounds.getMaxX() &gt;= bounds.getMaxX() ;//- bounds.getRadius();
                final boolean car1AtLeftBorder = car1Bounds.getMinX()&lt;= bounds.getMinX() ;//+ car1.getRadius();
                final boolean car1AtBottomBorder = car1Bounds.getMaxY() &gt;= bounds.getMaxY() ;//- car1.getRadius();
                final boolean car1AtTopBorder = car1Bounds.getMinY()  &lt;= bounds.getMinY() ;//+ car1.getRadius();

                if (car1AtRightBorder || car1AtLeftBorder) {
                    car1DeltaX *= -1;
                }
                if (car1AtBottomBorder || car1AtTopBorder) {
                    car1DeltaY *= -1;
                }

                //check car2
                final boolean car2AtRightBorder = car2Bounds.getMaxX() &gt;= bounds.getMaxX() ;
                final boolean car2AtLeftBorder = car2Bounds.getMinX()&lt;= bounds.getMinX() ;
                final boolean car2AtBottomBorder = car2Bounds.getMaxY() &gt;= bounds.getMaxY() ;
                final boolean car2AtTopBorder = car2Bounds.getMinY()  &lt;= bounds.getMinY() ;

                if (car2AtRightBorder || car2AtLeftBorder) {
                    car2DeltaX *= -1;
                }
                if (car2AtBottomBorder || car2AtTopBorder) {
                    car2DeltaY *= -1;
                }
            }
        }));

        primaryStage.show();
        loop.setCycleCount(Timeline.INDEFINITE);
        loop.play();
    }

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

Then you can add a simple method to determine if two bounds intersect :

private boolean collisionDetected(Bounds b1, Bounds b2) {
	return b1.intersects(b2);
}

and use it in the loop:

   public void handle(final ActionEvent t) {
            car1.setLayoutX(car1.getLayoutX() + car1DeltaX);
            car1.setLayoutY(car1.getLayoutY() + car1DeltaY);

            car2.setLayoutX(car2.getLayoutX() + car2DeltaX);
            car2.setLayoutY(car2.getLayoutY() + car2DeltaY);

            final Bounds bounds = canvas.getBoundsInLocal();
            final Bounds car1Bounds = car1.getBoundsInParent();
            final Bounds car2Bounds = car2.getBoundsInParent();

            if(collisionDetected(car1Bounds, car2Bounds)){
            	car1DeltaX *= -1;  car1DeltaY *= -1;
            	car2DeltaX *= -1;  car2DeltaY *= -1;
            }

            //check car1
            final boolean car1AtRightBorder = car1Bounds.getMaxX() &gt;= bounds.getMaxX() ;
            final boolean car1AtLeftBorder = car1Bounds.getMinX()&lt;= bounds.getMinX() ;
            final boolean car1AtBottomBorder = car1Bounds.getMaxY() &gt;= bounds.getMaxY() ;
            final boolean car1AtTopBorder = car1Bounds.getMinY()  &lt;= bounds.getMinY() ;

            if (car1AtRightBorder || car1AtLeftBorder) {
                car1DeltaX *= -1;
            }
            if (car1AtBottomBorder || car1AtTopBorder) {
                car1DeltaY *= -1;
            }

            //check car2
            final boolean car2AtRightBorder = car2Bounds.getMaxX() &gt;= bounds.getMaxX() ;
            final boolean car2AtLeftBorder = car2Bounds.getMinX()&lt;= bounds.getMinX() ;
            final boolean car2AtBottomBorder = car2Bounds.getMaxY() &gt;= bounds.getMaxY() ;
            final boolean car2AtTopBorder = car2Bounds.getMinY()  &lt;= bounds.getMinY() ;

            if (car2AtRightBorder || car2AtLeftBorder) {
                car2DeltaX *= -1;
            }
            if (car2AtBottomBorder || car2AtTopBorder) {
                car2DeltaY *= -1;
            }
        }

    }));

<hr>

如何通过改变方向,即旋转物体,来避免与边界或彼此发生碰撞。

<hr>
The following is a refactored cleaner version:

public class Car extends Application {

    private Pane canvas;
	private static final String[] CIRCLES_128 = {
			&quot;https://cdn3.iconfinder.com/data/icons/softwaredemo/PNG/128x128/Circle_Green.png&quot;,
			&quot;https://cdn3.iconfinder.com/data/icons/softwaredemo/PNG/128x128/Circle_Red.png&quot;,
	};

    private double car1DeltaX = 3, car2DeltaX = 3;  //each car must have its own deltaX and Y because
    private double car1DeltaY = 3, car2DeltaY = 3;  //only one car has to change direction when hitting the edge

    @Override
    public void start(final Stage primaryStage) throws FileNotFoundException {

        canvas = new Pane();
        final Scene scene = new Scene(canvas, 800, 600);
        scene.setFill(Color.LIGHTGREEN);

        primaryStage.setTitle(&quot;Car&quot;);
        primaryStage.setScene(scene);

        Image car1Image = new Image(CIRCLES_128[0]);
        Image car2Image = new Image(CIRCLES_128[1]);

        ImageView car1 = new ImageView(car1Image);
        ImageView car2 = new ImageView(car2Image);

        car1.setFitHeight(100);//Resize image
        car1.setFitWidth(100);
        car1.relocate(100,100);

        car2.setFitHeight(100);//Resize image
        car2.setFitWidth(100);
        car2.relocate(600,100);

        //add to stage
        canvas.getChildren().addAll(car1, car2);

        final Timeline loop = new Timeline(new KeyFrame(Duration.millis(10), t -&gt; {

			//move 2 cars to new position
			positionNode(car1, car1DeltaX, car1DeltaY);
			positionNode(car2, car2DeltaX, car2DeltaY);

		    final Bounds canvasBounds = canvas.getBoundsInLocal();
		    final Bounds car1Bounds = car1.getBoundsInParent();
		    final Bounds car2Bounds = car2.getBoundsInParent();

		    if(collisionDetected(car1Bounds, car2Bounds)){
		    	handleCollision();
		    }

		    //check car1 within canvas bounds
		    if(atHorizontalEdge(canvasBounds,car1Bounds)){
		    	 car1DeltaX *= -1;
		    }

		    if(atVerticalEdge(canvasBounds,car1Bounds)){
		    	 car1DeltaY *= -1;
		    }

		    //check car2 within canvas bounds
		    if(atHorizontalEdge(canvasBounds,car2Bounds)){
		    	 car2DeltaX *= -1;
		    }

		    if(atVerticalEdge(canvasBounds,car2Bounds)){
		    	 car2DeltaY *= -1;
		    }

		}));

        primaryStage.show();
        loop.setCycleCount(Timeline.INDEFINITE);
        loop.play();
    }

	private void positionNode(Node node, double deltaX, double deltaY) {
        node.setLayoutX(node.getLayoutX() + deltaX);
        node.setLayoutY(node.getLayoutY() + deltaY);
	}

	private boolean collisionDetected(Bounds b1, Bounds b2) {
		return b1.intersects(b2);
	}

	private boolean atHorizontalEdge(Bounds enclosing, Bounds enclosed) {  
	    return enclosed.getMaxX() &gt;= enclosing.getMaxX() || enclosed.getMinX()&lt;= enclosing.getMinX() ;
	}

    private boolean atVerticalEdge(Bounds enclosing, Bounds enclosed) {  
    	return enclosed.getMaxY() &gt;= enclosing.getMaxY() || enclosed.getMinY()&lt;= enclosing.getMinY() ;
	}

	private void handleCollision() {
		//change cars directions
		car1DeltaX *= -1;  car1DeltaY *= -1;
    	car2DeltaX *= -1;  car2DeltaY *= -1;
	}

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

huangapple
  • 本文由 发表于 2020年4月5日 16:55:38
  • 转载请务必保留本文链接:https://java.coder-hub.com/61040160.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定