0

I'm working on a program where "bullet lines" are used as a way for the enemy AI to detect where the player is (and shoot at the player accordingly). In my minimal reproducible example below, the player is the blue square and there are a bunch of lines shooting out from the enemy (red square)'s position. The lines should turn red whenever its bounds intersect the player's bounds, but that is not the case. The lines seem to turn red even when the player is not touching the lines.

Please look at this video to get a better sense of my problem: https://youtu.be/7jpv-lYNYYU

Here is my code (MinimalExample.java):

package main;

import javafx.animation.AnimationTimer;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Line;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

/**
 *
 * @author Preston Tang
 */
public class MinimalExample extends Application {

    private Pane graphics;

    //Keyboard Controls
    private boolean w, a, s, d;

    private Rectangle player, enemy;

    private final double GRIDCELLWIDTH = 25;
    private final double WIDTH = 800;
    private final double HEIGHT = 550;
    private final double TANKWIDTH = 20;

    private final int NUMBEROFBULLETLINES = 128;

    private Line[] bulletLines;

    @Override
    public void start(Stage stage) {
        graphics = new Pane();

        //Creating the grid
        for (int r = 0; r < WIDTH / GRIDCELLWIDTH; r++) {
            for (int c = 0; c < HEIGHT / GRIDCELLWIDTH; c++) {
                Rectangle gridCell = new Rectangle();
                gridCell.setX(GRIDCELLWIDTH * r);
                gridCell.setY(GRIDCELLWIDTH * c);
                gridCell.setWidth(GRIDCELLWIDTH);
                gridCell.setHeight(GRIDCELLWIDTH);

                if (r == 0 || c == 0
                        || r == WIDTH / GRIDCELLWIDTH - 1
                        || c == HEIGHT / GRIDCELLWIDTH - 1) {
                    gridCell.setFill(Color.rgb(75, 75, 75));
                } else {
                    gridCell.setFill(Color.WHITE);
                }
                gridCell.setStroke(Color.BLACK);
                gridCell.setStrokeWidth(0.1);

                graphics.getChildren().add(gridCell);
            }
        }

        //Initializing the player and the enemy
        player = new Rectangle();
        player.setX(WIDTH / 4D);
        player.setY(HEIGHT / 2D);
        player.setWidth(TANKWIDTH);
        player.setHeight(TANKWIDTH);
        player.setFill(Color.BLUE);
        player.setStroke(Color.BLACK);

        enemy = new Rectangle();
        enemy.setX(WIDTH / 1.5D);
        enemy.setY(HEIGHT / 2D);
        enemy.setWidth(TANKWIDTH);
        enemy.setHeight(TANKWIDTH);
        enemy.setFill(Color.RED);
        enemy.setStroke(Color.BLACK);

        graphics.getChildren().add(player);
        graphics.getChildren().add(enemy);

        //Creating the lines
        bulletLines = new Line[NUMBEROFBULLETLINES];
        double angle = -Math.PI;

        for (int i = 0; i < bulletLines.length; i++) {
            Line line = new Line();
            double startingX = enemy.getX() + enemy.getWidth() / 2;
            double startingY = enemy.getY() + enemy.getHeight() / 2;

            line.setStartX(startingX);
            line.setStartY(startingY);
            line.setEndX(startingX + Math.cos(angle) * 200);
            line.setEndY(startingY + Math.sin(angle) * 200);

            angle += Math.PI / (NUMBEROFBULLETLINES / 2);

            bulletLines[i] = line;
            graphics.getChildren().add(line);
        }

        stage.setTitle("Minimal Reproducible Example of Tank Game Bug");

        Scene scene = new Scene(graphics, WIDTH, HEIGHT);

        //Reading the keyboard for WASD movement
        scene.setOnKeyPressed(e -> {
            switch (e.getCode()) {
                case W:
                    w = true;
                    break;

                case A:
                    a = true;
                    break;

                case S:
                    s = true;
                    break;

                case D:
                    d = true;
                    break;
            }
        });

        scene.setOnKeyReleased(e -> {
            switch (e.getCode()) {
                case W:
                    w = false;
                    break;

                case A:
                    a = false;
                    break;

                case S:
                    s = false;
                    break;

                case D:
                    d = false;
                    break;
            }
        });

        stage.setScene(scene);
        stage.show();

        AnimationTimer timer = new AnimationTimer() {
            @Override
            public void handle(long now) {
                //Seeing if the player intersects a bullet line
                for (int i = 0; i < bulletLines.length; i++) {
                    if (player.getBoundsInParent().intersects(bulletLines[i].getBoundsInParent())) {
                        bulletLines[i].setStroke(Color.RED);
                    } else {
                        bulletLines[i].setStroke(Color.BLACK);
                    }
                }

                //For moving the player using WASD
                //Diagonals move the player faster in this example
                double x = 0.0;
                double y = 0.0;

                if (w) {
                    y = -1.4;
                }

                if (a) {
                    x = -1.4;
                }

                if (s) {
                    y = 1.4;
                }

                if (d) {
                    x = 1.4;
                }

                player.setTranslateX(player.getTranslateX() + x);
                player.setTranslateY(player.getTranslateY() + y);
            }

        };
        timer.start();
    }

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

Thank you for your time.

Gamer818
  • 102
  • 11
  • 1
    Does this answer your question? [How to check if line segment intersects a rectangle?](https://stackoverflow.com/q/16203760/5221149) – Andreas Dec 04 '20 at 02:13
  • 1
    The `intersects` method checks if the _bounds_ intersect. The bounds are defined by the min x/y and max x/y coordinates of the entire node. – Slaw Dec 04 '20 at 04:14
  • @Slaw So the bounds for a diagonal line would be a large rectangle that isn't diagonal? – Gamer818 Dec 04 '20 at 04:52
  • 1
    Correct. Two of the corners will be the end points of the line. This might help you: [Checking Collision of Shapes with JavaFX](https://stackoverflow.com/questions/15013913/checking-collision-of-shapes-with-javafx) (see the "Alternate Implementation" section of the answer). – Slaw Dec 04 '20 at 05:17
  • If it helps, here's a gist showing you the bounding box of a line (that I will delete eventually): https://gist.github.com/tkslaw/099b6c2da99c4761c68d5455375e66eb – Slaw Dec 04 '20 at 05:26
  • @Slaw Thank you so much! As for Andreas, I'm currently working on implementing the solution you shared in the link. Thank you as well! – Gamer818 Dec 04 '20 at 14:49

0 Answers0