New Hugo site in website/ with prosperon.dev theme (blue/gold/castle aesthetic), docs sidebar navigation, and content pages. Rewrote all doc files to align with the actual codebase: compositor+film2d rendering, use() modules (no global prosperon object), Pit language, script+JSON entity model. Added entities.md, front matter to all 70+ API docs, and updated API index for current module architecture. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
226 lines
5.1 KiB
Markdown
226 lines
5.1 KiB
Markdown
---
|
|
title: "Tutorial"
|
|
type: docs
|
|
---
|
|
|
|
# A Tutorial Introduction
|
|
|
|
This tutorial walks through building a simple game from scratch. By the end, you'll understand modules, programs, rendering, and input.
|
|
|
|
## How Prosperon Starts
|
|
|
|
Prosperon runs a `.ce` program file as the root actor. This is your game's entry point. There is no `config.js` or `main.js` — everything is modules you import with `use()`.
|
|
|
|
## Step 1: A Window
|
|
|
|
Create `game.ce`:
|
|
|
|
```javascript
|
|
var core = use('core')
|
|
|
|
core.start({
|
|
title: "My Game",
|
|
width: 1280,
|
|
height: 720
|
|
})
|
|
```
|
|
|
|
Run it with `prosperon game.ce`. You get a window. `core.start()` initializes the GPU backend, opens the window, and starts the main loop.
|
|
|
|
## Step 2: Drawing a Sprite
|
|
|
|
Sprites are the fundamental drawable. Create one and it appears on screen — you don't issue draw calls.
|
|
|
|
```javascript
|
|
var core = use('core')
|
|
var sprite = use('sprite')
|
|
var compositor = use('compositor')
|
|
var camera = use('camera')
|
|
|
|
var cam = camera.make({
|
|
pos: {x: 0, y: 0},
|
|
width: 320,
|
|
height: 240
|
|
})
|
|
|
|
var player = sprite({
|
|
image: "player.png",
|
|
pos: {x: 0, y: 0},
|
|
width: 32,
|
|
layer: 5
|
|
})
|
|
|
|
var plan = compositor.compile({
|
|
planes: [{
|
|
name: 'game',
|
|
plane: 'default',
|
|
resolution: {width: 320, height: 240},
|
|
camera: cam,
|
|
presentation: 'integer_scale'
|
|
}]
|
|
})
|
|
|
|
core.start({
|
|
title: "Sprite Test",
|
|
width: 1280,
|
|
height: 720,
|
|
render: function() {
|
|
return compositor.execute(plan)
|
|
}
|
|
})
|
|
```
|
|
|
|
Key ideas:
|
|
- `sprite()` creates a sprite and registers it with the engine automatically
|
|
- The **compositor** describes how to render the scene: which planes, at what resolution, with what camera
|
|
- Your `render` callback returns the compositor result — the engine sends it to the GPU
|
|
|
|
## Step 3: Moving the Sprite
|
|
|
|
Add an `update` callback to move things each frame:
|
|
|
|
```javascript
|
|
core.start({
|
|
title: "Moving Sprite",
|
|
width: 1280,
|
|
height: 720,
|
|
update: function(dt) {
|
|
player.pos.x += 60 * dt
|
|
},
|
|
render: function() {
|
|
return compositor.execute(plan)
|
|
}
|
|
})
|
|
```
|
|
|
|
`dt` is the time elapsed since the last frame, in seconds. Multiply speeds by `dt` for frame-rate-independent movement.
|
|
|
|
## Step 4: Handling Input
|
|
|
|
Use the `input` module to map physical keys to named actions, then route those actions to your game objects:
|
|
|
|
```javascript
|
|
var input = use('input')
|
|
|
|
input.configure({
|
|
action_map: {
|
|
move_left: ['a', 'left'],
|
|
move_right: ['d', 'right'],
|
|
jump: ['space']
|
|
}
|
|
})
|
|
|
|
var player_entity = {
|
|
on_input: function(action, data) {
|
|
if (action == 'move_left' && data.pressed) {
|
|
player.pos.x -= 16
|
|
}
|
|
if (action == 'move_right' && data.pressed) {
|
|
player.pos.x += 16
|
|
}
|
|
}
|
|
}
|
|
|
|
var p1 = input.player1()
|
|
p1.possess(player_entity)
|
|
```
|
|
|
|
The input system handles keyboard, gamepad, and touch. You define actions once and bind them to any physical input.
|
|
|
|
## Step 5: Adding Sound
|
|
|
|
```javascript
|
|
var sound = use('sound')
|
|
|
|
sound.play("jump.wav")
|
|
```
|
|
|
|
Sounds are loaded by path. The engine caches audio data so loading the same sound twice reuses the existing data.
|
|
|
|
## Step 6: Multiple Planes
|
|
|
|
Real games often need separate rendering layers — pixel art at low res, HUD at native res:
|
|
|
|
```javascript
|
|
var plan = compositor.compile({
|
|
clear: {r: 0.1, g: 0.1, b: 0.2, a: 1},
|
|
planes: [
|
|
{
|
|
name: 'game',
|
|
plane: 'default',
|
|
resolution: {width: 320, height: 240},
|
|
camera: cam,
|
|
layer_sort: {'5': 'y'},
|
|
presentation: 'integer_scale'
|
|
},
|
|
{
|
|
name: 'hud',
|
|
plane: 'hud',
|
|
resolution: {width: 1280, height: 720},
|
|
camera: hud_cam,
|
|
presentation: 'stretch'
|
|
}
|
|
]
|
|
})
|
|
```
|
|
|
|
Sprites belong to a plane via their `plane` property. Each plane renders at its own resolution with its own camera, then composites onto the screen in order.
|
|
|
|
## Step 7: Entities
|
|
|
|
For anything more than a few sprites, use the entity system. Define entity types as modules, create instances with overrides:
|
|
|
|
```javascript
|
|
// entities/coin.cm
|
|
var sprite = use('sprite')
|
|
|
|
return {
|
|
value: 1,
|
|
image: "coin.png",
|
|
|
|
init: function() {
|
|
this.sprite = sprite({
|
|
image: this.image,
|
|
pos: this.pos,
|
|
width: 16,
|
|
layer: 3
|
|
})
|
|
},
|
|
|
|
on_destroy: function() {
|
|
this.sprite.destroy()
|
|
}
|
|
}
|
|
```
|
|
|
|
```javascript
|
|
// In your game program
|
|
var world = use('world')
|
|
var coin_proto = use('entities/coin')
|
|
|
|
var c = world.add_entity(coin_proto, {
|
|
pos: {x: 50, y: 80},
|
|
value: 5
|
|
})
|
|
```
|
|
|
|
The entity's `init()` runs after overrides are applied. The prototype defines every valid field with a default — it is the schema.
|
|
|
|
## Putting It Together
|
|
|
|
A complete minimal game has:
|
|
|
|
1. A `.ce` program that imports modules and calls `core.start()`
|
|
2. Sprite and entity modules (`.cm`) that define game objects
|
|
3. A compositor config that describes the rendering setup
|
|
4. Input configuration that maps keys to actions
|
|
|
|
The engine does the rest: batching sprites, sorting layers, managing GPU resources, polling events, scheduling frames.
|
|
|
|
## Next Steps
|
|
|
|
- [Graphics](../graphics/) — Sprites, text, shapes, tilemaps
|
|
- [Compositor](../ops/) — Planes, effects, presentation modes
|
|
- [Input](../input/) — Actions, players, control stacks
|
|
- [Entities](../entities/) — The entity model and world system
|