Kinetics.ts Physics Engine

repository·main·Indexed 42 days ago

https://github.com/altanis/kinetics

A high-performance 2D physics engine for JavaScript and TypeScript applications, featuring a System/Entity architecture, optimized collision detection via SpatialHashGrid, and support for both frontend and backend environments. Version 1.4.1 includes core components like System, Circle, and Vector, along with comprehensive configuration interfaces for rendering, cameras, and entity physics.

Tokens
4.7K
Snippets
12
Records
21
Agent score
50%

What's inside Kinetics

  1. Install kinetics.ts

    main

    You can install kinetics.ts using npm for server-side or web framework environments, or use a CDN script tag for vanilla HTML/CSS/JS projects.

    npm Installation

    npm install kinetics.ts

    CDN Installation (Vanilla JS)

    Include the following script tag in your HTML. All engine classes will be available under the Kinetics namespace (e.g., window.Kinetics.System).

    <script src="https://cdn.jsdelivr.net/gh/Altanis/kinetics-ts@latest/build/kinetics.min.js" defer></script>
  2. Basic usage of the kinetics.ts engine

    main

    To use the engine, initialize a System with configuration options, create entities (such as Circle), and run a loop that calls system.update(dt) to advance the physics simulation.

    Core Components

    • System: The main engine instance that manages entities and physics calculations.
    • Circle: A type of entity representing a circular body.
    • Vector: A utility class for handling 2D coordinates and physics vectors.

    Simulation Loop and Error Correction

    When running the simulation, calculate a dt (delta time) value to act as an error correction mechanism. This scales time-variant operations if the interval does not run exactly at the specified MSPT (milliseconds per tick).

    /** Create a system with 100 circles. */
    const { System, Circle, Vector } = require("kinetics.ts");
    
    const system = new System({
        tickRate: 60,
        friction: 0.1,
        collisionInfo: {
            cellSize: 6,
        },
        bounds: new Vector(1920, 1080)
    });
    
    for (let i = 0; i < 100; i++) {
        const radius = 10;
    
        const entity = new Circle(
            {
                form: {
                    vertices: [new Vector(0, 0)],
                },
                radius,
                mass: 10,
                speed: 1,
                rotate: false,
                elasticity: 1,
                angularSpeed: 1,
            },
            system
        );
        system.addEntity(entity);
    }
    
    /** The number of ticks the engine will run per second. */
    const FPS = 60;
    /** The ideal time it will take for one system update. */
    const MSPT = 1000 / FPS;
    
    /** The timestamp of the last engine update. */
    let lastTimestamp = 0;
    
    setInterval(() => {
        let currentTime = performance.now();
        let deltaTime = currentTime - lastTimestamp; // time in between two ticks
        lastTimestamp = currentTime;
    
        // `dt` is a sort of error correction mechanism.
        // In the event the interval doesn't run at the specified
        // MSPT, `dt` corrects all time variant operations by scaling
        // them by its value.
        const dt = Math.min((deltaTime / MSPT), 3);
    
        system.update(dt);
    }, MSPT);
  3. Access the Kinetics public API

    main

    Kinetics provides a centralized entrypoint for managing physics systems, entities, and collisions. You can import the core modules directly into your project or, if running in a web browser environment, access them via the global window.Kinetics object.

    Core modules include:

    • System: The main engine controller.
    • Entity & Circle: Base classes for creating physical objects.
    • Collision: Contains CollisionResolver and SpatialHashGrid for handling physics interactions.
    • Camera, Renderer, Vector: Utility classes for visualization and math.
    import { System, Entity, Circle, Collision, Vector } from 'kinetics';
    
    // Example usage pattern
    const system = new System();
    const pos = new Vector(0, 0);
    const myCircle = new Circle(pos, 10);
  4. Configure the System constructor

    main

    The System class is the central controller of the physics engine. It accepts an options object to define the simulation environment.

    Configuration Options

    • tickRate: The number of physics ticks per second.
    • friction: Global friction coefficient.
    • collisionInfo: Object containing collision detection settings.
      • cellSize: Size of the cells used for broadphase collision detection.
    • bounds: A Vector defining the dimensions of the simulation area.
    const system = new System({
        tickRate: 60,
        friction: 0.1,
        collisionInfo: {
            cellSize: 6,
        },
        bounds: new Vector(1920, 1080)
    });
  5. Configure Entity Rendering with EntityRenderingConfig

    main

    The EntityRenderingConfig interface defines the visual appearance of an individual entity.

    Properties:

    • strokeColor: The color of the entity's outline. Accepts Colors enum values or a string. If not specified, the entity is not stroked unless both fillColor and strokeColor are missing, in which case it defaults to Colors.Black.
    • fillColor: The color of the entity's interior. Accepts Colors enum values or a string. If not specified, the entity is not filled. If both fillColor and strokeColor are missing, it defaults to Colors.Black.
    • strokeWidth: The width of the outline. Defaults to 1.
    • glowIntensity: The intensity of the entity's glow. If not specified, no glow is applied.
    • glowColor: The color of the glow. Accepts Colors enum values or a string. If not specified, it uses the strokeColor.
    • hooks: Lifecycle hooks for the entity renderer:
      • preRender: A function called before rendering the entity. Receives (entity: Entity, context: CanvasRenderingContext2D).
      • postRender: A function called after rendering the entity. Receives (entity: Entity, context: CanvasRenderingContext2D).
  6. Configure System Rendering with SystemRenderingConfig

    main

    The SystemRenderingConfig interface defines how the system's background and grid are drawn on a canvas.

    Properties:

    • canvas: The HTMLCanvasElement to draw on (required).
    • background: The background color. Accepts Colors enum values or a string. Defaults to Colors.White.
    • gridColor: The color of the grid lines. Accepts Colors enum values or a string. Defaults to Colors.Black.
    • gridSize: The length of one side of the grid squares. If omitted, no grid is drawn.
    • gridWidth: The width of the gridlines. Defaults to 1.
    • hooks: Lifecycle hooks for the renderer:
      • preRender: A function called before rendering. Receives context: CanvasRenderingContext2D.
      • postRender: A function called after rendering. Receives context: CanvasRenderingContext2D.
  7. Configure the System with SystemConfig

    main

    The SystemConfig interface defines the global settings for a Kinetics system, including physics properties, dimensions, camera settings, and rendering configurations.

    Key properties include:

    • collisionInfo: Configures the collision engine. If using hashgrids, set cellSize (defaults to 12, representing 2 ** x game units).
    • dimensions: The size of the system using a VectorLike object.
    • friction: Movement friction (defaults to 0.1).
    • gravity: System gravity (defaults to 0).
    • camera: An optional CameraConfig object.
    • render: An optional SystemRenderingConfig object.
  8. Available scripts for development and production

    main

    This project uses Create React App. You can manage the application lifecycle using the following npm scripts in the project directory:

    # Runs the app in development mode at http://localhost:3000
    npm start
    
    # Launches the test runner in interactive watch mode
    npm test
    
    # Builds the app for production into the `build` folder
    # Includes minification and optimized bundling
    npm run build
    
    # Removes the single build dependency and copies all configuration files
    # (webpack, Babel, ESLint, etc.) directly into the project for full control
    # WARNING: This is a one-way operation and cannot be undone.
    npm run eject
  9. Implement a CollisionManager

    main

    If you are building a custom collision system or extending the engine, you must implement the CollisionManager interface. It requires three methods:

    • insert(x, y, w, h, id): Adds an entity to the manager using its bounding box and a unique ID.
    • query(): Executes the collision detection and resolution logic.
    • clear(): Resets the collision manager state.
  10. Configure a Circle using CircleConfig

    main

    For entities that are strictly circular, use the CircleConfig interface. It extends EntityConfig and requires a radius property.

    import { CircleConfig } from "../typings/Interfaces";
    
    const circle: CircleConfig = {
      radius: 25,
      mass: 2,
      elasticity: 0.9,
      static: false,
      form: { radius: 25 } // Note: form must also reflect the shape
    };
  11. Use the Collision module

    main

    The Collision namespace provides tools for managing and resolving physical interactions between entities. It exports:

    • CollisionResolver: Handles the logic for resolving collisions.
    • SpatialHashGrid: A spatial partitioning structure used to optimize collision detection performance.
    import { Collision } from 'kinetics';
    
    const resolver = new Collision.CollisionResolver();
    const grid = new Collision.SpatialHashGrid();