npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

kinetik-engine

v0.1.35

Published

Kinetik engine and project initializer for Three.js games

Readme

Kinetik Engine

A lightweight 3D game engine built on Three.js for desktop (Electron) and mobile (Capacitor/Android). Provides a scene graph, physics, input, level loading, a built-in visual editor, save management, and spatial audio out of the box.


Core Modules

| Module | Purpose | |---|---| | globals.js | Shared gameState object and engine constants | | scene.js | Renderer, camera, lighting, resize, TV knob interaction | | physics.js | Player collision, movement, gravity, interact/tooltip hooks | | input.js | Keyboard/mouse input, freecam, pause toggle hook | | mobileControls.js | Touch joystick and mobile freecam | | levelLoader.js | Loads .json level files, spawns meshes, CSG, image models | | stateManager.js | Stateful object system, enter/exit sounds, level vars | | saveManager.js | Cross-platform save slots (Capacitor Preferences / localStorage) | | editor.js | Full visual level editor (launch with --editor flag) | | settings.js | Persistent player settings |


Quick Start — New Game Project

  1. Create a folder and add Kinetik as a submodule

    mkdir my-game && cd my-game && git init
    git submodule add https://github.com/Jacqueb-1337/kinetik-engine.git src/core
  2. Run the scaffold script — copies electron-main.js, preload.js, package.json, vite.config.js, .gitignore, starter scripts/ files, and all required asset directories into the project root:

    node src/core/init.js
  3. Set your game name — open the generated package.json and update name, build.appId, and build.productName.

  4. Install dependencies:

    npm install
  5. Create your entry point (src/main.js):

    import { gameState } from './core/globals.js';
    import { initScene, updateCamera } from './core/scene.js';
    import { initInput } from './core/input.js';
    import { loadLevel } from './core/levelLoader.js';
    import { update as physicsUpdate } from './core/physics.js';
    import { updateStateAnimations } from './core/stateManager.js';
    
    await initScene();
    initInput();
    await loadLevel('main');
    
    function loop(delta) {
      physicsUpdate(delta);
      updateCamera();
      updateStateAnimations(delta);
      gameState.renderer.render(gameState.scene, gameState.camera);
    }
  6. Create levels/main.json — start with an empty level:

    { "objects": [], "playerStart": { "x": 0, "y": 1, "z": 0 } }
  7. Run:

    npm start          # Electron desktop (game)
    npm run editor     # Electron desktop (visual editor)
    npm run dev        # Browser dev server (open /src/index.html)

Scene & Input Options

Both initScene() and initInput() accept an options object. All options are optional and defaults preserve the historical behavior.

initScene({
  background: 0x17142a,     // scene background color
  fogDensity: 0.016,        // FogExp2 density — pass 0 to disable fog
  fogColor: 0x17142a,       // defaults to background
  antialias: true,          // renderer antialiasing (default false)
  autoFullscreen: false,    // don't request fullscreen on click (default true)
  autoPointerLock: true,    // request pointer lock on click (default true)
  lockKeyboard: true,       // capture Escape via Keyboard Lock API (default true)
});

initInput({
  // Disable or remap the built-in hotkeys (pause/debug/camera/export/freecam).
  // Pass hotkeys: false to disable all of them, or override individually:
  hotkeys: { freecam: false, export: false, cameraMode: 'F6' },
});

Edge-triggered input

initInput() also tracks per-frame pressed/released state so games don't have to build their own edge detection:

import { initInput, endInputFrame } from 'kinetik-engine/input.js';

initInput();

function loop(delta) {
  if (gameState.keysPressed['Space']) jump();       // true only on the press frame
  if (gameState.mousePressed[0]) attack();          // left mouse button edge
  if (gameState.keysReleased['KeyE']) stopChannel();
  // ... game update + render ...
  endInputFrame();  // clear edge state — call once at the END of each frame
}

gameState.keys (held keys) and gameState.mouseButtons (held buttons) remain available for continuous input.


Visual Editor

Launch with the --editor flag:

npm run editor     # equivalent to: electron . --editor

The editor opens initEditor() from editor.js instead of the game loop. From there you can:

  • Place, move, rotate, and scale meshes
  • Paint CSG cuts and boolean geometry
  • Add stateful objects with enter/exit sounds and animations
  • Attach per-scene scripts and per-object scripts from the inspector
  • Set level variables and trigger conditions
  • Place player spawn, save triggers, and interact zones
  • Export the scene back to levels/<name>.json

To open the editor in a new project, follow the Quick Start above and use npm run editor.

The editor also runs in a plain browser (e.g. npm run dev, then open /src/editor.html). Outside Electron it loads levels over HTTP from levels/ and Save downloads the level JSON so you can drop it into your project's levels/ folder. Model/actor import still requires Electron.


Spatial Audio

import { playSound } from './core/stateManager.js';

// Play a sound at a world position — handles distance falloff,
// stereo panning, masterVolume, and ogg/mp3/wav format fallback.
playSound('explosion', new THREE.Vector3(4, 0, -10));

Drop audio files in sounds/ as <name>.ogg, <name>.mp3, or <name>.wav — the engine tries each in that order.


Save System

import { triggerSave, loadSave, registerSaveExtension } from './core/saveManager.js';

// Register custom data to save/restore
registerSaveExtension('myGame', {
  capture: () => ({ score, inventory }),
  restore: (data) => { score = data.score; inventory = data.inventory; }
});

await triggerSave('slot1');
await loadSave('slot1');

Works on desktop (Electron file system) and mobile (Capacitor Preferences) automatically.


Stateful Objects

Objects in level JSON can have a states array. Each state has enter/exit sounds, animations, and variable conditions. Advance state at runtime:

import { advanceObjectState, fireButtonTrigger, setLevelVar } from './core/stateManager.js';

advanceObjectState(myMesh);           // cycle to next state
fireButtonTrigger(myMesh, 'press');   // fire a named trigger
setLevelVar('door_open', true);       // set a level variable

Scripts

Level JSON can also carry scripts:

  • sceneScripts for level-wide modules
  • scripts on any placed object entry

Modules can export:

  • onLoad(ctx)
  • onUpdate(ctx, delta)
  • onStateChange(ctx, nextIdx, prevIdx)
  • onUnload(ctx)

The editor stores these as plain module paths, one per line. Starter examples live in scripts/scene.js and scripts/object.js.

If you build your own main loop, call initLevelScripts() after loadLevel() and updateLevelScripts(delta) once per frame.


Platform

Kinetik targets:

  • Desktop — Electron (Windows / Mac / Linux)
  • Mobile — Capacitor (Android), with touch joystick via mobileControls.js
  • Browser — Vite dev server for rapid iteration