Player Controller
The PlayerController is the preferable and the fastest way to initialize the game. The controller wraps all boilerplate needed to wire Spinorium pieces together and exposes overridable hooks for project-specific logic. The current PlayerController instance is exposed via System.controller property.
As a developer, you can customize the controller by overriding the following methods:
createParameters()– Creates game parameters, which contain information about the player session used for backend authentication and game initialization (e.g. language, jurisdiction). Usually based on URL query parameters as data source.createSettings()– Creates game settings, which store player-specific preferences such as sound volume and turbo spin state. Usually based on local storage as data source.createTemplateConfig()– Customizes the template config, which includes game loading and initialization steps.createModel()– Creates a custom player model tailored to your backend and game type.createSystemConfig()– Customizes the engine config, including the initial configuration for all engine managers and systems, such as the renderer.
In addition, you can override built-in managers or create custom ones. All managers receive the PlayerModel and must be created once per controller instance:
createRoundManager()– Creates a custom round manager responsible for handling game rounds. This includes creating the model, generating features from the backend, and handling round interruptions.createIntegrationsManager()– Creates a custom integrations manager to handle bridge between the game and external services.createJurisdictionsManager()– Creates a custom jurisdictions manager to handle jurisdiction-specific logic.createCustomManagers()– Allows creating custom managers that can be used throughout the game. The default implementation registersAutoplayManager.
System Config Customization
The SystemConfig is used to configure the engine. It includes the initial configuration for all engine managers and systems, such as the renderer and state machine. The config can be merged with project defaults via ConfigUtil.overrideConfig().
Define only the sections that need adjustments. Everything else can fall back to template defaults and environment-specific overrides.
application– Renderer setup, ticker limits, device wrapper, auto-resize strategy, and canvas details.dependencyManager– Dependency inversion container with optional dependency replacements, timeline extensions, and component registrations.inputManager– Toggles context menu handling on the game canvas.performanceMonitor– Placement, colors, and visibility of the runtime performance overlay.localeManager– Default language and fallback languages for translations.viewportManager– Available viewport configurations and supported resolutions.stateMachine– Startup transitions and default state for the template state machine.soundManager– Default volume and auto-mute behaviors during blur and loading.
System Config Override Example
export class GameController extends PlayerController {
protected override createSystemConfig():Optional<SystemConfig> {
return ConfigUtil.overrideConfig(super.createSystemConfig(), {
application: {
backgroundColor: '#000000',
displayEngineVersion: false,
clearBeforeRender: true,
applicationCanvas: '#game-canvas'
},
inputManager: {
disableContextMenu: true
},
soundManager: {
enableAutoMute: true,
enableLoadingAutoMute: true,
defaultVolume: 0.6
}
});
}
}
Template Config Customization
Template config controls the loading pipeline, splash screen, and main scene activation. To customize game loading steps, such as backend authentication, override the template config. You can use several parameters to insert custom steps:
initialLoaderStepsQueue– A list of steps executed right after loading initial resource bundles. Useful for initializing UI components, such as popups with localized error messages.preLoaderStepsQueue– Steps executed before loading resources. Ideal for backend player authorization or integration setup.postLoaderStepsQueue– Steps executed after loading resources.
Authentication Step Example
To add a backend authentication step, extend the GameController and add a custom step to the preLoaderStepsQueue:
export class GameController extends PlayerController {
protected override createTemplateConfig():Optional<TemplateConfig> {
return ConfigUtil.overrideConfig(
super.createTemplateConfig(), {
preLoaderStepsQueue: [
AuthorizePlayerStep
]
}
);
}
}
Then define the custom loader step:
export class AuthorizePlayerStep extends LoaderStateStep {
public override async enter(loader:LoadingState):Promise<void> {
super.enter(loader);
const response = await authorizePlayer();
// handling the response
this.complete();
}
}
Parameters and Settings Customization
Spinorium provides built-in storage adapters to simplify access to multiple data sources. The PlayerController supports different data sources for parameters and settings. There are two methods to extract data from storage:
createProxyObject(config)– Creates a static object based on the current storage state. Changes to the storage or object are not reflected in each other. Use it for launch parameters that should not be mutated later.createProxy(config)– Creates a live proxy bound to storage. Changes to the proxy update the storage and vice versa. Perfect for runtime preferences that must persist between sessions.
PlayerController caches both objects, so construct them once and let the controller reuse them. Switching to live proxies is handy for mutable player preferences such as volume sliders, while a plain object keeps initialization parameters deterministic. Every storage entry must define its type and default value, ensuring that the controller never starts with undefined data.
Storage Usage Example
export interface GameParameters {
playerToken:string;
language:string;
}
export interface GameSettings {
turboSpin:boolean;
showSplashScreen:boolean;
volume:number;
}
export class GameController extends PlayerController<GameModel, GameParameters, GameSettings> {
protected override createParameters():GameParameters {
return System.urlStorage.createProxyObject<GameParameters>({
playerToken: { storeType: StorageValueType.STRING, value: null },
language: { storeType: StorageValueType.STRING, value: 'en' }
});
}
protected override createSettings():GameSettings {
return System.localStorage.createProxy<GameSettings>({
turboSpin: { storeType: StorageValueType.BOOLEAN, value: false },
showSplashScreen: { storeType: StorageValueType.BOOLEAN, value: true },
volume: { storeType: StorageValueType.NUMBER, value: 1 }
});
}
}
Studio Template
Studio templates typically provide a CommonController class that extends the base PlayerController with additional properties and functionality specific to the studio's requirements:
- Custom loading steps such as authentication.
- Custom managers initialization (usually at least
BackendManager,UIManagerandDebugManager). - Custom modules configuration.
- Default game parameters, settings and player model.
- Default system and template configs.