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>
190 lines
4.1 KiB
Markdown
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.
|