1.0.0 • Published 1 year ago

@rbxts/delta v1.0.0

Weekly downloads
-
License
MIT
Repository
github
Last release
1 year ago

Delta

A deterministic physics simulation library for Roblox written in TypeScript.

Table of Contents

Overview

The library provides a modular, deterministic physics simulation system for Roblox. The library operates entirely in world units (meters, m/s, m/s²) and features:

  • Translation and Rotation: Euler integration for position, velocity, and rotation.
  • Collision Detection: Supports both simple AABB (for point and box collisions) and oriented bounding box (OBB) collision detection for static, rotated objects.
  • Collision Resolution: Impulse-based resolution with restitution and friction impulses.
  • Friction & Damping: Applies friction and damping on dynamic objects when in contact with static objects.
  • Customizable Time Control: Fixed time step integration with a SetTime method for fast-forwarding the simulation.

Features

  • World-Unit Integration: All positions, velocities, and forces are expressed in world units.
  • Oriented Static Collision: Supports collisions with rotated static platforms via OBB calculations (no physical part is required).
  • Dynamic Collision Resolution: Uses impulse-based resolution with friction between dynamic objects.
  • Rotational Dynamics: Updates rotation, angular velocity, and angular acceleration.
  • Time Control: A fixed time-step integrator and a SetTime method that advances simulation until the target time is reached.

Installation

TypeScript

  1. In the terminal run: npm i @rbxts/delta

Luau

  1. For luau you must use the pesde package manager
  2. To add the package run: pesde add prismatyx/delta
  3. to install the package run pesde install

Usage

TypeScript

import { PhysicsEngine, PhysicsObject } from "@rbxts/delta";

// Create engine and start it.
const engine = new PhysicsEngine();
engine.Start();

// Create a ball.
const ball = new PhysicsObject(
	"ball",
	{
		mass: 10,
		friction: 0.5,
		elasticity: 0.8,
		collisionMethod: "box",
		size: new Vector3(2, 2, 2),
		ignoreGlobalForces: false,
	},
	{
		position: new Vector3(0, 10, 0),
		velocity: new Vector3(0, 0, 0),
		acceleration: new Vector3(0, 0, 0),
		forces: [],
	},
);

// Create a static platform.
const platform = new PhysicsObject(
	"platform",
	{
		mass: 1e9,
		friction: 0.4,
		elasticity: 0.4,
		collisionMethod: "box",
		size: new Vector3(20, 2, 20),
		ignoreGlobalForces: true,
	},
	{
		position: new Vector3(0, 0, 0),
		velocity: new Vector3(0, 0, 0),
		acceleration: new Vector3(0, 0, 0),
		forces: [],
	},
);

// Add objects to the engine.
engine.AddObject("ball", ball);
engine.AddObject("platform", platform);

// Add gravity.
engine.AddGlobalForce("gravity", new Vector3(0, -9.81, 0));

// Simulate.
game.GetService("RunService").Stepped.Connect((_, dt) => {
	engine.Step(dt);
});

Luau

local delta = require(game.ReplicatedStorage.delta)
local PhysicsEngine = delta.PhysicsEngine
local PhysicsObject = delta.PhysicsObject

local engine = PhysicsEngine.new()
engine:Start()

local ball = PhysicsObject.new("ball", {
	mass = 10,
	friction = 0.5,
	elasticity = 0.8,
	collisionMethod = "box",
	size = Vector3.new(2, 2, 2),
	ignoreGlobalForces = false,
}, {
	position = Vector3.new(0, 10, 0),
	velocity = Vector3.new(0, 0, 0),
	acceleration = Vector3.new(0, 0, 0),
	forces = {}
})

local platform = PhysicsObject.new("platform", {
	mass = 1e9,
	friction = 0.4,
	elasticity = 0.4,
	collisionMethod = "box",
	size = Vector3.new(20, 2, 20),
	ignoreGlobalForces = true,
}, {
	position = Vector3.new(0, 0, 0),
	velocity = Vector3.new(0, 0, 0),
	acceleration = Vector3.new(0, 0, 0),
	forces = {}
})

engine:AddObject("ball", ball)
engine:AddObject("platform", platform)
engine:AddGlobalForce("gravity", Vector3.new(0, -9.81, 0))

game:GetService("RunService").Stepped:Connect(function(_, dt)
	engine:Step(dt)
end)

API Documentation

PhysicsObject

  • Constructor:
    new(id: string, properties: PhysicsObjectProperties, state?: ObjectState, part?: BasePart)
    Creates a new physics object.
    Properties:

    • mass: Mass of the object.
    • friction: Friction coefficient (default 0.3).
    • damping: Additional damping for contact with static objects (default 0.5).
    • elasticity: Restitution coefficient (default 0.4).
    • momentOfInertia: Rotational inertia (default 1).
    • collisionMethod: "box", "point", or "none".
    • size: For box collisions, the dimensions of the hitbox.
    • ignoreGlobalForces: If true, the object will not receive global forces (e.g. static objects).
  • ApplyForce(force: Vector3, offset?: Vector3): void
    Applies a force (and optional offset for torque) to the object.

  • Update(dt: number): void
    Updates the object state (position, velocity, rotation) over a time step.

  • GetWorldPosition(): Vector3
    Returns the current world position.

  • GetState(): PhysicsObjectState
    Returns the current state (position, velocity, acceleration).

  • Destroy(): void
    Cleans up the object.

PhysicsEngine

  • Constructor:
    new()
    Creates a new physics engine instance.

  • Start(): void
    Starts the simulation.

  • Stop(): void
    Stops the simulation.

  • Step(realDeltaTime: number): void
    Advances the simulation by the given delta time (adjusted by timeScale).

  • SetTime(targetTime: number): void
    Advances the simulation until the current time reaches the target time.

  • AddGlobalForce(name: string, accel: Vector3): void
    Adds a global force (provided as acceleration) to all dynamic objects.

  • AddObject(id: string, object: PhysicsObject): void
    Adds a physics object to the simulation.

  • DestroyObject(id: string): void
    Removes and destroys the object with the given id.

  • GetObject(id: string): PhysicsObject | undefined
    Retrieves an object by its id.

  • GetObjects(): PhysicsObject[]
    Returns all physics objects.

Notes

  • Rotational Collisions:
    The library currently updates rotation via applied torques but doesn't automatically compute collision based torques. This will be added sometime in the future

  • Performance:
    Point collision detection is simpler and is more performant than box collision. However, the performance difference is generally negligible unless you have a very large number of objects

  • Customization:
    Adjust parameters (mass, friction, damping, elasticity, fixedDeltaTime) to tune the simulation behavior to your needs

License

This project is licensed under the MIT License. See the LICENSE file for details.