Happy Holidays!
For today's post I want to share something I have been working on for
the last few days. For quite some time I have wanted to build a small
application which would generate a maze of sorts. The program would produce a
user who would try to escape out of the box by trying multiple directions to
get around the obstacles. I decided to use JavaFX as my platform to
produce this application as it has the functions necessary (like intersects for
collision detection) to build out my idea and I know the Java language very
well.
Challenges
Collision Detection
During the development process I ran into many challenges. One of the
largest of those was attempting to build the collision detection math from
scratch. After many failed attempts I came across the built in functionality to
assign intersection binding to nodes which is built into JavaFX. After each
move I took the new user coordinates and used the Shape class
getBoundsInLocal().getWidth() method to determine if the collision had occurred.
In that case I would reset the current direction of the user.
for (Line border : borders) {
Shape intersect =
Shape.intersect(border, user);
if
(intersect.getBoundsInLocal().getWidth() != -1) {
System.out.println("Hit a border");
hitPlayer.play();
user.setCenterX(currentX);
user.setCenterY(currentY);
currentDirection =
-1;
break;
}
}
UI Updates / JFX Application Thread
Due to the implementation of JavaFX and threading it is necessary
execute updates to the scene graph on the JavaFX application thread. In order
to update this thread and graph from your application you must choose one of
the methods provided by the platform. The one that I choose was using the Task
object. Overriding the call method I execute the platform.runLater method to
move the user. After each move the status bar is updated along with the
position of the user in the application. This task is started with Thread t =
new Thread(task), t.setDaemon(true), then t.start().
Task task = new Task<Void>() {
@Override
protected Void
call() throws Exception {
for (int i = 1; i <=
TASK_MAX; i++) {
updateProgress(i, TASK_MAX);
Platform.runLater(new Runnable() {
@Override
public void run() {
autoMove();
}
Movement
Another issue which I had to solve was giving the user some sort of
intelligence. If you were stuck in this box and you moved forward one space you
most likely wouldn’t change your mind and go backwards. To
provide for this I implemented logic to continue the user in their current
direction until you hit something. When a collision ccurred the user would randomly decide a new
direction and continue that way until they hit another block. I used a random
number generator to provide an integer between 0 and 7, one for up, down,
left, right, up right, up left, down right, down left. Then I update the position
:
private void autoMove() {
int dir = getDirection();
if (dir < 0) {
return;
}
switch (dir) {
case 0:
updateUser(null,
user.getCenterY(), 0, JUMP);
break;
The get direction method is used to return your current direction or get
you a new one since you hit a block. A block collision sets direction
to -1.
private int getDirection() {
if (currentDirection ==
-1) {
Random rand = new
Random();
currentDirection =
rand.nextInt(8);
}
return currentDirection;
}
The code for this project can be found on my github site here: https://github.com/dtbell99/GetMeOuttaHere