dP dP 88 .d8' 88aaa8P' .d8888b. 88d888b. 88d888b. .d8888b. dP. .dP 88 `8b. 88ooood8 88' `88 88' `88 88' `88 `8bd8' 88 88 88. ... 88 88 88 88. .88 .d88b. dP dP `88888P' dP dP dP `88888P' dP' `dP
Entity-Component-System-based JavaScript framework for real-time applications
- Entity-Component-System Architecture - Highly decoupled design for scalable real-time applications
- Prototype-Based Entities - Define entity templates with multi-inheritance support
- Scene Management - Isolate entities across multiple game states (menus, levels, etc.)
- Entity Pooling - Automatic memory optimization through object reuse
- Event System - Decoupled communication via event broker
- Addon System - Modular organization with namespace support
- TypeScript Support - Full type safety with modern ES6+ syntax
npm install kernoximport { Kernox, KernoAddon } from "kernox"; import { prototypes } from "./setup/prototypes.js"; import { systems } from "./setup/systems.js"; import { collections } from "./setup/collections.js"; // Bundle resources as an addon const myApp: KernoAddon = { name: "myApp", prototypes, systems, collections }; // Initialize and run const app = new Kernox(); app.use(myApp); app.execute();Define entity templates with attributes and collection assignments:
import type { PrototypeSchema, Entity } from "kernox"; interface Player extends Entity { position: { x: number; y: number }; velocity: { x: number; y: number }; hp: number; level: number; } const playerPrototype: PrototypeSchema<Player> = { name: "Player", attributes: { position: { x: 0, y: 0 }, velocity: { x: 0, y: 0 }, hp: 100, level: 1 }, collections: new Set(["Players", "Kinetics", "Renderables"]) };Multi-Inheritance:
const enemyPrototype: PrototypeSchema<Enemy> = { name: "Enemy", attributes: { damage: 10 }, collections: new Set(["Enemies"]), inherits: [kineticPrototype, spritePrototype] // Inherit from multiple prototypes };Group entities for efficient processing:
import { ArrayList } from "kernox"; // Define typed collections class Players extends ArrayList<Player> {} class Enemies extends ArrayList<Enemy> {} class Projectiles extends ArrayList<Projectile> {} export const collections = [Players, Enemies, Projectiles];Usage:
const players = app.collectionManager.get<Players>("Players"); for (const player of players) { console.log(`Player ${player.id} has ${player.hp} HP`); } // Array methods const alive = players.filter(p => p.hp > 0); const count = players.size();Learn more about collections →
Process entities each frame:
import { System } from "kernox"; import type { Kinetics } from "./collections"; class MovementSystem extends System { private kinetics!: Kinetics; init() { this.kinetics = this.getCollection<Kinetics>("Kinetics"); } execute() { for (const entity of this.kinetics) { entity.position.x += entity.velocity.x; entity.position.y += entity.velocity.y; } } }Isolate entities across different game states:
// Switch to menu scene app.collectionManager.switchScene("menu"); app.entityFactory.create("Button", { text: "Start Game" }); // Switch to level1 - menu entities are preserved but hidden app.collectionManager.switchScene("level1"); app.entityFactory.create("Player", { position: { x: 100, y: 100 } }); // Switch back to menu - entities still exist app.collectionManager.switchScene("menu");Scene-Aware Systems:
class RenderSystem extends System { private renderables!: CollectionProxy<Renderables>; init() { // Automatically updates when scenes change this.renderables = this.__kernox.collectionManager.getSmartWrapper<Renderables>("Renderables"); } execute() { for (const entity of this.renderables) { this.draw(entity); } } }Learn more about scene management →
Decouple communication between systems:
// Define event interface PlayerDiedEvent { playerId: string; position: { x: number; y: number }; } // Emit event this.__kernox.eventBroker.emit<PlayerDiedEvent>("player:died", { playerId: player.id, position: player.position }); // Subscribe to event this.__kernox.eventBroker.subscribe<PlayerDiedEvent>("player:died", (data) => { console.log(`Player ${data.playerId} died at`, data.position); this.spawnExplosion(data.position); });Optimize memory usage through automatic entity recycling:
// Create entity (may reuse pooled entity) const enemy = app.entityFactory.create("Enemy", { position: { x: 100, y: 100 } }); // Return entity to pool for reuse app.entityFactory.sendToRest(enemy); // Next create() call may reuse the pooled entity const newEnemy = app.entityFactory.create("Enemy");Each entity type has its own pool. Entities are automatically removed from all collections before pooling.
Organize code into modular, reusable packages:
import type { KernoAddon } from "kernox"; const gameAddon: KernoAddon = { name: "myGame", prototypes: [playerPrototype, enemyPrototype], systems: [MovementSystem, CombatSystem, RenderSystem], collections: [Players, Enemies, Projectiles] }; // Load addon with automatic namespace registration app.use(gameAddon); // Access namespaced resources app.entityFactory.create("myGame.Player"); const players = app.collectionManager.get("myGame.Players");// Create from prototype const player = app.entityFactory.create("Player", { position: { x: 100, y: 200 }, hp: 80 }); // With namespace const enemy = app.entityFactory.create("myGame.Enemy"); // Entities are automatically added to their prototype's collectionsconst app = new Kernox(); // Register addons app.use(gameAddon); // Start execution loop app.execute(); // Stop execution app.stop();Clone the repository and run the demo:
git clone https://github.com/WebAxol/Kernox.git cd Kernox npm install npm startThen visit localhost:2025
For detailed documentation, see the wiki directory:
Contributions are welcome! Please send pull requests to the dev branch.
git clone https://github.com/WebAxol/Kernox.git cd Kernox npm install npm testMIT License - see LICENSE file for details.
