create-asciitorium 0.1.46 → 0.1.47

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,27 +1,19 @@
1
- # Materials Directory
1
+ # Asciitorium Materials
2
2
 
3
- This directory contains ASCII art representations of various materials and textures that can be used in asciitorium games. Materials define the visual appearance of surfaces, walls, floors, and other environmental elements.
4
-
5
- ## Contents
6
-
7
- - `wireframe.art`: A complex wireframe pattern demonstrating layered first-person perspective rendering
3
+ This directory contains ASCII art material files for the **FirstPersonView** and
4
+ **MapView** components. Materials define the visual appearance of walls, floors,
5
+ and other environmental surfaces with depth-based layering.
8
6
 
9
7
  ## Material File Format
10
8
 
11
- Material files use a special format that combines ASCII art with JSON metadata to define how materials should be rendered in different contexts.
9
+ Material files use the `.art` extension and follow a structured format with
10
+ metadata separators:
12
11
 
13
12
  ### File Structure
14
13
 
15
- Materials use paragraph markers (`¶`) to separate different layers or variants, with each section containing:
16
-
17
- 1. **Metadata line**: JSON configuration starting with `¶`
18
- 2. **ASCII art**: The visual representation using text characters
19
-
20
- ### Example Material
21
-
22
- Here's a section from `wireframe.art` showing the layered format:
14
+ #### Wall Material
23
15
 
24
- ```text
16
+ ```txt
25
17
  § {"kind":"material","usage":"first-person"}
26
18
  ¶ {"layer":"here","position":"left","x":-1}
27
19
  |╲
@@ -41,11 +33,9 @@ Here's a section from `wireframe.art` showing the layered format:
41
33
  |____________|
42
34
  ```
43
35
 
44
- ### Example with Placement
36
+ #### Ground Material
45
37
 
46
- Here's an example from `bone.art` showing placement for ground materials:
47
-
48
- ```text
38
+ ```txt
49
39
  § {"kind":"material","usage":"first-person","placement":"ground"}
50
40
  ¶ {"layer":"here","position":"center"}
51
41
  ⎽ ⎽
@@ -59,221 +49,105 @@ Here's an example from `bone.art` showing placement for ground materials:
59
49
 
60
50
  ```
61
51
 
