Files
prosperon/docs/graphics.md
John Alanbrook 83b798e365 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>
2026-02-23 18:09:55 -06:00

190 lines
4.1 KiB
Markdown

---
title: "Graphics"
type: docs
---
# Graphics Concepts
This page covers the fundamental graphics concepts in Prosperon.
## Textures and Images
A **texture** is a set of bytes on the GPU — not directly accessible from script code.
An **image** is a texture combined with a UV rect that specifies which region to draw:
```
image = {
texture: GPU texture handle,
rect: {x, y, width, height} // UV coordinates
}
```
This means multiple images can share one texture (a sprite sheet or atlas), each referencing a different region.
## Supported Image Formats
| Format | Notes |
|--------|-------|
| PNG | Standard, lossless |
| QOI | Fast decode, lossless |
| GIF | Animated frames supported |
| JPG/JPEG | Lossy |
| Aseprite (.ase) | Frames, tags, slices, durations, pivots |
Aseprite files are fully parsed — named animation tags, per-frame durations, pivot points, and slice data are all available.
## Sprites
A sprite is the fundamental drawable. Create one with the `sprite` module:
```javascript
var sprite = use('sprite')
var s = sprite({
image: "player.png",
pos: {x: 100, y: 200},
width: 32,
height: null, // derived from aspect ratio
anchor_x: 0.5, // center horizontally
anchor_y: 0, // bottom edge
layer: 5,
rotation: 0,
flip: {x: false, y: false},
color: {r: 1, g: 1, b: 1, a: 1},
opacity: 1,
tint: {r: 1, g: 1, b: 1, a: 1},
filter: 'nearest',
plane: 'default',
groups: [],
visible: true
})
```
### Fit Modes
When both `width` and `height` are specified, the `fit` property controls how the texture maps into the rectangle:
| Fit | Behavior |
|-----|----------|
| `none` | Use the texture's native pixel size |
| `fill` | Stretch to exactly fill the rectangle (may distort) |
| `contain` | Fit inside the rectangle, preserving aspect ratio |
| `cover` | Fill the rectangle, preserving aspect ratio (crops via UV) |
If only one dimension is given (e.g. `width: 32, height: null`), the other is derived from the texture's aspect ratio.
### Anchors
The anchor determines which point of the sprite sits at `pos`:
- `anchor_x: 0, anchor_y: 0` — top-left at pos
- `anchor_x: 0.5, anchor_y: 0.5` — center at pos
- `anchor_x: 0.5, anchor_y: 0` — bottom-center at pos (good for characters)
### UV Mapping
For sprite sheets, control which region of the texture is drawn:
```javascript
sprite({
image: spritesheet_texture,
uv: {offset: {x: 0.25, y: 0}, scale: {x: 0.25, y: 0.5}}
})
```
## Text
Create text with the `text2d` module:
```javascript
var text2d = use('text2d')
var label = text2d({
text: "Hello World",
font: "myfont.ttf",
size: 24,
pos: {x: 100, y: 100},
layer: 10
})
```
## Shapes
SDF-rendered shapes via the `shape2d` module:
```javascript
var shape2d = use('shape2d')
var box = shape2d.rect({
pos: {x: 50, y: 50},
width: 100,
height: 80,
color: {r: 1, g: 0, b: 0, a: 1},
layer: 3
})
var ball = shape2d.circle({
pos: {x: 200, y: 200},
radius: 25,
color: {r: 0, g: 1, b: 0, a: 1}
})
```
Available shapes: `rect`, `circle`, `ellipse`, `pill`.
## Tilemaps
Grid-based tile rendering:
```javascript
var tilemap2d = use('tilemap2d')
var map = tilemap2d({
tiles: tiles_2d_array,
tile_width: 16,
tile_height: 16,
layer: 0
})
```
Tiles can be flipped, and the entire tilemap can have an affine transform applied. Camera culling for large maps is planned.
## Particles
Particle emitters produce sprite-like particles:
```javascript
var particles2d = use('particles2d')
var emitter = particles2d({
texture: "spark.png",
pos: {x: 100, y: 100},
layer: 8
})
```
## Coordinate System
Prosperon uses a Y-up coordinate system:
- **X+** goes right
- **Y+** goes up
- `[0, 0]` in world space is where the camera starts
- `[0, 0]` in HUD space is the bottom-left of the screen
## Camera
A camera defines the viewport into the world. Its `width` and `height` set the game's internal resolution. Its `pos` determines what world coordinate is at the center of the screen.
```javascript
var camera = use('camera')
var cam = camera.make({
pos: {x: 0, y: 0},
width: 320,
height: 240
})
```
Everything in world space is drawn relative to the camera's position. HUD space is always screen-relative.