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.