62
- ## Metadata Properties
63
-
64
- ### Section Header (`§`)
65
-
66
- - **kind**: Type of asset (`"material"`)
67
- - **usage**: Rendering context (`"first-person"`, `"top-down"`, `"side-scroller"`)
68
- - **placement**: Surface placement (`"ground"`, `"ceiling"`) - optional property that indicates where the material should be applied. Use `"scenery"` for general background/wall materials (default)
69
- - **onEnterSound**: Sound that triggers when the player steps onto this tile (optional)
70
- - Value: `"filename.mp3"`
71
- - Sound files should be placed in `art/sounds/` directory
72
- - **onExitSound**: Sound that triggers when the player steps off this tile (optional)
73
- - Value: `"filename.mp3"`
74
- - Sound files should be placed in `art/sounds/` directory
75
- - **ambientSound**: Looping sound while material is visible (optional, future feature)
76
- - Value: `"filename.mp3"`
77
- - Sound files should be placed in `art/sounds/` directory
78
-
79
- ### Layer Configuration (`¶`)
80
-
81
- - **layer**: Depth layer (`"here"`, `"near"`, `"middle"`, `"far"`)
82
- - **position**: Horizontal alignment (`"left"`, `"center"`, `"right"`)
83
- - **x**: Horizontal offset for precise positioning
84
-
85
- ## Layer System
86
-
87
- The wireframe material demonstrates a sophisticated layering system for first-person perspective:
88
-
89
- - **here**: Immediate foreground elements (closest to viewer)
90
- - **near**: Close objects with full detail
91
- - **middle**: Mid-distance objects with moderate detail
92
- - **far**: Distant objects with minimal detail
93
-
94
- Each layer can have left, center, and right positioned elements with specific x-offsets for proper perspective alignment.
95
-
96
- ## Visual Techniques
97
-
98
- Materials can use various ASCII characters for different effects:
99
-
100
- - **Box drawing**: `|`, `─`, `╱`, `╲`, `╭`, `╮`, `╯`, `╰` for structural lines
101
- - **Perspective lines**: `╱`, `╲` for diagonal depth
102
- - **Solid fills**: `_` for horizontal surfaces
103
- - **Spacing**: Careful use of spaces for proper alignment and depth
104
-
105
- ## Usage in Maps
52
+ ### Key Components
53
+
54
+ 1. **File Header** (`§` separator)
55
+ - Must start with `§ {"kind":"material"}`
56
+ - Indicates this is a material asset
57
+ - Defines material properties:
58
+ - `usage`: Rendering context (`"first-person"`, `"top-down"`,
59
+ `"side-scroller"`)
60
+ - `placement`: Surface type (`"scenery"` [default], `"ground"`,
61
+ `"ceiling"`)
62
+ - `onEnterSound`: Sound file to play when player enters tile (e.g.,
63
+ `"splash.mp3"`)
64
+ - `onExitSound`: Sound file to play when player exits tile
65
+ - `ambientSound`: Looping sound while visible (future feature)
66
+
67
+ 2. **Layer Sections** (`¶` separator)
68
+ - Each layer begins with `¶` followed by JSON metadata
69
+ - Layer metadata:
70
+ - `layer`: Depth layer (`"here"`, `"near"`, `"middle"`, `"far"`)
71
+ - `position`: Horizontal alignment (`"left"`, `"center"`, `"right"`)
72
+ - `x`: Horizontal offset for precise positioning
73
+ - Layer content follows immediately after the metadata line
74
+
75
+ 3. **Layer Content**
76
+ - ASCII art representation of the material at that depth
77
+ - Each layer can be any width/height
78
+ - Blank lines are preserved
79
+ - Multiple layers create perspective depth
80
+
81
+ **Tips:**
82
+
83
+ - `"here"` layer is closest to viewer (immediate foreground)
84
+ - `"far"` layer is furthest (distant background)
85
+ - Use box drawing characters for structure: `|`, `─`, `╱`, `╲`, `╭`, `╮`, `╯`,
86
+ `╰`
87
+ - Each layer can have left/center/right positioned elements with x-offsets for
88
+ perspective alignment
89
+
90
+ ## Using Materials in Your App
106
91
 
107
92
  Materials are referenced in map legends through the `asset` property:
108
93
 
94
+ ### Map Legend Entry
95
+
109
96
  ```json
110
97
  {
111
98
  "chars": ["#"],
112
- "kind": "material",
113
99
  "name": "wireframe-wall",
114
100
  "solid": true,
115
- "asset": "material/wireframe"
101
+ "material": "wireframe"
116
102
  }
117
103
  ```
118
104
 
119
- The system will load the corresponding `wireframe.art` file and render the appropriate layer based on the viewing context and distance.
120
-
121
- ## Relationship with Legend Entities
122
-
123
- The architecture separates visual presentation (materials) from gameplay behavior (legend entities):
124
-
125
- ### Materials Handle
105
+ The system loads the corresponding `wireframe.art` file and renders the
106
+ appropriate layer based on viewing context and distance.
126
107
 
127
- - **Visual representation** at different distances (layer system)
128
- - **Ambient sounds** tied to proximity (howling when near a wolf wall)
129
- - **Transition sounds** when moving between layers (door creaking as you approach)
130
- - **Distance-based events** (footsteps on different floor types)
108
+ ## Technical Details
131
109
 
132
- ### Legend Entities Handle
110
+ ### Loading
133
111
 
134
- - **Interactions** (opening doors, picking up items, talking to NPCs)
135
- - **Game state** (is door locked/unlocked, enemy health, treasure quantity)
136
- - **Collision detection** (solid vs passable)
137
- - **Gameplay behaviors** (enemy AI, trap triggers, puzzle mechanics)
112
+ Materials are loaded asynchronously via the `AssetManager`:
138
113
 
