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

@certe/atmos-core

v0.8.8

Published

Component model, scene graph, game loop, and serialization for the Atmos Engine

Readme

🧩 @certe/atmos-core

The heart of the Atmos Engine — game loop, scene graph, component model, input, and serialization. This package has no rendering or physics code; it defines the contracts that all other packages build on.


🔑 Key Concepts

Component Lifecycle

Every component follows a strict lifecycle:

onAwake()  →  onStart()  →  onUpdate(dt)  →  onRender()  →  onDestroy()
   once          once        every frame      every frame      once
import { Component } from '@certe/atmos-core';

class Rotator extends Component {
  speed = 1;

  onUpdate(dt: number) {
    const r = this.gameObject.transform.rotation;
    Quat.rotateY(r, r, this.speed * dt);
    this.gameObject.transform.rotation = r; // triggers dirty flag
  }
}

GameObject & Transform

Every GameObject has a unique ID and always carries a Transform:

const cube = new GameObject('Cube');
cube.transform.setPosition(0, 5, 0);
cube.transform.setScale(2, 2, 2);

const child = new GameObject('Child');
child.setParent(cube); // inherits parent's world matrix

Transform uses a dirty flag system — local matrix recomputes only when TRS changes, and world matrix propagates through the parent chain.


🚀 Quick Start

import { Engine, Scene, GameObject, Time, Input } from '@certe/atmos-core';

const scene = new Scene();
const player = new GameObject('Player');
player.addComponent(MyController);
scene.add(player);

const engine = new Engine();
engine.start(scene);

📖 API Overview

Engine

The main loop orchestrator. Frame order:

Input.endFrame() → Physics.step() → Scene.updateAll(dt) → Render

| Method / Property | Description | |---|---| | start(scene) | Begin the game loop | | stop() | Stop the loop | | paused | Get/set — skips physics & scripts when true | | scene | Set to swap scenes at runtime | | setRenderer(r) | Provide a renderer implementation | | setPhysics(p) | Provide a physics stepper |

Scene

Container for GameObjects. Manages lifecycle propagation.

| Method | Description | |---|---| | add(obj) | Add a GameObject (and children) | | remove(obj) | Remove and call onDestroy on all components | | getAllObjects() | ReadonlySet<GameObject> | | findAll<T>(Ctor) | Find all components of a type | | awakeAll() / startAll() / updateAll(dt) / renderAll() | Lifecycle phases |

Input

Keyboard and mouse state, frame-deterministic:

if (Input.getKeyDown('Space')) jump();
if (Input.getKey('KeyW')) moveForward(dt);
const { x, y } = input.mousePosition;

Time

Time.deltaTime   // seconds since last frame (clamped to 100ms)
Time.time        // accumulated seconds
Time.frameCount  // integer frame counter

Component Registry

Register components at startup so the editor and serializer know about them:

import { registerComponent } from '@certe/atmos-core';

registerComponent(Rotator, {
  name: 'Rotator',
  properties: [
    { key: 'speed', type: 'number', default: 1, min: 0, max: 10 },
  ],
});

Scene Serialization

import { serializeScene, deserializeScene } from '@certe/atmos-core';

const data = serializeScene(scene);           // → JSON-safe SceneData
const restored = deserializeScene(data, ctx); // → new Scene

The serializer handles Transform, parent-child relationships, component data, and gameObjectRef resolution across a 3-pass process.


🧠 Design Principles

  • No circular dependencies — Component ↔ Scene link uses late binding
  • Deterministic execution — fixed update order, frame-deterministic input
  • Composition over inheritance — components attached to GameObjects
  • Strict TypeScript — no any, all public APIs typed

📁 Structure

packages/core/src/
  index.ts              # Public API
  component.ts          # Abstract Component base class
  game-object.ts        # GameObject with Transform
  transform.ts          # TRS + dirty flags + hierarchy
  scene.ts              # Scene graph + lifecycle
  engine.ts             # Main loop
  input.ts              # Keyboard/mouse
  time.ts               # Frame timing
  component-registry.ts # Property metadata
  scene-serializer.ts   # Save/load scenes

🔗 Dependencies

  • @certe/atmos-math — Vec3, Mat4, Quat for Transform