Use check2d in the browser via ESM
mainFor browser-based projects, you can import check2d directly using an ESM provider like esm.sh.
import { System } from 'https://esm.sh/check2d'repository·main·Indexed 42 days ago
https://github.com/nenjack/check2dA high-performance 2D collision detection library for real-time games and simulations. It utilizes Bounding Volume Hierarchy (BVH) for quick tree trimming and the Separating Axis Theorem (SAT) for accurate detection. Version 9.36.4 supports RayCasting, offsets, rotation, scaling, and group filtering for shapes including Boxes, Circles, and Polygons.
For browser-based projects, you can import check2d directly using an ESM provider like esm.sh.
import { System } from 'https://esm.sh/check2d'You can debug your collision system by drawing bodies or the internal BVH structure directly onto a HTML5 <canvas> context.
// Draw all bodies in the system
context.beginPath()
system.draw(context)
context.stroke()
// Draw the BVH bounding boxes
context.beginPath()
system.drawBVH(context)
context.stroke()You can install check2d using yarn to add it to your project.
yarn add check2dTo begin using check2d, instantiate a System. The System manages the Bounding Volume Hierarchy (BVH) and handles collision detection logic.
const { System } = require('check2d')
const system = new System()Collision filtering is handled via a group property on bodies. The group is a 32-bit integer where:
category.mask (which categories this body can interact with).Two bodies can interact if (categoryA & maskB) !== 0 and (categoryB & maskA) !== 0.
groupBits(category, mask): Creates a group integer from category and mask bits.bin2dec(binary): Converts a binary string (e.g., '0001') to a decimal number.ensureNumber(input): Ensures the input is a number, converting binary strings if necessary.// Example: Setting up collision groups
// Category 1, Mask 2
const group1 = groupBits(0x0001, 0x0002);
// Category 2, Mask 1
const group2 = groupBits(0x0002, 0x0001);
const body1 = new Circle({ x: 0, y: 0 }, 10, { group: group1 });
const body2 = new Circle({ x: 5, y: 5 }, 10, { group: group2 });
// canInteract(body1, body2) would return trueBoth Circle and Polygon use a dirty flag to optimize performance. When a body's position, angle, scale, or points change, it is marked as dirty.
markAsDirty(updateNow): If updateNow is true, the body is immediately updated in the collision system. If false, it is simply flagged to be updated during the next collision check.updateBody(updateNow): Synchronizes the body with the collision system (e.g., updating AABB or convex polygon positions).Collision filtering is handled via a 32-bit integer group. The high 16 bits represent the category and the low 16 bits represent the mask.
groupBits(category, mask) to generate a group value.ensureNumber(input) to handle both numeric and binary string inputs.canInteract(bodyA, bodyB) to determine if two bodies are allowed to collide based on their groups.import { groupBits, canInteract } from './utils';
// Define categories and masks using binary strings
const playerGroup = groupBits('00000000_00000001', '11111111_11111111');
const wallGroup = groupBits('00000000_00000010', '00000000_00000001');
// Check if they can interact
const collisionAllowed = canInteract({ group: playerGroup }, { group: wallGroup });The check2d library provides a comprehensive suite of tools for 2D collision detection, body manipulation, and raycasting. You can import all core functionality from the main entrypoint. The library is organized into several functional areas:
Circle, Ellipse, Polygon, Box, Point, and Line.import * as check2d from 'check2d';
// Accessing components via the main namespace
const circle = new check2d.Circle(...);
const intersection = check2d.intersectSomething(...);Bodies in check2d support transformations including position, rotation, and scale. To optimize performance, changes are batched. When you modify a body, pass false as the last argument to prevent immediate updates, then call body.updateBody() once all transformations are complete to apply them in a single batch.
// Batching transformations for performance
box.setPosition(10, 5, false)
box.setAngle(Math.PI / 4, false)
box.setScale(2, 1, false)
box.move(1, false)
// Apply all changes at once
box.updateBody()The System provides methods to check for collisions between bodies:
system.checkAll(callback): Checks all bodies in the system and executes the callback for every collision result found.system.checkOne(body, callback): Checks a specific body against all other bodies in the system.system.separate(): An optional method to automatically handle separation of colliding bodies.To find the exact points where two bodies are colliding, use system.getCollisionPoints(bodyA, bodyB).
// Check all collisions in the system
system.checkAll((result) => {
console.log(result)
})
// Check collisions for a specific body
system.checkOne(box, (result) => {
console.log(result)
})
// Automatically separate colliding bodies
system.separate()
// Get specific collision points from a result
const points = system.getCollisionPoints(result.a, result.b)Use system.raycast to detect collisions along a line segment. The method takes a starting point, an end point, and an optional filter function. If a hit is detected, it returns an object containing the point of impact and the body hit.
const hit = system.raycast(
{ x: 0, y: 0 }, // Start point
{ x: 0, y: -10 }, // End point
(body) => true // Filter function (returns true to include body)
)
if (hit) {
const { point, body } = hit
console.log(point, body)
}You can create various shape types such as Box, Circle, and Polygon. While some shapes can be instantiated directly, it is recommended to use the system.createBox method (or similar factory methods) to ensure they are properly integrated with the system. After creation, use system.insert(body) to add the body to the collision detection engine.
const { Box, Circle, Polygon } = require('check2d')
// Using a factory method from the system
const box = system.createBox({ x: 0, y: 0 }, 10, 10)
// Instantiating a shape directly
const circle = new Circle({ x: 5, y: 0 }, 5)
// Adding the body to the system for collision checks
system.insert(circle)