139
- ### Example: Door Material + Entity
140
-
141
- **Material file** (`door-wooden.art`):
142
-
143
- ```text
144
- § {"kind":"material","usage":"first-person","placement":"scenery","onEnterSound":"door-open.mp3","onExitSound":"door-close.mp3"}
145
- ¶ {"layer":"here","position":"center"}
146
- [ASCII art for door at immediate distance - plays open sound when player steps onto this tile, close sound when leaving]
147
- ¶ {"layer":"near","position":"center"}
148
- [ASCII art for door at near distance]
149
- ```
150
-
151
- **Legend entry** (references the material):
152
-
153
- ```json
154
- {
155
- "chars": ["o"],
156
- "kind": "material",
157
- "entity": "door",
158
- "variant": "wooden",
159
- "name": "Wooden Door",
160
- "solid": false,
161
- "asset": "material/door-wooden",
162
- "state": {
163
- "locked": false,
164
- "open": false
165
- },
166
- "interactions": {
167
- "onInteract": "toggle-door",
168
- "onMelee": "bash-door"
169
- }
170
- }
171
- ```
172
-
173
- This design allows:
174
-
175
- - **Reusable materials**: Same door material can be used for locked/unlocked/magic doors
176
- - **Instance-specific behavior**: Each door on the map can have different state (some locked, some open)
177
- - **Separation of concerns**: Artists focus on materials, game designers focus on legend entities
178
- - **Sensory cohesion**: Sounds/visuals stay together in material files
179
-
180
- ### Example: Puddle with Sound
181
-
182
- Ground materials can also use `onEnterSound` for footstep sounds:
183
-
184
- **Material file** (`puddle.art`):
185
-
186
- ```text
187
- § {"kind":"material","usage":"first-person","placement":"ground","onEnterSound":"splash.mp3"}
188
- ¶ {"layer":"here","position":"center"}
189
- ~~~~
190
- ~~~~~~
191
- ~~~~~~~~
192
- ~~~~~~
193
- ~~~~
194
- ¶ {"layer":"near","position":"center"}
195
- ~~
196
- ```
197
-
198
- **Legend entry**:
199
-
200
- ```json
201
- {
202
- "chars": ["~"],
203
- "kind": "material",
204
- "name": "puddle",
205
- "solid": false,
206
- "asset": "material/puddle"
207
- }
114
+ ```typescript
115
+ const materialAsset = await AssetManager.getMaterial('wireframe');
208
116
  ```
209
117
 
210
- When the player steps onto a `~` tile, they'll hear a splash sound. This same pattern works for:
211
-
212
- - Gravel paths (`crunch.mp3`)
213
- - Creaky floorboards (`creak.mp3`)
214
- - Grass (`rustle.mp3`)
215
- - Snow (`snow-step.mp3`)
216
-
217
- ## Sound System
218
-
219
- Materials support sound playback through properties in the section header (`§`). Sounds are automatically triggered by the GameWorld when the player moves.
220
-
221
- ### Sound File Requirements
222
-
223
- - **Location**: Place sound files in `art/sounds/` directory relative to your project root
224
- - **Formats**: MP3, WAV, and other browser-supported audio formats
225
- - **Environment**: Sounds only play in web environments (browser), not in CLI mode
226
- - **Reference**: Use filename in section header: `{"onEnterSound":"filename.mp3"}`
227
-
228
- ### Sound Properties
118
+ ### Caching
229
119
 
230
- - **onEnterSound**: Plays once when the player steps onto a tile with this material
231
- - **onExitSound**: Plays once when the player steps off a tile with this material
232
- - **ambientSound**: Looping sound while material is visible (future feature)
120
+ Material assets are cached on first load - subsequent uses of the same material
121
+ reuse the cached data.
233
122
 
234
- ### How Sound Triggering Works
123
+ ### Sound System
235
124
 
236
- When using `GameWorld` for game logic:
125
+ Materials support sound playback through properties in the file header (`§`):
237
126
 
238
- 1. Player moves to a new tile coordinate (x, y)
239
- 2. GameWorld triggers `onExitSound` for the previous tile's material (if any)
240
- 3. GameWorld checks the new tile's legend entry
241
- 4. If the entry is a material, GameWorld loads the material asset
242
- 5. If the material has `onEnterSound`, the sound plays
243
- 6. When the player leaves the tile, `onExitSound` plays (if defined)
244
- 7. Sounds play once per tile entry/exit (moving onto the same tile repeatedly will retrigger both sounds)
127
+ - **Sound files location**: `art/sounds/` directory
128
+ - **Supported formats**: MP3
129
+ - **Environment**: Sounds only play in web mode (not CLI)
130
+ - **onEnterSound**: Plays once when player steps onto tile with this material
131
+ - **onExitSound**: Plays once when player steps off tile
245
132
 
246
- ### Controlling Sound Playback
247
-
248
- You can control sound globally through the `SoundManager`:
133
+ Control sounds globally via `SoundManager`:
249
134
 
250
135
  ```typescript
