Skip to main content

Architecture

GameByte uses a Laravel-inspired architecture with a service container, service providers, and facades.

🎮Service Container - Interactive Visualization
Loading demo...
🎮Cookie Clicker - Service Container & Reactive State in Action
Loading demo...

Service Container

The service container manages all game services and their dependencies.

Basic Usage

import { createGame } from '@gamebyte/framework';

const game = createGame();

// Bind a service
game.bind('my.service', () => new MyService());

// Resolve a service
const service = game.make('my.service');

Binding Types

Factory Binding

Creates a new instance each time:

game.bind('player', () => new Player());

const player1 = game.make('player'); // New instance
const player2 = game.make('player'); // Different instance

Singleton Binding

Creates one shared instance:

game.singleton('score.manager', () => new ScoreManager());

const manager1 = game.make('score.manager');
const manager2 = game.make('score.manager');
// manager1 === manager2 (same instance)

Instance Binding

Binds an existing instance:

const config = { debug: true, fps: 60 };
game.instance('config', config);

Dependency Resolution

The container automatically resolves nested dependencies:

game.singleton('logger', () => new Logger());
game.singleton('api', (app) => {
const logger = app.make('logger');
return new ApiClient(logger);
});

Service Providers

Service providers organize service registration and boot logic.

Creating a Provider

import { AbstractServiceProvider, GameByte } from '@gamebyte/framework';

export class ScoreServiceProvider extends AbstractServiceProvider {
register(app: GameByte): void {
// Register services
app.singleton('score.manager', () => new ScoreManager());
app.singleton('leaderboard', (app) => {
return new Leaderboard(app.make('score.manager'));
});
}

boot(app: GameByte): void {
// Run after all providers are registered
const scoreManager = app.make('score.manager');
scoreManager.loadSavedScores();
}
}

Registering Providers

const game = createGame();

// Register custom providers
game.register(new ScoreServiceProvider());
game.register(new AudioServiceProvider());

await game.initialize(canvas, '2d');

Built-in Providers

GameByte includes these providers by default:

ProviderServices
RenderServiceProviderrenderer, graphics
SceneServiceProviderscene.manager
InputServiceProviderinput, input.keyboard, input.touch
AudioServiceProvideraudio, audio.music, audio.sfx
PhysicsServiceProviderphysics
AssetServiceProviderassets

Facades

Facades provide static access to services for convenience.

Using Facades

import { Renderer, Scenes, Audio, Input } from '@gamebyte/framework';

// Instead of:
const renderer = game.make('renderer');
renderer.start();

// You can use:
Renderer.start();

// Other facades:
await Scenes.switchTo('game');
Audio.playMusic('background.mp3');
Input.on('click', handleClick);

Available Facades

FacadeService KeyDescription
RendererrendererRendering control
Scenesscene.managerScene management
UIuiUI component creation
AudioaudioAudio playback
Musicaudio.musicMusic control
SFXaudio.sfxSound effects
InputinputInput handling
PhysicsphysicsPhysics engine
AssetsassetsAsset loading

Creating Custom Facades

import { Facade } from '@gamebyte/framework';

class Score extends Facade {
protected static getFacadeAccessor(): string {
return 'score.manager';
}
}

// Usage:
Score.add(100);
Score.getTotal();

Container Events

Listen to container lifecycle events:

game.on('binding', (key, resolver) => {
console.log(`Service bound: ${key}`);
});

game.on('resolved', (key, instance) => {
console.log(`Service resolved: ${key}`);
});

Best Practices

1. Use Providers for Organization

// Good: Organized in providers
class GameServicesProvider extends AbstractServiceProvider {
register(app: GameByte): void {
app.singleton('inventory', () => new Inventory());
app.singleton('quests', () => new QuestManager());
app.singleton('achievements', () => new Achievements());
}
}

// Avoid: Scattered bindings
game.singleton('inventory', ...);
// ... elsewhere in code
game.singleton('quests', ...);

2. Use Singletons for Shared State

// Good: Shared score state
game.singleton('score', () => new ScoreManager());

// Avoid: Multiple instances causing state issues
game.bind('score', () => new ScoreManager());

3. Type Your Service Keys

// Define service types
interface ServiceMap {
'score.manager': ScoreManager;
'inventory': Inventory;
'player': Player;
}

// Type-safe resolution
const score = game.make<ServiceMap['score.manager']>('score.manager');

Reactive State

🎮Reactive State Management Demo
Loading demo...

Architecture Diagram

┌──────────────────────────────────────────────────────────┐
│ Your Game │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Facades │ │
│ │ Renderer │ Scenes │ Audio │ Input │ UI │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Service Container (GameByte) │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │ renderer │ │ scenes │ │ audio │ ... │ │
│ │ └──────────┘ └──────────┘ └──────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Service Providers │ │
│ │ RenderProvider │ SceneProvider │ AudioProvider │ │
│ └─────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────┘