# Understanding physics continuous collision detection using swept AABB method and Minkowski sum – Part 2: both bodies are moving

I had a lot of positive feedback with to post Understanding physics continuous collision detection using swept AABB method and Minkowski sum, but in the example there was only one moving body, while the other did not move.

What if there are two moving bodies? Does Minkowski sum still apply?

Let’s see what happens when two bodies move:

In the above picture, Body A is moving towards Body B, and Body Bis moving towards Body A, and it would be too difficult to say when – or even if – these two bodies collide, if we don’t pretend only one body is moving, with a relative velocity which we can get by subtracting, for instance, Body B velocity from Body A velocity, this way:

Now we can say we have only one body moving, and we can build the Minkowski Sum line explained in previous step:

Allright, we also have a collision point. Let’s strip everything but velocity vector and collision point:

If we define movement start with zero and movement end with one, collision point will be somewhere between 0 and 1 on the velocity vector.

This is the amount of velocity vector needed by both bodies to collide, this way:

So we can start the simulation, which at low velocities works well both with Arcade Physics and Swept AABB:

Click or touch the canvas to make simulation start. You’ll probably won’t notice differences between Arcade Physics and Swept AABB.

Things change at higher speeds:

Click or touch the canvas to make simulation start. While Swept AABB still handles the collision, Arcade Physics fails.

Let’s see the source code of this experiment, built around a simple class:

### index.html

The webpage which hosts the game, just the bare bones of HTML.

Also look at the thegame div, this is where the game runs.

<!DOCTYPE html>
<html>
<script src = "main.js"></script>
<body>
<div id = "thegame"></div>
</body>
</html>

### main.ts

The main TypeScript file, the one called by index.html.

Here we import most of the game libraries and define Scale Manager object.

Here we also initialize the game itself.

// MAIN GAME FILE

// modules to import
import Phaser from 'phaser';
import { PlayGame} from './playGame';

// object to initialize the Scale Manager
const scaleObject: Phaser.Types.Core.ScaleConfig = {
mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_BOTH,
parent: 'thegame',
width: 800,
height: 416
}

// game configuration object
const configObject: Phaser.Types.Core.GameConfig = {
type: Phaser.AUTO,
scale: scaleObject,
scene: [PlayGame],
physics: {
}
}

// the game itself
new Phaser.Game(configObject);

### playGame.ts

In playGame class we place all stuff on the canvas, make all stuff work and handle user input

// THE GAME ITSELF

import { PhaserSweptAABB } from "./phaserSweptAABB";
import PhysicsBox from "./physicsBox";

// this class extends Scene class
export class PlayGame extends Phaser.Scene {

// these are my physics box and wall
box: PhysicsBox;
wall: PhysicsBox;

// these are the Arcade physics box and wall

// speed of the projectile, in pixels per second
projectileSpeed: number = 4000;

// speed of the wall, in pixels per second
wallSpeed: number = -2000;

// our Swept AABB class
AABB: PhaserSweptAABB;

// constructor
constructor() {
super({
key: 'PlayGame'
});
}

// method to be called once the class preloads

}

// method to be called once the class has been created
create(): void {

// create a new instance of Swept AABB class
this.AABB = new PhaserSweptAABB();

// creation of my physics box and wall
this.box = new PhysicsBox(this, 20, 128, 'dot');
this.wall = new PhysicsBox(this, 780, 128, 'wall');

// creation of Arcade box and wall

// set Arcade box and wall immovable

// input listener to fire the bullet
this.input.on('pointerdown', this.fireBullets, this);

// just some text to display informaiton
this.add.text(20, 195, 'Bullet Speed: ' + this.projectileSpeed + ' pixels/s, Wall speed: ' + this.wallSpeed + ' pixels/s', {
fontSize: '20px'
});
fontSize: '24px'
});
fontSize: '24px'
});
}

// FIRE!!!
fireBullets() {

// fire both my box and Arcade physics box
this.box.setVelocity(this.projectileSpeed, 0);

// fire both my wall and Arcade physics wall
this.wall.setVelocity(this.wallSpeed, 0);
}

// method to be executed at each frame
update(totalTime: number, deltaTime: number): void {

// Swept AABB collider, to execute only if at least one body is moving
if (this.box.isMoving() || this.wall.isMoving()) {

// check collision time, can be any number between 0 (already colliding) and 1 (never colliding in this frame)
let collisionTime: number = this.AABB.checkCollisionTime(this.box, this.wall, deltaTime);

// update box and wall positions according to collision time
this.box.updatePosition(deltaTime * collisionTime);
this.wall.updatePosition(deltaTime * collisionTime);

// if collision time is less than one, that is there was a collision...
if (collisionTime < 1) {

// stop both box and wall
this.box.stopMoving();
this.wall.stopMoving();
}
}

// just stop both bodies
b1.setVelocity(0, 0);
b2.setVelocity(0, 0)
});
}
}

### physicsBox.ts

A simple extension of Phaser Sprite class to store velocity.

// PhysicsBox class extends Phaser Sprite class
export default class PhysicsBox extends Phaser.GameObjects.Sprite {

// vector containing x and y velocity
velocity: Phaser.Math.Vector2;

// constructor - arguments: the scene, x and y position and texture key
constructor(scene: Phaser.Scene, x: number, y: number, key: string) {
super(scene, x, y, key);

// add sprite to the scene

// physics object has no velocity at the beginning
this.velocity = new Phaser.Math.Vector2(0, 0);
}

// set body velocity - arguments: x and y velocity
setVelocity(x: number, y: number): void {

// update velocity property
this.velocity.x = x;
this.velocity.y = y;
}

// method to check if the body is moving
isMoving(): boolean {
return this.velocity.x != 0 || this.velocity.y != 0;
}

// method to stop the object
stopMoving(): void {
this.setVelocity(0, 0);
}

// method to update physics box position - arguments: the amount of milliseconds
updatePosition(milliseconds: number): void {

this.x += this.velocity.x * (milliseconds / 1000);
this.y += this.velocity.y * (milliseconds / 1000);
}
}

