Saturday, December 12, 2015

Get Me Outta Here!

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;
}

I hope everyone has a safe and happy holiday with family and friends! Enjoy! 

The code for this project can be found on my github site here: https://github.com/dtbell99/GetMeOuttaHere