Add Hugo website and rewrite docs to match current engine

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>
This commit is contained in:
2026-02-23 18:09:55 -06:00
parent 1619122a58
commit 83b798e365
106 changed files with 2749 additions and 492 deletions

View File

@@ -1,67 +1,225 @@
---
title: "Tutorial"
type: docs
---
# A Tutorial Introduction
Let's make your first game. When prosperon is launched, it looks in the folder it's in for a ```config.js``` and ```main.js```. These are your first two examples of a module and a program.
This tutorial walks through building a simple game from scratch. By the end, you'll understand modules, programs, rendering, and input.
A module is a file that returns a single value. It could be any value: a number, a function, a string. Usually, it's an object. Values are **frozen** before returning, so they cannot be modified. A module is ran once and cached, so any program that accesses a module subsequently is simply getting the already cached object. Modules can import other modules. Circular references are not allowed.
## How Prosperon Starts
The ```config.js``` module must return a single object that describes your game. It sets up the window name, starting size, etc. Below is the default config, demonstrating all of the values that can be set on it.
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()`.
| Key | Default Value | Type | Description |
|--------------------|----------------------------------------------------------------|---------|-----------------------------------------------------------------------------------------------------------------------|
| **title** | `Prosperon [\${prosperon.version}-\${prosperon.revision}]` | string | Title of the game window, typically including version information. |
| **width** | `1280` | number | Initial width of the game window. |
| **height** | `720` | number | Initial height of the game window. |
| **icon** | `graphics.make_texture(io.slurp('icons/moon.gif'))` | object | Icon texture for the game window, loaded from the provided file. |
| **high_dpi** | `0` | number | Enables (1) or disables (0) High DPI support for the window. |
| **alpha** | `1` | number | Alpha channel setting for the window (0 to disable, 1 to enable transparency). |
| **fullscreen** | `0` | number | Sets whether the window should launch in fullscreen (1) or windowed (0). |
| **sample_count** | `1` | number | Multisampling count for rendering. Increasing this can improve image quality at the cost of performance. |
| **enable_clipboard** | `true` | boolean | Enables clipboard functionality within the application. |
| **enable_dragndrop** | `true` | boolean | Enables drag-and-drop functionality for files into the window. |
| **max_dropped_files** | `1` | number | Maximum number of files that can be dropped into the window at once. |
| **swap_interval** | `1` | number | Controls vertical synchronization (VSync). Commonly 1 for enabling or 0 for disabling VSync. |
| **name** | `"Prosperon"` | string | Human-readable name of the application. |
| **version** | `prosperon.version + "-" + prosperon.revision` | string | Version string for the application, dynamically built from Prosperon's version info. |
| **identifier** | `"world.pockle.prosperon"` | string | Package or bundle identifier for your game/application. |
| **creator** | `"Pockle World LLC"` | string | Name of the creator or organization behind the application. |
| **copyright** | `"Copyright Pockle World 2025"` | string | Copyright declaration for the application. |
| **type** | `"application"` | string | The general content type or category of this project. |
| **url** | `"https://github.com/johnbrethauer/prosperon"` | string | URL link associated with the project, such as a repository or official homepage. |
## Step 1: A Window
Create `game.ce`:
With the engine configured, prosperon starts ```main.js``` as the first **actor** of the game. Actors are created from files that **do not** return a value. An actor executes the statements in its script. Initialization should happen here. An actor can pull in other chunks of code by importing modules. Modules are imported with the ```use``` statement. ```use``` returns the value the module returned, and it can be assigned to any variable. To use the internal ```io``` module, for example, you might say ```var io = use('cellfs')```.
Actors exist until they are explicitly killed, by invoking their ```kill``` function. Because the actor created from ```main.js``` is the root actor for the entire game, when it is killed, the program exits. In an actor script file, ```this``` is set to the actor being spawned from the script.
## Our first program
With that out of the way, we can establish our first simple program.
In the folder with your ```prosperon``` executable, create a ```config.js``` and set it to be the following:
```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 {
title: "Hello World",
width: 500,
height:500
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()
}
}
```
This will cause prosperon to launch a 500x500 window with the title 'Hello World'. In your ```main.js```, write the following:
```javascript
// In your game program
var world = use('world')
var coin_proto = use('entities/coin')
```
log.console("Hello world")
this.delay(_ => {
this.kill();
}, 3)
var c = world.add_entity(coin_proto, {
pos: {x: 50, y: 80},
value: 5
})
```
**delay** is a function on all actors in prosperon. It executes a given function after a number of seconds. In this case, after 3 seconds, the root actor kills itself, closing the window.
The entity's `init()` runs after overrides are applied. The prototype defines every valid field with a default — it is the schema.
## The prosperon global
The global object called `prosperon` has a variety of engine specific settings on it that can be set to influence how the engine behaves. For example, `prosperon.argv` contains a list of the command line arguments given to prosperon; `prosperon.PATH` is an array of paths to resolve resources such as modules and images. `prosperon` is fully documented in the API section.
## Putting It Together
## Getting help
The `prosperon` global has a 'doc' function, which can be invoked on any engine object to see a description of it and its members. For example, to learn about `prosperon`, try printing out `cell.DOC(prosperon)` in your `main.js`.
A complete minimal game has:
Writing documentation for your own modules and game components will be explored in the chapter on actors & modules.
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