How a Rune Application Works - VectorPanic/rune-sdk GitHub Wiki
A Rune application consists of an application class, one or more scenes, and objects that build each scene. Rune manages the game loop and calls your code when itโs time to create, update, or remove content.
You describe the gameโs parts as objects: a scene for the main menu, a scene for the game, and separate classes for, for example, the player and the enemies.
The Application Holds Everything Together
rune.system.Application is the central class of the application. It ties together common systems such as the screen, resources, input, sound, and scene management.
In your own application class, you specify among other things the starting scene, resources, and which input devices will be used. Hereโs a simplified example, where game.scene.Play and game.data.Requests are classes in your project:
game.system.Application = function() {
rune.system.Application.call(this, {
developer: "com.example",
app: "mygame",
build: "1.0.0",
scene: game.scene.Play,
resources: game.data.Requests,
useKeyboard: true,
useGamepads: true,
framerate: 60
});
};
game.system.Application.prototype =
Object.create(rune.system.Application.prototype);
game.system.Application.prototype.constructor =
game.system.Application;
The application class describes the overall configuration of the project. The game logic is primarily placed in the scenes and their objects.
The Scene Describes a Part of the Application
A rune.scene.Scene can represent a main menu, a game level, or a results screen.
Each scene has its own Stage, cameras, and systems for timers, tweens, and states, among others. The scene also uses the applicationโs common systems, such as the keyboard and sound.
A simple breakdown might look like this:
Application
โโโ Scenes
โโโ Menu
โโโ Play
โ โโโ Stage
โ โโโ Background
โ โโโ Player
โ โโโ Enemies
โโโ Result
Stage Contains the Visual Objects
The scene's stage is the root of its display list. Here you add sprites, graphics, text, and containers that are part of the scene:
this.stage.addChild(this.player);
Objects can be grouped into containers to form a hierarchy. This makes it possible, for example, to group several visual parts into a common figure.
The cameras determine which part of the sceneโs content is displayed and how it is displayed.
Lifecycle: Create, Update, and Clean Up
When writing your own scene, you primarily work with three methods:
| Method | When it's called | What you usually do |
|---|---|---|
init() |
When the scene is initialized | Creates objects and adds them to the scene. |
update(step) |
At each update step when the scene is active | Reads input and updates game logic. |
dispose() |
When the scene is removed | Cleans up your own resources and references. |
When overriding the methods, you also need to call the base class's implementation. It manages the built-in systems of the scene.
The following example assumes that the project has its own sprite class, game.entity.Player:
game.scene.Play = function() {
this.player = null;
rune.scene.Scene.call(this, "play");
};
game.scene.Play.prototype =
Object.create(rune.scene.Scene.prototype);
game.scene.Play.prototype.constructor = game.scene.Play;
game.scene.Play.prototype.init = function() {
rune.scene.Scene.prototype.init.call(this);
this.player = new game.entity.Player(40, 80);
this.stage.addChild(this.player);
};
game.scene.Play.prototype.update = function(step) {
rune.scene.Scene.prototype.update.call(this, step);
// Move the player 100 pixels per second.
if (this.keyboard.pressed("RIGHT")) {
this.player.x += 100 * (step / 1000);
}
};
game.scene.Play.prototype.dispose = function() {
rune.scene.Scene.prototype.dispose.call(this);
this.player = null;
};
The scene's base class cleans up its stage, among other things. Any subscriptions or resources outside the scene's system need to be managed yourself.
Rune Drives the Game Loop
Rune distinguishes between updating the application state and rendering the result on the screen.
During the update, the engine reads the input and updates the scenes and other systems. During rendering, the result of the selected scene is drawn.
update(step) receives a time step in milliseconds. Rune uses fixed update steps based on the configured frame rate. At 60 updates per second, a step is approximately 16.67 milliseconds.
For movements you calculate yourself, you can convert the time step to seconds:
var seconds = step / 1000;
this.player.x += speed * seconds;
You normally do not need to call update() or render() yourself. For regular sprites and other display objects, Rune handles the drawing as well.
Selecting a Scene and Loading New Scenes
The scene manager can hold multiple initialized scenes simultaneously. With load(), you request that the current set be replaced:
this.application.scenes.load([
new game.scene.Menu(),
new game.scene.Play(),
new game.scene.Result()
]);
The switch occurs at the next update step. The previous scenes are cleaned up, and the new ones are initialized.
With select(), you choose a scene from the loaded set:
// Select Play, which is at index 1.
this.application.scenes.select(1);
Selecting another scene does not destroy the previous scene. Its objects and states remain. Use onSelect() and onDeselect() for any actions that should happen when a scene is selected or deselected.
Normally, only the selected scene is updated. A scene with persistent = true continues to be updated even when it is not selected. Only the selected scene is rendered.
Give Objects Their Own Responsibilities
As the game grows, each type of object can have its own class:
- The Scene creates the levels and maintains the gameโs rules.
- The Player manages its behavior and animations.
- The Enemy manages its behavior and states.
- The Interface displays things like score and lives.
This makes the scene easier to overview and allows the same objects to be used across multiple levels.