251
136
  import { SoundManager } from 'asciitorium';
252
137
 
253
- // Disable all sounds
254
- SoundManager.setEnabled(false);
255
-
256
- // Re-enable sounds
257
- SoundManager.setEnabled(true);
258
-
259
- // Check if sounds are enabled
260
- const enabled = SoundManager.isEnabled();
261
-
262
- // Manually play a sound
263
- SoundManager.playSound('custom-sound.mp3');
264
-
265
- // Clear sound cache
266
- SoundManager.clearCache();
138
+ SoundManager.setEnabled(false); // Disable all sounds
139
+ SoundManager.setEnabled(true); // Re-enable sounds
140
+ SoundManager.playSound('custom-sound.mp3'); // Play manually
267
141
  ```
268
142
 
269
- ## Creating New Materials
143
+ ### Layer System
270
144
 
271
- When creating new material files:
145
+ The layering system creates first-person perspective depth:
272
146
 
273
- 1. Start with a section header (`§`) defining the material type and usage
274
- 2. Define multiple layers for depth perception
275
- 3. Use consistent positioning and x-offsets for alignment
276
- 4. Test with different viewing distances and angles
277
- 5. Follow ASCII art best practices for readability
147
+ - **here**: Immediate foreground (closest to viewer)
148
+ - **near**: Close objects with full detail
149
+ - **middle**: Mid-distance objects with moderate detail
150
+ - **far**: Distant objects with minimal detail
278
151
 
279
- Use this directory as a reference for creating rich, layered materials that enhance the visual depth of your asciitorium games.
152
+ Each layer can have left, center, and right positioned elements with specific
153
+ x-offsets for proper perspective alignment.
@@ -0,0 +1,9 @@
1
+ # Sounds Directory
2
+
3
+ This directory contains audio assets in MP3 format used throughout the
4
+ application.
5
+
6
+ ## Usage
7
+
8
+ Sound files can be referenced in material definitions, sprite definitions, or
9
+ played programmatically through the application's audio system.
@@ -0,0 +1,136 @@
1
+ # Asciitorium Sprites
2
+
3
+ This directory contains ASCII sprite files for the **Art** component. Sprites
4
+ allow you to display static or animated ASCII art via the Art component.
5
+
6
+ ## Sprite File Format
7
+
8
+ Sprite files use the `.art` extension and follow a structured format with
9
+ metadata separators:
10
+
11
+ ### File Structure
12
+
13
+ #### Simple Static Sprite (no metadata)
14
+
15
+ ``` txt
16
+ ▄█▀█▄ ▄███▄
17
+ ▐█░██████████▌
18
+ ██▒█████████
19
+ ▀████████▀
20
+ ▀██▀
21
+ ```
22
+
23
+ #### Animated Sprite with Metadata
24
+
25
+ ``` txt
26
+ § {"kind":"sprite","loop":true,"default-frame-rate":100}
27
+ ¶ {"duration":1000}
28
+ ▄█▀█▄ ▄███▄
29
+ ▐█░██████████▌
30
+ ██▒█████████
31
+ ▀████████▀
32
+ ▀██▀
33
+
34
+ ▄█▀▄ ▄██▄
35
+ ▐█░████████▌
36
+ ██▒███████
37
+ ▀██████▀
38
+ ▀▀
39
+
40
+ ▄█▀▄▄██▄
41
+ ▐█░██████▌
42
+ ██▒█████
43
+ ▀████▀
44
+ ▀▀
45
+ ```
46
+
47
+ ### Key Components
48
+
49
+ 1. **File Header** (`§` separator) - Optional
50
+ - Must start with `§ {"kind":"sprite"}`
51
+ - Indicates this is a sprite asset
52
+ - Defines default animation settings:
53
+ - `default-frame-rate`: Default duration in milliseconds for each frame
54
+ - `loop`: Whether animation loops (true/false)
55
+ - `transparent`: Single character to treat as transparent (e.g., `" "`)
56
+
57
+ 2. **Frame Sections** (`¶` separator) - Optional
58
+ - Each frame begins with `¶` followed by optional JSON metadata
59
+ - Frame metadata (all optional):
60
+ - `duration`: Override default frame duration in milliseconds
61
+ - `sound`: Sound ID to play when frame displays
62
+ - Frame content follows immediately after the metadata line
63
+ - If no metadata needed, use `¶` alone
64
+
65
+ 3. **Frame Content**
66
+ - ASCII art representation of the sprite frame
67
+ - Each frame can be any width/height
68
+ - Blank lines are preserved
69
+ - Maximum sprite dimensions determined by largest frame
70
+
71
+ **Tips:**
72
+
73
+ - Files without `§` or `¶` are treated as single-frame static sprites
74
+ - Empty lines within frames are preserved for vertical spacing
75
+ - The first line after frame metadata is part of the sprite (no automatic
76
+ trimming)
77
+ - All frames should have consistent dimensions for best results
78
+ - Use the `transparent` property to define overlay sprites
79
+
80
+ ## Using Sprites in Your App
81
+
82
+ ### Basic Usage (Async Loading)
83
+
84
+ ```tsx
85
+ <Art sprite="balloon" />
86
+ ```
87
+
88
+ ### With Reactive State
89
+
90
+ ```tsx
91
+ import { State } from 'asciitorium';
92
+
93
+ const playerSprite = new State<string>(defaultArt);
94
+
95
+ <Art content={playerSprite} />
96
+ ```
97
+
98
+ ### Available Props
99
+
100
+ - `sprite`: Name of sprite file (without `.art` extension) to load asynchronously
101
+ - `content`: String or `State<string>` for inline sprite content
102
+ - `children`: Alternative way to provide inline content
103
+ - Plus all standard component props: `position`, `border`, `align`, `style`,
104
+ etc.
105
+
106
+ ## Technical Details
107
+
108
+ ### Loading
109
+
110
+ Sprites are loaded asynchronously via the `AssetManager`:
111
+
112
+ ```typescript
113
+ const spriteAsset = await AssetManager.getSprite('mysprite');
114
+ ```
115
+
116
+ ### Caching
117
+
118
+ Sprite assets are cached on first load - subsequent uses of the same sprite
119
+ reuse the cached data.
120
+
121
+ ### Animation System
122
+
123
+ The Art component automatically:
124
+
125
+ - Parses sprite metadata and frames
126
+ - Schedules frame transitions based on duration
127
+ - Handles looping vs. one-shot playback
128
+ - Requests renders when frames change
129
+ - Cleans up timers when component is destroyed
130
+
131
+ ### Dimension Calculation
132
+
133
+ Component dimensions are automatically calculated from the largest frame:
134
+
135
+ - Width: Maximum line length across all frames
136
+ - Height: Maximum number of lines across all frames
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  App,
3
3
  Art,
4
- Button,
4
+ Banner,
5
5
  Column,
6
6
  Text,
7
7
  PerfMonitor,
@@ -25,14 +25,14 @@ const app = (
25
25
  <Keybind keyBinding="p" action={togglePerfMonitor} />
26
26
 
27
27
  <Column style={{ align: 'center', gap: 1, width: '100%' }}>
28
- <Art font="pencil" text="Welcome to" align="center" />
29
- <Art src="asciitorium" align="center" />
28
+ <Banner font="pencil" text="Welcome to" align="center" />
29
+ <Banner font="shadows" text="asciitorium" align="center" />
30
30
 
31
31
  <Text style={{ align: 'center', gap: 1 }}>
32
32
  Edit src/main.tsx and save to reload.
33
33
  </Text>
34
34
 
35
- <Art src="beating-heart" width={20} align="center" />
35
+ <Art sprite="beating-heart" width={20} align="center" />
36
36
 
37
37
  <Text style={{ align: 'center', gap: 1 }}>
38
38
  Press [P] to toggle performance monitor
@@ -291,7 +291,7 @@ Line 3
291
291
  <Column gap={1}>
292
292
  <Text>If art/asciitorium.art exists, it should render below:</Text>
293
293
  {/* Uncomment if you have art files:
294
- <Art src="asciitorium" align="center" />
294
+ <Art sprite="asciitorium" align="center" />
295
295
  */}
296
296
  <Text>Art test skipped (no art files in template)</Text>
297
297
  </Column>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-asciitorium",
3
- "version": "0.1.46",
3
+ "version": "0.1.47",
4
4
  "private": false,
5
5
  "description": "Scaffold a Vite + TypeScript project prewired for asciitorium (web + cli).",
6
6
  "bin": {