collision detection
java programming
rectangle collision
game development
2D graphics

Collision detection between two rectangles in java

Data Structures & Algorithms practice on Codemia

Step through 300+ coding interview problems with animated visualisers that show the data structure changing as the code runs. The Blind 75 are free.

Practice algorithms

Introduction

Axis-Aligned Bounding Box (AABB) collision detection checks whether two rectangles overlap by comparing their edges. Two rectangles collide if and only if they overlap on both the x-axis and the y-axis. This runs in O(1) time and is the foundation of 2D collision detection in games and UI frameworks.

The AABB Overlap Condition

Two rectangles A and B overlap when all four of these conditions are true:

  • A's left edge is to the left of B's right edge
  • A's right edge is to the right of B's left edge
  • A's top edge is above B's bottom edge
  • A's bottom edge is below B's top edge

In code (where y increases downward, as in most screen coordinate systems):

java
1boolean collides =
2    a.x < b.x + b.width &&
3    a.x + a.width > b.x &&
4    a.y < b.y + b.height &&
5    a.y + a.height > b.y;

If any one condition is false, the rectangles do not overlap.

Basic Implementation

java
1public class Rectangle {
2    public double x, y, width, height;
3
4    public Rectangle(double x, double y, double width, double height) {
5        this.x = x;
6        this.y = y;
7        this.width = width;
8        this.height = height;
9    }
10
11    public boolean intersects(Rectangle other) {
12        return this.x < other.x + other.width &&
13               this.x + this.width > other.x &&
14               this.y < other.y + other.height &&
15               this.y + this.height > other.y;
16    }
17}
java
1Rectangle player = new Rectangle(100, 100, 50, 50);
2Rectangle enemy = new Rectangle(130, 120, 40, 40);
3
4if (player.intersects(enemy)) {
5    System.out.println("Collision detected!");
6}

Using java.awt.Rectangle

Java's standard library provides java.awt.Rectangle with built-in collision detection:

java
1import java.awt.Rectangle;
2
3Rectangle r1 = new Rectangle(100, 100, 50, 50);
4Rectangle r2 = new Rectangle(130, 120, 40, 40);
5
6// Check for intersection
7if (r1.intersects(r2)) {
8    System.out.println("Collision!");
9}
10
11// Get the overlapping region
12Rectangle overlap = r1.intersection(r2);
13System.out.println("Overlap area: " + overlap.width * overlap.height);
14
15// Check if one rectangle contains another
16if (r1.contains(r2)) {
17    System.out.println("r1 fully contains r2");
18}

Using Rectangle2D for Floating-Point Precision

For sub-pixel precision, use Rectangle2D.Double:

java
1import java.awt.geom.Rectangle2D;
2
3Rectangle2D.Double r1 = new Rectangle2D.Double(100.5, 100.5, 50.0, 50.0);
4Rectangle2D.Double r2 = new Rectangle2D.Double(130.2, 120.8, 40.0, 40.0);
5
6if (r1.intersects(r2)) {
7    System.out.println("Collision with sub-pixel precision");
8}

Game Loop Example

A typical game loop with collision detection:

java
1public class Game {
2    private Rectangle player;
3    private List<Rectangle> obstacles;
4
5    public void update() {
6        // Move player based on input
7        player.x += velocityX;
8        player.y += velocityY;
9
10        // Check collisions with all obstacles
11        for (Rectangle obstacle : obstacles) {
12            if (player.intersects(obstacle)) {
13                handleCollision(player, obstacle);
14            }
15        }
16    }
17
18    private void handleCollision(Rectangle a, Rectangle b) {
19        // Calculate overlap on each axis
20        double overlapX = Math.min(a.x + a.width, b.x + b.width)
21                        - Math.max(a.x, b.x);
22        double overlapY = Math.min(a.y + a.height, b.y + b.height)
23                        - Math.max(a.y, b.y);
24
25        // Push back on the axis with less overlap (minimum translation)
26        if (overlapX < overlapY) {
27            if (a.x < b.x) a.x -= overlapX;
28            else a.x += overlapX;
29        } else {
30            if (a.y < b.y) a.y -= overlapY;
31            else a.y += overlapY;
32        }
33    }
34}

Optimization: Broad Phase with Spatial Partitioning

When checking many objects, testing every pair is O(n²). Use spatial partitioning to reduce checks:

java
1// Simple grid-based broad phase
2public class SpatialGrid {
3    private int cellSize;
4    private Map<Long, List<Rectangle>> cells = new HashMap<>();
5
6    public SpatialGrid(int cellSize) {
7        this.cellSize = cellSize;
8    }
9
10    private long cellKey(int cx, int cy) {
11        return ((long) cx << 32) | (cy & 0xFFFFFFFFL);
12    }
13
14    public void insert(Rectangle r) {
15        int startX = (int)(r.x / cellSize);
16        int startY = (int)(r.y / cellSize);
17        int endX = (int)((r.x + r.width) / cellSize);
18        int endY = (int)((r.y + r.height) / cellSize);
19
20        for (int cx = startX; cx <= endX; cx++) {
21            for (int cy = startY; cy <= endY; cy++) {
22                cells.computeIfAbsent(cellKey(cx, cy), k -> new ArrayList<>())
23                     .add(r);
24            }
25        }
26    }
27
28    public List<Rectangle> getPotentialCollisions(Rectangle r) {
29        // Return only objects in the same grid cells
30        Set<Rectangle> candidates = new HashSet<>();
31        int startX = (int)(r.x / cellSize);
32        int startY = (int)(r.y / cellSize);
33        int endX = (int)((r.x + r.width) / cellSize);
34        int endY = (int)((r.y + r.height) / cellSize);
35
36        for (int cx = startX; cx <= endX; cx++) {
37            for (int cy = startY; cy <= endY; cy++) {
38                List<Rectangle> cell = cells.get(cellKey(cx, cy));
39                if (cell != null) candidates.addAll(cell);
40            }
41        }
42        candidates.remove(r);
43        return new ArrayList<>(candidates);
44    }
45}

Common Pitfalls

  • Coordinate system: Screen coordinates typically have y increasing downward. Mathematical coordinates have y increasing upward. Make sure your collision conditions match your coordinate system.
  • Edge-touching: The conditions above use strict inequality (<, >), so rectangles that touch edges without overlapping are not considered colliding. Use <= if you want edge-touching to count.
  • Integer overflow: java.awt.Rectangle uses int fields. Very large coordinates or sizes can overflow. Use Rectangle2D.Double for large worlds.
  • Moving objects: Fast-moving objects can pass through thin obstacles between frames (tunneling). For high-speed objects, use swept collision detection or reduce the time step.
  • Rotated rectangles: AABB only works for axis-aligned rectangles. For rotated rectangles, use the Separating Axis Theorem (SAT) instead.

Summary

  • Two axis-aligned rectangles collide when they overlap on both axes — four simple comparisons
  • Use java.awt.Rectangle.intersects() for built-in support or implement your own for custom types
  • Calculate minimum translation vector to resolve collisions by pushing back on the axis with less overlap
  • Use spatial partitioning (grids, quadtrees) when checking many objects to avoid O(n²) pair checks
  • AABB does not handle rotated rectangles — use SAT for that case

Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Data Structures & Algorithms practice on Codemia

Step through 300+ coding interview problems with animated visualisers that show the data structure changing as the code runs. The Blind 75 are free.

Practice algorithms