Skip to content

Tag: rectangle collision

JavaFX, rectangular collision detection

[youtube]NRwRTHPGg6M[/youtube]

In a game I wrote some years ago we handled simple rectangular collisions. Given the points:

We did:

// returning 0 means collision
int collision(int ax, int ay, int bx, int by, int cx, int cy, int dx, int dy){
	return ((ax > dx)||(bx < cx)||(ay > dy)||(by < cy));
}

I'll show here a little demo about how implement simple rectangular collisions on JavaFX.
First I created a movable rectangle using the same idea of draggable nodes I already had posted before.

import javafx.input.MouseEvent;
import javafx.scene.geometry.Rectangle;

public class MovableRectangle extends Rectangle {
    private attribute startX = 0.0;
    private attribute startY = 0.0;

    public attribute onMove = function(e:MouseEvent):Void {}

    override attribute onMousePressed = function(e:MouseEvent):Void {
        startX = e.getDragX()-translateX;
        startY = e.getDragY()-translateY;
        onMove(e);
    }

    override attribute onMouseDragged = function(e:MouseEvent):Void {
        translateX = e.getDragX()-startX;
        translateY = e.getDragY()-startY;
        onMove(e);
    }
}

In the main code I some important things:

  • colide, a color that represents the collision effect. White means no collision and gray means collision.
  • rec1 and rec2, the two rectangles that can collide.
  • checkcollision() the function that checks and handles a possible collision.

Here is the main code:

import javafx.application.Frame;
import javafx.application.Stage;
import javafx.scene.geometry.Rectangle;
import javafx.scene.paint.Color;
import javafx.input.MouseEvent;

var colide = Color.WHITE;

function checkcollision():Void {
    if (
        (rec1.getBoundsX() > rec2.getBoundsX() + rec2.getWidth()) or
        (rec1.getBoundsX() + rec1.getWidth() < rec2.getBoundsX()) or 
        (rec1.getBoundsY() > rec2.getBoundsY() + rec2.getHeight()) or 
        (rec1.getBoundsY() + rec1.getHeight() < rec2.getBoundsY())
    ) {
        colide = Color.WHITE
    } else {
        colide = Color.LIGHTGRAY
    }
}

var rec1: MovableRectangle = MovableRectangle {
    x: 10, y: 10, width: 50, height: 60, fill: Color.RED
    onMove: function(e:MouseEvent):Void {
        checkcollision()
    }
}

var rec2: MovableRectangle = MovableRectangle {
    x: 100, y: 100, width: 70, height: 30, fill: Color.BLUE
    onMove: function(MouseEvent):Void {
        checkcollision()
    }
}
Frame {
    title: "Rectangular Collisions", width: 300, height: 300
    closeAction: function() { 
        java.lang.System.exit( 0 ); 
    }
    visible: true

    stage: Stage {
        fill: bind colide
        content: [rec1, rec2]
    }
}

Try it via Java Web Start:

Java Web Start

Some considerations:

  • You can use rectangular collisions to create bounding boxes to handle collisions in more complex shapes or sprites. Is a common approach in 2d games to avoid more expensive calculations.
  • There are space for optimizations.
  • In this case I'm using only two objects. Some problems raises when I have N objects to handle.

More generally, we can code:

function collission(ax, ay, bx, by, cx, cy, dx, dy): Boolean {
    return not ((ax > dx)or(bx < cx)or(ay > dy)or(by < cy));
}

function hitnode(a: Node, b:Node): Boolean{
    return (collission(
        a.getBoundsX(), a.getBoundsY(),
        a.getBoundsX() + a.getWidth(), a.getBoundsY() + a.getHeight(),
        b.getX(), b.getY(),
        b.getX() + b.getWidth(), b.getY() + b.getHeight()
    ));
}

This way we can pass just two bounding boxes to hitnode and easily check collision of a node against a list of bounding boxes nodes.
Using the same approach I also wrote this function to test if a Node is inside another Node:

function inside (ax, ay, bx, by, cx, cy, dx, dy):Boolean{
    return ((ax > cx) and (bx < dx) and (ay > cy) and (by < dy));
}

function insidenode(a:Node,b:Node):Boolean{
    return (inside(
        a.getBoundsX(), a.getBoundsY(),
        a.getBoundsX() + a.getWidth(), a.getBoundsY() + a.getHeight(),
        b.getBoundsX(), b.getBoundsY(),
        b.getBoundsX() + b.getWidth(), b.getBoundsY() + b.getHeight()
    ));
}

Soon I'll post game examples showing how to use this method and others collission detection methods.

Downloads: