aboutsummaryrefslogtreecommitdiff
path: root/context.md
blob: cb0ee876613bd4c0563158ca28472c648ef5f4a3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# Project Context

## Project Type
Game project (likely a game jam entry - ggj26). Features top-down twin-stick shooter gameplay.

## Asset Generation
Uses ImageMagick scripts (`.imagemagick` files) in `assets_src/` to procedurally generate game assets.

### ImageMagick Script Conventions
- Start with `#!/usr/bin/env magick-script`
- Standard canvas: `512x512`
- Consistent styling: 8px border with `rgb(58,58,58)`, slight blur (`0x0.3-0.5`)
- Output to PNG via `-write png:-`
- Color palette: grayscale tones (40-80 RGB range)

### Existing Assets
- `floor.imagemagick`: Checkerboard pattern floor tile
- `wall.imagemagick`: Gray wall tile with horizontal stripe
- `player.imagemagick`: Top-down player sprite (circle body, shoulder pads, gun pointing east)
- Pre-made button sprites: 18 PNG files for UI buttons (up/down states, 3x3 grid variations)

## Drawing Approach
ImageMagick uses `-draw` commands for shapes. Player sprite demonstrates layering:
- Base circle for body
- Rounded rectangles for shoulder pads
- Rectangles for gun barrel extending horizontally

## Shaders (`src/shaders/`)
The game uses custom GLSL shaders with MoonScript/Lua setup code, built on the Amulet game engine.

### Rendering Architecture
- **Pseudo-3D perspective**: Uses Z-coordinate scaling to create depth without true 3D projection
- **Buffered rendering**: Pre-allocated vertex buffers for performance (world.moon sets MAX_PLAYERS=8, MAX_LEVEL_TRIS=1024)
- **World-space rendering**: All shaders receive `world_x` and `world_y` uniforms for camera positioning
- **Multi-lamp lighting**: Up to 8 dynamic lamps per shader with distance-based illumination

### Color Palette System
All lit shaders use a consistent 7-color palette for quantized lighting:
- `black` (darkest)
- `outline`
- `shadow`
- `background`
- `midground`
- `foreground`
- `highlight` (brightest)

Colors are selected based on calculated light intensity thresholds (>1.0, >0.8, >0.6, >0.4, >0.2, else black).

### Individual Shaders

#### Lake Shader (`lake.frag`, `lake.vert`, `lake.moon`)
- Water surface rendering with dynamic lighting
- Distance-based lamp illumination (up to 8 lamps: `lamp1` through `lamp8`)
- Noise/random functions for visual texture
- `streamer` uniform: toggles noise off for cleaner rendering
- Normal map support via `atlas` texture and `norm` varying
- Simple vertex shader (no rotation or Z-effects)

#### Land Shader (`land.frag`, `land.vert`)
- Ground/terrain rendering, nearly identical to lake shader
- Additional `water` uniform: enables simplex noise animation when > 1
- Vertex shader includes rotation matrix (`rot` uniform)
- Z-scaling for pseudo-3D perspective (clamped ±0.5)
- Normal mapping support

#### Player Shader (`player.frag`, `player.vert`)
- Character rendering (currently shows UV debug visualization)
- Supports texture mapping with `textures`, `emissives`, `normals` samplers
- Directional rotation via `dir` uniform
- Fixed Z-depth at -2 to position above world
- Lamp support declared but not used in fragment shader

#### Stars Shader (`stars.frag`, `stars.vert`, `stars.lua`)
- Starfield background using point sprites
- Procedurally generates ~500 stars in Lua setup
- Stars arranged in 3×3 tiling pattern for infinite scrolling
- Animated blinking: `gl_PointSize = pow(intensity, 2.) * stars.z * 0.3` where intensity = `sin(stars.z + time) * cos(time) + 1`
- Stars avoid circular region in center (radius 0.5) for game area
- Wrapping via `world_x_period` and `world_y_period`
- Z-position: -0.1 (behind everything)

#### World Shader (`world.frag`, `world.vert`, `world.moon`)
- Main 3D geometry renderer for levels
- Texture-mapped rendering (currently uses floor texture)
- Pseudo-3D via Z-based offset: `xoff = clamp(world.z * vxy.x * z_scale, -32., 32.)`
- Geometry generation in MoonScript:
  - `up_down_hall`: Creates hallway segments with floor and walls
  - `barrel`: Generates cylindrical objects with triangulated sides
  - `room`: Room generation (partially implemented)
- Buffered architecture allows dynamic level geometry
- Uses depth testing (`less`) and front-face culling
- Support for round objects via radius attribute (unused currently)

### Technical Details
- **Noise functions**: Simplex noise from Shadertoy (https://www.shadertoy.com/view/Msf3WH)
- **Random function**: Hash-based PRNG by @patriciogv (2015)
- **Lamp format**: `vec4(x, y, z, strength)` in normalized coordinates, scaled by 256 in shaders
- **Coordinate system**: World space, with fragment coord offset by `worldxy * 256`
- **View matrices**: Custom MV/P matrices in MoonScript, not standard OpenGL projection
- **Engine**: Amulet (`am.*` functions), uses scene graph with `append`, `bind`, `draw` nodes