minimojs 1.0.0-alpha.1
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.
- package/LICENSE +21 -0
- package/README.md +333 -0
- package/dist/minimo.d.ts +941 -0
- package/dist/minimo.js +1381 -0
- package/package.json +42 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 MinimoJS Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
# MinimoJS v1
|
|
2
|
+
|
|
3
|
+
> Ultra-minimal, flat, deterministic 2D web game engine.
|
|
4
|
+
> Emoji-only sprites · Degrees rotation · Milliseconds timing · rAF loop · TypeScript-first · LLM-friendly
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm install minimojs
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Or build from source:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install
|
|
18
|
+
npm run build
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Output: `dist/minimo.js` + `dist/minimo.d.ts`
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Examples
|
|
26
|
+
|
|
27
|
+
- `examples/chickens-eggs-basket/` — Pollos lanzan huevos y una cesta los recoge.
|
|
28
|
+
- `examples/run-dino-run/` — Classic endless runner: jump with the dino and avoid obstacles.
|
|
29
|
+
|
|
30
|
+
Run examples from project root with a static server:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npx serve .
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Open:
|
|
37
|
+
|
|
38
|
+
`http://localhost:3000/examples/chickens-eggs-basket/`
|
|
39
|
+
|
|
40
|
+
`http://localhost:3000/examples/run-dino-run/`
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Quick Start
|
|
45
|
+
|
|
46
|
+
```html
|
|
47
|
+
<script type="module">
|
|
48
|
+
import { Game, Sprite } from "./dist/minimo.js";
|
|
49
|
+
|
|
50
|
+
const game = new Game(800, 600);
|
|
51
|
+
game.gravityY = 980;
|
|
52
|
+
|
|
53
|
+
const player = new Sprite("🐢");
|
|
54
|
+
player.x = 400;
|
|
55
|
+
player.y = 300;
|
|
56
|
+
player.size = 48;
|
|
57
|
+
player.gravityScale = 1;
|
|
58
|
+
game.add(player);
|
|
59
|
+
|
|
60
|
+
game.onUpdate = (dt) => {
|
|
61
|
+
if (game.isKeyDown("ArrowLeft")) player.vx = -200;
|
|
62
|
+
else if (game.isKeyDown("ArrowRight")) player.vx = 200;
|
|
63
|
+
else player.vx = 0;
|
|
64
|
+
|
|
65
|
+
if (game.isKeyPressed(" ") && player.y >= 550) player.vy = -600;
|
|
66
|
+
|
|
67
|
+
if (player.y > 700) game.reset();
|
|
68
|
+
|
|
69
|
+
game.drawText(`x: ${Math.round(player.x)}`, 10, 10, 16, "#ffffff");
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
game.start();
|
|
73
|
+
</script>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Core Rules
|
|
79
|
+
|
|
80
|
+
| Rule | Value |
|
|
81
|
+
|---|---|
|
|
82
|
+
| All time parameters | **milliseconds** |
|
|
83
|
+
| All rotations | **degrees** |
|
|
84
|
+
| Game loop | **requestAnimationFrame only** |
|
|
85
|
+
| Sprites | **emoji only** |
|
|
86
|
+
| Canvas layout | **auto-centered + responsive scaling** |
|
|
87
|
+
| Coordinate system | **center-based world space** |
|
|
88
|
+
| Y-axis | **positive = down** |
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## API Reference
|
|
93
|
+
|
|
94
|
+
### `new Game(width?, height?)`
|
|
95
|
+
|
|
96
|
+
Creates the engine, creates its own canvas, and appends it to the page.
|
|
97
|
+
Canvas is automatically centered and scaled to the maximum viewport space
|
|
98
|
+
while keeping aspect ratio.
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
const game = new Game(800, 600);
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
### Sprite Management
|
|
107
|
+
|
|
108
|
+
| Method | Description |
|
|
109
|
+
|---|---|
|
|
110
|
+
| `game.add(sprite)` | Register a Sprite instance with the engine and return it |
|
|
111
|
+
| `game.destroySprite(sprite)` | Remove a sprite from the engine |
|
|
112
|
+
| `game.getSprites()` | Read-only snapshot of all sprites |
|
|
113
|
+
|
|
114
|
+
**Creating sprites** — instantiate `Sprite` directly or subclass it:
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
// Plain instantiation
|
|
118
|
+
const coin = new Sprite("🪙");
|
|
119
|
+
coin.x = 300; coin.y = 200; coin.size = 32;
|
|
120
|
+
game.add(coin);
|
|
121
|
+
|
|
122
|
+
// Subclassing
|
|
123
|
+
class Enemy extends Sprite {
|
|
124
|
+
health = 3;
|
|
125
|
+
constructor(x: number, y: number) {
|
|
126
|
+
super("👾");
|
|
127
|
+
this.x = x; this.y = y; this.size = 40; this.gravityScale = 1;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
const enemy = game.add(new Enemy(600, 100));
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
**Sprite properties and defaults:**
|
|
134
|
+
|
|
135
|
+
| Property | Type | Default | Description |
|
|
136
|
+
|---|---|---|---|
|
|
137
|
+
| `sprite` | `string` | — | **Required in constructor.** Single emoji |
|
|
138
|
+
| `x` | `number` | `0` | World X (center), pixels |
|
|
139
|
+
| `y` | `number` | `0` | World Y (center), pixels |
|
|
140
|
+
| `size` | `number` | `32` | Bounding square size, pixels |
|
|
141
|
+
| `rotation` | `number` | `0` | Degrees, clockwise |
|
|
142
|
+
| `flipX` | `boolean` | `false` | Visual horizontal mirror |
|
|
143
|
+
| `flipY` | `boolean` | `false` | Visual vertical mirror |
|
|
144
|
+
| `ignoreScroll` | `boolean` | `false` | Render in screen space (ignore `scrollX`/`scrollY`) |
|
|
145
|
+
| `alpha` | `number` | `1` | Opacity 0–1 |
|
|
146
|
+
| `visible` | `boolean` | `true` | Render toggle |
|
|
147
|
+
| `layer` | `number` | `0` | Render order (higher = on top) |
|
|
148
|
+
| `vx` | `number` | `0` | Horizontal velocity, px/s |
|
|
149
|
+
| `vy` | `number` | `0` | Vertical velocity, px/s |
|
|
150
|
+
| `gravityScale` | `number` | `0` | Gravity multiplier |
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
### Public State
|
|
155
|
+
|
|
156
|
+
| Property | Type | Description |
|
|
157
|
+
|---|---|---|
|
|
158
|
+
| `game.gravityX` | `number` | Horizontal gravity acceleration, px/s² |
|
|
159
|
+
| `game.gravityY` | `number` | Vertical gravity acceleration, px/s² |
|
|
160
|
+
| `game.scrollX` | `number` | Camera scroll X offset, pixels |
|
|
161
|
+
| `game.scrollY` | `number` | Camera scroll Y offset, pixels |
|
|
162
|
+
| `game.background` | `string \| null` | Solid canvas background color |
|
|
163
|
+
| `game.backgroundGradient` | `{ from: string; to: string } \| null` | Vertical canvas gradient (`from` top, `to` bottom) |
|
|
164
|
+
| `game.pageBackground` | `string \| null` | Full page (`document.body`) background color |
|
|
165
|
+
| `game.pointerX` | `number` | Pointer X in screen space, pixels (read-only) |
|
|
166
|
+
| `game.pointerY` | `number` | Pointer Y in screen space, pixels (read-only) |
|
|
167
|
+
| `game.width` | `number` | Canvas width, pixels (read-only) |
|
|
168
|
+
| `game.height` | `number` | Canvas height, pixels (read-only) |
|
|
169
|
+
| `game.onCreate` | `() => void` | Scene creation callback (start + reset) |
|
|
170
|
+
| `game.onUpdate` | `(dt: number) => void` | Frame callback. `dt` = seconds |
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
### Background
|
|
175
|
+
|
|
176
|
+
```ts
|
|
177
|
+
game.background = "#92d7ff"; // solid canvas background
|
|
178
|
+
game.backgroundGradient = { from: "#92d7ff", to: "#5ca44f" }; // vertical gradient
|
|
179
|
+
game.pageBackground = "#f4e4bc"; // page background
|
|
180
|
+
// If backgroundGradient is set, it takes priority over background.
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
### Collision (AABB, no resolution)
|
|
186
|
+
|
|
187
|
+
```ts
|
|
188
|
+
game.overlap(a, b) // → boolean
|
|
189
|
+
game.overlapAny(listA, listB) // → [Sprite, Sprite] | null
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Bounding box is a square centered at `(x, y)` with side `size`. Rotation ignored.
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
### Input
|
|
197
|
+
|
|
198
|
+
```ts
|
|
199
|
+
// Keyboard
|
|
200
|
+
game.isKeyDown("ArrowRight") // true every frame while held
|
|
201
|
+
game.isKeyPressed("ArrowRight") // true only on first frame of press
|
|
202
|
+
|
|
203
|
+
// Pointer (mouse / touch)
|
|
204
|
+
game.isPointerDown() // true every frame while held
|
|
205
|
+
game.isPointerPressed() // true only on first frame of press
|
|
206
|
+
game.pointerX // screen space X
|
|
207
|
+
game.pointerY // screen space Y
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
### Sound
|
|
213
|
+
|
|
214
|
+
```ts
|
|
215
|
+
game.sound(freq, durationMs)
|
|
216
|
+
// Square wave only. freq in Hz. durationMs in milliseconds.
|
|
217
|
+
game.sound(440, 100); // 440 Hz beep for 100ms
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
### Animation
|
|
223
|
+
|
|
224
|
+
```ts
|
|
225
|
+
game.animateAlpha(sprite, to, durationMs, onComplete?)
|
|
226
|
+
game.animateRotation(sprite, toDegrees, durationMs, onComplete?)
|
|
227
|
+
// Linear interpolation. durationMs in milliseconds.
|
|
228
|
+
// New animation on same property replaces the current one immediately.
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
### Timers
|
|
234
|
+
|
|
235
|
+
```ts
|
|
236
|
+
const id = game.addTimer(delayMs, repeat, callback)
|
|
237
|
+
game.clearTimer(id)
|
|
238
|
+
// rAF-driven (no setTimeout). delayMs in milliseconds.
|
|
239
|
+
// repeat=true fires every delayMs; repeat=false fires once then removes.
|
|
240
|
+
// All timers cleared on game.reset().
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
### Text Overlay
|
|
246
|
+
|
|
247
|
+
```ts
|
|
248
|
+
game.drawText(text, x, y, fontSize, color?, centered?)
|
|
249
|
+
// Screen space (ignores scroll). Must be called every frame.
|
|
250
|
+
// Always renders on top of all sprites.
|
|
251
|
+
// Font is always monospace (fixed by engine).
|
|
252
|
+
// Default color: "#ffffff"
|
|
253
|
+
// centered=true makes (x, y) the center anchor (both axes).
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
### Misc
|
|
259
|
+
|
|
260
|
+
```ts
|
|
261
|
+
game.isMobileDevice() // true on likely mobile/touch-first devices (heuristic)
|
|
262
|
+
game.random() // Math.random() wrapper → [0, 1)
|
|
263
|
+
game.reset() // Full state clear + calls onCreate() for scene rebuild
|
|
264
|
+
game.start() // Start rAF loop
|
|
265
|
+
game.stop() // Stop rAF loop
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
## Scene Creation and Reset
|
|
271
|
+
|
|
272
|
+
MinimoJS has no scene system. Use `onCreate()` to build scenes and `reset()` to rebuild:
|
|
273
|
+
|
|
274
|
+
```ts
|
|
275
|
+
game.onCreate = () => {
|
|
276
|
+
// Scene init — called on start and after reset()
|
|
277
|
+
const skull = new Sprite("💀");
|
|
278
|
+
skull.x = 400; skull.y = 300; skull.size = 96;
|
|
279
|
+
game.add(skull);
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
function goToGameOver() {
|
|
283
|
+
game.reset(); // clears everything, calls onCreate()
|
|
284
|
+
}
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## Forbidden Features
|
|
290
|
+
|
|
291
|
+
These do **not** exist in MinimoJS v1:
|
|
292
|
+
|
|
293
|
+
- Scene system / scene manager
|
|
294
|
+
- Entity Component System (ECS)
|
|
295
|
+
- Physics engine
|
|
296
|
+
- Camera zoom
|
|
297
|
+
- Nested APIs
|
|
298
|
+
- Text input
|
|
299
|
+
- Parallax
|
|
300
|
+
- Multiple cameras
|
|
301
|
+
- Collision resolution
|
|
302
|
+
- Image sprites (PNG/SVG)
|
|
303
|
+
- `setTimeout` / `setInterval`
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
## Build
|
|
308
|
+
|
|
309
|
+
```bash
|
|
310
|
+
npm run build # compile to dist/
|
|
311
|
+
npm run clean # remove dist/
|
|
312
|
+
npm run rebuild # clean + build
|
|
313
|
+
npm run pack:check # preview npm package contents
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
TypeScript target: **ES2020**, module: **ES2020**, strict mode, declaration files enabled.
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
|
|
320
|
+
## NPM Publish Notes
|
|
321
|
+
|
|
322
|
+
- `prepack` runs `npm run build` automatically before packaging.
|
|
323
|
+
- `files` whitelist includes only:
|
|
324
|
+
- `dist/`
|
|
325
|
+
- `README.md`
|
|
326
|
+
- `LICENSE`
|
|
327
|
+
- Example code under `examples/` is for repository usage and is excluded from the npm package.
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
## License
|
|
332
|
+
|
|
333
|
+
MIT
|