### phaserSweptAABB.ts

The core of the script, the methods responsible of collision detection

import PhysicsBox from "./physicsBox";

export class PhaserSweptAABB {

// method to check if two bodies collide within a certain time - arguments: the two bodies and a time
checkCollisionTime(sprite1: PhysicsBox, sprite2: PhysicsBox, time: number): number {

// determine relative speed subtracting the two speed vectors
let relativeSpeed: Phaser.Math.Vector2 = new Phaser.Math.Vector2(sprite1.velocity.x, sprite1.velocity.y).subtract(new Phaser.Math.Vector2(sprite2.velocity.x, sprite2.velocity.y));

// get movement line, from box origin to box relative destination
let movementLine: Phaser.Geom.Line =  new Phaser.Geom.Line(sprite1.x, sprite1.y, sprite1.x + relativeSpeed.x * (time / 1000), sprite1.y + relativeSpeed.y * (time / 1000));

// Minkowski rectangle built inflating the sprite bodies
let minkowskiRectangle: Phaser.Geom.Rectangle = this.minkowskiSum(sprite1, sprite2);

// array to store all intersection points between movement line and Minkowski rectangle
let intersectionPoints: Phaser.Geom.Point[] = [];

// get all intersection points between movement line and Minkowski rectangle, then store them into intersectionPoints array
Phaser.Geom.Intersects.GetLineToRectangle(movementLine, minkowskiRectangle, intersectionPoints);

// different cases according to intersection points vector length
switch (intersectionPoints.length) {

// no intersection points: return 1, that is objects can move for the entire interval
case 0:
return 1;

// only one intersection point: this is the collision point
case 1:

// get the collision line
let collisionLine: Phaser.Geom.Line = new Phaser.Geom.Line(sprite1.x, sprite1.y, intersectionPoints[0].x, intersectionPoints[0].y);

// return the ratio between collision line and movement line
return Phaser.Geom.Line.Length(collisionLine) / Phaser.Geom.Line.Length(movementLine);

// more than one intersection point: collision point is the closest to moving body
default:

// set the minimum distance to Infinity, the highest number
let minDistance: number = Infinity;

// set minimum index to zero (first element)
let minIndex: number = 0;

// looping through all instersection points
for (let i: number = 0; i < intersectionPoints.length; i ++) {

// get distance between body and points
let distance: number = Phaser.Math.Distance.Between(sprite1.x, sprite2.y, intersectionPoints[i].x, intersectionPoints[i].y);

// is distance less then minimum distance?
if (distance < minDistance) {

// update minimum index
minIndex = i;

// update minimum distance
minDistance = distance;
}
}

// get the collision line
let collisionLine2: Phaser.Geom.Line = new Phaser.Geom.Line(sprite1.x, sprite1.y, intersectionPoints[minIndex].x, intersectionPoints[minIndex].y);

// return the ratio between collision line and movement line
return Phaser.Geom.Line.Length(collisionLine2) / Phaser.Geom.Line.Length(movementLine);
}
}

// method to perform the Minkowski sum between two Sprites - argument: the sprites
minkowskiSum(sprite1: PhysicsBox, sprite2: PhysicsBox): Phaser.Geom.Rectangle {

// get bounding boxes
let spriteBounds1: Phaser.Geom.Rectangle = sprite1.getBounds();
let spriteBounds2: Phaser.Geom.Rectangle = sprite2.getBounds();

// new rectangle leftmost point
let newLeft: number = spriteBounds2.left - spriteBounds1.width / 2;

// new rectangle upper point
let newTop: number = spriteBounds2.top - spriteBounds1.height / 2;

// new rectangle width
let newWidth: number = spriteBounds1.width + spriteBounds2.width;

// new rectangle height
let newHeight: number = spriteBounds1.height + spriteBounds2.height;

// return the inflated rectangle
return new Phaser.Geom.Rectangle(newLeft, newTop, newWidth, newHeight);
}
}

And we managed to build a continuous collision detection script capable of handling to fast moving objects. Now we have to put everything together and apply to a real world example, meanwhile download the source code of the entire project.

215 GAME PROTOTYPES EXPLAINED WITH SOURCE CODE
// 1+2=3
// 10000000
// 2 Cars
// 2048
// Avoider
// Ballz
// Block it
// Blockage
// Bloons
// Boids
// Bombuzal
// Breakout
// Bricks
// Columns
// CubesOut
// Dots
// DROP'd
// Dudeski
// Eskiv
// Filler
// Fling
// Globe
// HookPod
// Hundreds
// InkTd
// Iromeku
// Lumines
// Magick
// MagOrMin
// Maze
// Memdot
// Nano War
// Nodes
// o:anquan
// Ononmin
// Pacco
// Phyballs
// Platform
// Poker
// Pool
// Poux
// Pudi
// qomp
// Racing
// Renju
// SameGame
// Security
// Sling
// Slingy
// Sokoban
// Splitter
// Sproing
// Stack
// Stairs
// Stringy
// Sudoku
// Tetris
// Threes
// Toony
// Turn
// TwinSpin
// vvvvvv
// Wordle
// Worms
// Yanga
// Zhed
// zNumbers