@guinetik/gcanvas 1.0.0 → 1.0.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.
Files changed (68) hide show
  1. package/demos/fluid-simple.html +22 -0
  2. package/demos/fluid.html +37 -0
  3. package/demos/index.html +2 -0
  4. package/demos/js/blob.js +18 -5
  5. package/demos/js/fluid-simple.js +253 -0
  6. package/demos/js/fluid.js +527 -0
  7. package/demos/js/tde/accretiondisk.js +64 -11
  8. package/demos/js/tde/blackholescene.js +2 -2
  9. package/demos/js/tde/config.js +2 -2
  10. package/demos/js/tde/index.js +152 -27
  11. package/demos/js/tde/lensedstarfield.js +32 -25
  12. package/demos/js/tde/tdestar.js +78 -98
  13. package/demos/js/tde/tidalstream.js +23 -7
  14. package/docs/README.md +230 -222
  15. package/docs/api/FluidSystem.md +173 -0
  16. package/docs/concepts/architecture-overview.md +204 -204
  17. package/docs/concepts/rendering-pipeline.md +279 -279
  18. package/docs/concepts/two-layer-architecture.md +229 -229
  19. package/docs/fluid-dynamics.md +97 -0
  20. package/docs/getting-started/first-game.md +354 -354
  21. package/docs/getting-started/installation.md +175 -157
  22. package/docs/modules/collision/README.md +2 -2
  23. package/docs/modules/fluent/README.md +6 -6
  24. package/docs/modules/game/README.md +303 -303
  25. package/docs/modules/isometric-camera.md +2 -2
  26. package/docs/modules/isometric.md +1 -1
  27. package/docs/modules/painter/README.md +328 -328
  28. package/docs/modules/particle/README.md +3 -3
  29. package/docs/modules/shapes/README.md +221 -221
  30. package/docs/modules/shapes/base/euclidian.md +123 -123
  31. package/docs/modules/shapes/base/shape.md +262 -262
  32. package/docs/modules/shapes/base/transformable.md +243 -243
  33. package/docs/modules/state/README.md +2 -2
  34. package/docs/modules/util/README.md +1 -1
  35. package/docs/modules/util/camera3d.md +3 -3
  36. package/docs/modules/util/scene3d.md +1 -1
  37. package/package.json +3 -1
  38. package/readme.md +19 -5
  39. package/src/collision/collision.js +75 -0
  40. package/src/game/index.js +2 -1
  41. package/src/game/pipeline.js +3 -3
  42. package/src/game/systems/FluidSystem.js +835 -0
  43. package/src/game/systems/index.js +11 -0
  44. package/src/game/ui/button.js +39 -18
  45. package/src/game/ui/cursor.js +14 -0
  46. package/src/game/ui/fps.js +12 -4
  47. package/src/game/ui/index.js +2 -0
  48. package/src/game/ui/stepper.js +549 -0
  49. package/src/game/ui/theme.js +121 -0
  50. package/src/game/ui/togglebutton.js +9 -3
  51. package/src/game/ui/tooltip.js +11 -4
  52. package/src/math/fluid.js +507 -0
  53. package/src/math/index.js +2 -0
  54. package/src/mixins/anchor.js +17 -7
  55. package/src/motion/tweenetik.js +16 -0
  56. package/src/shapes/index.js +1 -0
  57. package/src/util/camera3d.js +218 -12
  58. package/types/fluent.d.ts +361 -0
  59. package/types/game.d.ts +303 -0
  60. package/types/index.d.ts +144 -5
  61. package/types/math.d.ts +361 -0
  62. package/types/motion.d.ts +271 -0
  63. package/types/particle.d.ts +373 -0
  64. package/types/shapes.d.ts +107 -9
  65. package/types/util.d.ts +353 -0
  66. package/types/webgl.d.ts +109 -0
  67. package/disk_example.png +0 -0
  68. package/tde.png +0 -0
@@ -1,354 +1,354 @@
1
- # First Game
2
-
3
- > Create an interactive game with the Game layer.
4
-
5
- ## Overview
6
-
7
- This guide shows how to use the Game layer to create interactive applications. We'll build a simple game with keyboard input, collision detection, and animations.
8
-
9
- ## Basic Game Setup
10
-
11
- ```js
12
- import { Game, Scene, GameObject, Circle, Group, Rectangle, TextShape } from 'gcanvas';
13
-
14
- class MyGame extends Game {
15
- constructor(canvas) {
16
- super(canvas);
17
- this.enableFluidSize(); // Canvas fills window
18
- this.backgroundColor = '#1a1a2e';
19
- }
20
-
21
- init() {
22
- super.init(); // Initialize input systems
23
-
24
- // Create a scene
25
- this.scene = new Scene(this);
26
- this.pipeline.add(this.scene);
27
-
28
- // Add game objects
29
- this.scene.add(new Player(this));
30
- }
31
- }
32
-
33
- // Start the game
34
- const canvas = document.getElementById('game');
35
- const game = new MyGame(canvas);
36
- game.start();
37
- ```
38
-
39
- ## Creating a Player
40
-
41
- ```js
42
- class Player extends GameObject {
43
- constructor(game) {
44
- super(game);
45
-
46
- // Create the player shape
47
- this.shape = new Circle(30, {
48
- color: '#4ecdc4',
49
- stroke: '#fff',
50
- lineWidth: 2
51
- });
52
-
53
- // Position at center
54
- this.shape.x = game.width / 2;
55
- this.shape.y = game.height / 2;
56
-
57
- // Movement speed (pixels per second)
58
- this.speed = 300;
59
-
60
- // Enable mouse/touch input on this shape
61
- this.enableInteractivity(this.shape);
62
- }
63
-
64
- update(dt) {
65
- // Handle keyboard input
66
- const input = this.game.input;
67
-
68
- if (input.isKeyDown('ArrowLeft') || input.isKeyDown('KeyA')) {
69
- this.shape.x -= this.speed * dt;
70
- }
71
- if (input.isKeyDown('ArrowRight') || input.isKeyDown('KeyD')) {
72
- this.shape.x += this.speed * dt;
73
- }
74
- if (input.isKeyDown('ArrowUp') || input.isKeyDown('KeyW')) {
75
- this.shape.y -= this.speed * dt;
76
- }
77
- if (input.isKeyDown('ArrowDown') || input.isKeyDown('KeyS')) {
78
- this.shape.y += this.speed * dt;
79
- }
80
-
81
- // Keep player on screen
82
- this.shape.x = Math.max(30, Math.min(this.game.width - 30, this.shape.x));
83
- this.shape.y = Math.max(30, Math.min(this.game.height - 30, this.shape.y));
84
- }
85
-
86
- render() {
87
- this.shape.draw();
88
- }
89
-
90
- // Called when player is clicked
91
- onPointerDown(e) {
92
- console.log('Player clicked!');
93
- }
94
- }
95
- ```
96
-
97
- ## Adding Enemies
98
-
99
- ```js
100
- class Enemy extends GameObject {
101
- constructor(game, x, y) {
102
- super(game);
103
-
104
- this.shape = new Rectangle({
105
- x: x,
106
- y: y,
107
- width: 40,
108
- height: 40,
109
- color: '#ff6b6b'
110
- });
111
-
112
- // Random direction
113
- this.vx = (Math.random() - 0.5) * 200;
114
- this.vy = (Math.random() - 0.5) * 200;
115
- }
116
-
117
- update(dt) {
118
- // Move
119
- this.shape.x += this.vx * dt;
120
- this.shape.y += this.vy * dt;
121
-
122
- // Bounce off walls
123
- if (this.shape.x < 20 || this.shape.x > this.game.width - 20) {
124
- this.vx *= -1;
125
- }
126
- if (this.shape.y < 20 || this.shape.y > this.game.height - 20) {
127
- this.vy *= -1;
128
- }
129
-
130
- // Rotate
131
- this.shape.rotation += dt * 2;
132
- }
133
-
134
- render() {
135
- this.shape.draw();
136
- }
137
- }
138
- ```
139
-
140
- ## Complete Game Example
141
-
142
- Here's a complete game from `demos/js/basic.js`:
143
-
144
- ```js
145
- import {
146
- Game,
147
- GameObject,
148
- Scene,
149
- Circle,
150
- Rectangle,
151
- TextShape,
152
- Group,
153
- Motion,
154
- Easing,
155
- FPSCounter
156
- } from 'gcanvas';
157
-
158
- /**
159
- * HelloWorldBox - A simple animated text box
160
- */
161
- class HelloWorldBox extends GameObject {
162
- constructor(game) {
163
- super(game);
164
-
165
- // Create a group to hold shapes
166
- this.group = new Group({});
167
-
168
- // Background box
169
- this.box = new Rectangle({
170
- width: 200,
171
- height: 80,
172
- color: '#333'
173
- });
174
-
175
- // Text label
176
- this.label = new TextShape('Hello World!', {
177
- font: '18px monospace',
178
- color: '#0f0',
179
- align: 'center',
180
- baseline: 'middle'
181
- });
182
-
183
- // Add to group
184
- this.group.add(this.box);
185
- this.group.add(this.label);
186
-
187
- // Animation time
188
- this.animTime = 0;
189
- }
190
-
191
- update(dt) {
192
- this.animTime += dt;
193
-
194
- // Pulse the text opacity
195
- const pulse = Motion.pulse(
196
- 0, 1, // min, max opacity
197
- this.animTime,
198
- 2, // 2 second cycle
199
- true, // loop
200
- false, // no yoyo
201
- Easing.easeInOutSine
202
- );
203
- this.label.opacity = pulse.value;
204
-
205
- // Float the group
206
- const float = Motion.float(
207
- { x: 0, y: 0 },
208
- this.animTime,
209
- 5, // 5 second cycle
210
- 0.5, // speed
211
- 0.5, // randomness
212
- 50, // radius
213
- true,
214
- Easing.easeInOutSine
215
- );
216
- this.group.x = float.x;
217
- this.group.y = float.y;
218
-
219
- super.update(dt);
220
- }
221
-
222
- render() {
223
- this.group.render();
224
- }
225
- }
226
-
227
- /**
228
- * DemoGame - Main game class
229
- */
230
- class DemoGame extends Game {
231
- constructor(canvas) {
232
- super(canvas);
233
- this.enableFluidSize();
234
- this.backgroundColor = 'black';
235
- }
236
-
237
- init() {
238
- super.init();
239
-
240
- // Create main scene
241
- this.gameScene = new Scene(this);
242
- this.gameScene.add(new HelloWorldBox(this));
243
- this.pipeline.add(this.gameScene);
244
-
245
- // Add orbiting circle
246
- this.floatingCircle = new Circle(30, {
247
- x: this.width / 2 + 200,
248
- y: this.height / 2,
249
- color: '#0f0'
250
- });
251
- this.floatingCircle.animTime = 0;
252
- this.pipeline.add(this.floatingCircle);
253
-
254
- // Add FPS counter
255
- this.pipeline.add(new FPSCounter(this, {
256
- anchor: 'bottom-right'
257
- }));
258
- }
259
-
260
- update(dt) {
261
- super.update(dt);
262
-
263
- // Center the scene
264
- this.gameScene.x = this.width / 2;
265
- this.gameScene.y = this.height / 2;
266
-
267
- // Orbit the circle
268
- this.floatingCircle.animTime += dt;
269
- const orbit = Motion.orbit(
270
- this.width / 2, this.height / 2,
271
- 200, 200, // radius X, Y
272
- 0, // start angle
273
- this.floatingCircle.animTime,
274
- 8, // 8 second orbit
275
- true, // loop
276
- true // clockwise
277
- );
278
- this.floatingCircle.x = orbit.x;
279
- this.floatingCircle.y = orbit.y;
280
- }
281
- }
282
-
283
- // Run the game
284
- window.addEventListener('load', () => {
285
- const canvas = document.getElementById('game');
286
- const game = new DemoGame(canvas);
287
- game.start();
288
- });
289
- ```
290
-
291
- ## HTML Template
292
-
293
- ```html
294
- <!DOCTYPE html>
295
- <html>
296
- <head>
297
- <meta charset="UTF-8">
298
- <title>My First Game</title>
299
- <style>
300
- body { margin: 0; overflow: hidden; }
301
- canvas { display: block; }
302
- </style>
303
- </head>
304
- <body>
305
- <canvas id="game"></canvas>
306
- <script type="module" src="./game.js"></script>
307
- </body>
308
- </html>
309
- ```
310
-
311
- ## Key Concepts
312
-
313
- | Concept | Description |
314
- |---------|-------------|
315
- | `Game` | Main class managing loop, canvas, input |
316
- | `Scene` | Container for GameObjects |
317
- | `GameObject` | Interactive entity with update/render |
318
- | `enableInteractivity(shape)` | Enable click/hover on a shape |
319
- | `dt` | Delta time in seconds |
320
- | `game.input.isKeyDown(key)` | Check if key is pressed |
321
- | `Motion.*` | Animation helper functions |
322
- | `FPSCounter` | Built-in FPS display |
323
-
324
- ## Input Reference
325
-
326
- ```js
327
- // Keyboard
328
- game.input.isKeyDown('ArrowUp')
329
- game.input.isKeyDown('KeyW')
330
- game.input.isKeyDown('Space')
331
-
332
- // Mouse position
333
- game.mouse.x
334
- game.mouse.y
335
-
336
- // GameObject events
337
- onPointerDown(e) { }
338
- onPointerUp(e) { }
339
- onPointerMove(e) { }
340
- onMouseOver() { }
341
- onMouseOut() { }
342
- ```
343
-
344
- ## Next Steps
345
-
346
- - [Game Module](../modules/game/README.md) - Full Game API reference
347
- - [Motion Patterns](../modules/motion/README.md) - Animation functions
348
- - [Input Handling](../modules/io/README.md) - Mouse, keyboard, touch
349
-
350
- ## Related
351
-
352
- - [Hello World](./hello-world.md)
353
- - [Two-Layer Architecture](../concepts/two-layer-architecture.md)
354
- - [Game Lifecycle](../concepts/lifecycle.md)
1
+ # First Game
2
+
3
+ > Create an interactive game with the Game layer.
4
+
5
+ ## Overview
6
+
7
+ This guide shows how to use the Game layer to create interactive applications. We'll build a simple game with keyboard input, collision detection, and animations.
8
+
9
+ ## Basic Game Setup
10
+
11
+ ```js
12
+ import { Game, Scene, GameObject, Circle, Group, Rectangle, TextShape } from '@guinetik/gcanvas';
13
+
14
+ class MyGame extends Game {
15
+ constructor(canvas) {
16
+ super(canvas);
17
+ this.enableFluidSize(); // Canvas fills window
18
+ this.backgroundColor = '#1a1a2e';
19
+ }
20
+
21
+ init() {
22
+ super.init(); // Initialize input systems
23
+
24
+ // Create a scene
25
+ this.scene = new Scene(this);
26
+ this.pipeline.add(this.scene);
27
+
28
+ // Add game objects
29
+ this.scene.add(new Player(this));
30
+ }
31
+ }
32
+
33
+ // Start the game
34
+ const canvas = document.getElementById('game');
35
+ const game = new MyGame(canvas);
36
+ game.start();
37
+ ```
38
+
39
+ ## Creating a Player
40
+
41
+ ```js
42
+ class Player extends GameObject {
43
+ constructor(game) {
44
+ super(game);
45
+
46
+ // Create the player shape
47
+ this.shape = new Circle(30, {
48
+ color: '#4ecdc4',
49
+ stroke: '#fff',
50
+ lineWidth: 2
51
+ });
52
+
53
+ // Position at center
54
+ this.shape.x = game.width / 2;
55
+ this.shape.y = game.height / 2;
56
+
57
+ // Movement speed (pixels per second)
58
+ this.speed = 300;
59
+
60
+ // Enable mouse/touch input on this shape
61
+ this.enableInteractivity(this.shape);
62
+ }
63
+
64
+ update(dt) {
65
+ // Handle keyboard input
66
+ const input = this.game.input;
67
+
68
+ if (input.isKeyDown('ArrowLeft') || input.isKeyDown('KeyA')) {
69
+ this.shape.x -= this.speed * dt;
70
+ }
71
+ if (input.isKeyDown('ArrowRight') || input.isKeyDown('KeyD')) {
72
+ this.shape.x += this.speed * dt;
73
+ }
74
+ if (input.isKeyDown('ArrowUp') || input.isKeyDown('KeyW')) {
75
+ this.shape.y -= this.speed * dt;
76
+ }
77
+ if (input.isKeyDown('ArrowDown') || input.isKeyDown('KeyS')) {
78
+ this.shape.y += this.speed * dt;
79
+ }
80
+
81
+ // Keep player on screen
82
+ this.shape.x = Math.max(30, Math.min(this.game.width - 30, this.shape.x));
83
+ this.shape.y = Math.max(30, Math.min(this.game.height - 30, this.shape.y));
84
+ }
85
+
86
+ render() {
87
+ this.shape.draw();
88
+ }
89
+
90
+ // Called when player is clicked
91
+ onPointerDown(e) {
92
+ console.log('Player clicked!');
93
+ }
94
+ }
95
+ ```
96
+
97
+ ## Adding Enemies
98
+
99
+ ```js
100
+ class Enemy extends GameObject {
101
+ constructor(game, x, y) {
102
+ super(game);
103
+
104
+ this.shape = new Rectangle({
105
+ x: x,
106
+ y: y,
107
+ width: 40,
108
+ height: 40,
109
+ color: '#ff6b6b'
110
+ });
111
+
112
+ // Random direction
113
+ this.vx = (Math.random() - 0.5) * 200;
114
+ this.vy = (Math.random() - 0.5) * 200;
115
+ }
116
+
117
+ update(dt) {
118
+ // Move
119
+ this.shape.x += this.vx * dt;
120
+ this.shape.y += this.vy * dt;
121
+
122
+ // Bounce off walls
123
+ if (this.shape.x < 20 || this.shape.x > this.game.width - 20) {
124
+ this.vx *= -1;
125
+ }
126
+ if (this.shape.y < 20 || this.shape.y > this.game.height - 20) {
127
+ this.vy *= -1;
128
+ }
129
+
130
+ // Rotate
131
+ this.shape.rotation += dt * 2;
132
+ }
133
+
134
+ render() {
135
+ this.shape.draw();
136
+ }
137
+ }
138
+ ```
139
+
140
+ ## Complete Game Example
141
+
142
+ Here's a complete game from `demos/js/basic.js`:
143
+
144
+ ```js
145
+ import {
146
+ Game,
147
+ GameObject,
148
+ Scene,
149
+ Circle,
150
+ Rectangle,
151
+ TextShape,
152
+ Group,
153
+ Motion,
154
+ Easing,
155
+ FPSCounter
156
+ } from '@guinetik/gcanvas';
157
+
158
+ /**
159
+ * HelloWorldBox - A simple animated text box
160
+ */
161
+ class HelloWorldBox extends GameObject {
162
+ constructor(game) {
163
+ super(game);
164
+
165
+ // Create a group to hold shapes
166
+ this.group = new Group({});
167
+
168
+ // Background box
169
+ this.box = new Rectangle({
170
+ width: 200,
171
+ height: 80,
172
+ color: '#333'
173
+ });
174
+
175
+ // Text label
176
+ this.label = new TextShape('Hello World!', {
177
+ font: '18px monospace',
178
+ color: '#0f0',
179
+ align: 'center',
180
+ baseline: 'middle'
181
+ });
182
+
183
+ // Add to group
184
+ this.group.add(this.box);
185
+ this.group.add(this.label);
186
+
187
+ // Animation time
188
+ this.animTime = 0;
189
+ }
190
+
191
+ update(dt) {
192
+ this.animTime += dt;
193
+
194
+ // Pulse the text opacity
195
+ const pulse = Motion.pulse(
196
+ 0, 1, // min, max opacity
197
+ this.animTime,
198
+ 2, // 2 second cycle
199
+ true, // loop
200
+ false, // no yoyo
201
+ Easing.easeInOutSine
202
+ );
203
+ this.label.opacity = pulse.value;
204
+
205
+ // Float the group
206
+ const float = Motion.float(
207
+ { x: 0, y: 0 },
208
+ this.animTime,
209
+ 5, // 5 second cycle
210
+ 0.5, // speed
211
+ 0.5, // randomness
212
+ 50, // radius
213
+ true,
214
+ Easing.easeInOutSine
215
+ );
216
+ this.group.x = float.x;
217
+ this.group.y = float.y;
218
+
219
+ super.update(dt);
220
+ }
221
+
222
+ render() {
223
+ this.group.render();
224
+ }
225
+ }
226
+
227
+ /**
228
+ * DemoGame - Main game class
229
+ */
230
+ class DemoGame extends Game {
231
+ constructor(canvas) {
232
+ super(canvas);
233
+ this.enableFluidSize();
234
+ this.backgroundColor = 'black';
235
+ }
236
+
237
+ init() {
238
+ super.init();
239
+
240
+ // Create main scene
241
+ this.gameScene = new Scene(this);
242
+ this.gameScene.add(new HelloWorldBox(this));
243
+ this.pipeline.add(this.gameScene);
244
+
245
+ // Add orbiting circle
246
+ this.floatingCircle = new Circle(30, {
247
+ x: this.width / 2 + 200,
248
+ y: this.height / 2,
249
+ color: '#0f0'
250
+ });
251
+ this.floatingCircle.animTime = 0;
252
+ this.pipeline.add(this.floatingCircle);
253
+
254
+ // Add FPS counter
255
+ this.pipeline.add(new FPSCounter(this, {
256
+ anchor: 'bottom-right'
257
+ }));
258
+ }
259
+
260
+ update(dt) {
261
+ super.update(dt);
262
+
263
+ // Center the scene
264
+ this.gameScene.x = this.width / 2;
265
+ this.gameScene.y = this.height / 2;
266
+
267
+ // Orbit the circle
268
+ this.floatingCircle.animTime += dt;
269
+ const orbit = Motion.orbit(
270
+ this.width / 2, this.height / 2,
271
+ 200, 200, // radius X, Y
272
+ 0, // start angle
273
+ this.floatingCircle.animTime,
274
+ 8, // 8 second orbit
275
+ true, // loop
276
+ true // clockwise
277
+ );
278
+ this.floatingCircle.x = orbit.x;
279
+ this.floatingCircle.y = orbit.y;
280
+ }
281
+ }
282
+
283
+ // Run the game
284
+ window.addEventListener('load', () => {
285
+ const canvas = document.getElementById('game');
286
+ const game = new DemoGame(canvas);
287
+ game.start();
288
+ });
289
+ ```
290
+
291
+ ## HTML Template
292
+
293
+ ```html
294
+ <!DOCTYPE html>
295
+ <html>
296
+ <head>
297
+ <meta charset="UTF-8">
298
+ <title>My First Game</title>
299
+ <style>
300
+ body { margin: 0; overflow: hidden; }
301
+ canvas { display: block; }
302
+ </style>
303
+ </head>
304
+ <body>
305
+ <canvas id="game"></canvas>
306
+ <script type="module" src="./game.js"></script>
307
+ </body>
308
+ </html>
309
+ ```
310
+
311
+ ## Key Concepts
312
+
313
+ | Concept | Description |
314
+ |---------|-------------|
315
+ | `Game` | Main class managing loop, canvas, input |
316
+ | `Scene` | Container for GameObjects |
317
+ | `GameObject` | Interactive entity with update/render |
318
+ | `enableInteractivity(shape)` | Enable click/hover on a shape |
319
+ | `dt` | Delta time in seconds |
320
+ | `game.input.isKeyDown(key)` | Check if key is pressed |
321
+ | `Motion.*` | Animation helper functions |
322
+ | `FPSCounter` | Built-in FPS display |
323
+
324
+ ## Input Reference
325
+
326
+ ```js
327
+ // Keyboard
328
+ game.input.isKeyDown('ArrowUp')
329
+ game.input.isKeyDown('KeyW')
330
+ game.input.isKeyDown('Space')
331
+
332
+ // Mouse position
333
+ game.mouse.x
334
+ game.mouse.y
335
+
336
+ // GameObject events
337
+ onPointerDown(e) { }
338
+ onPointerUp(e) { }
339
+ onPointerMove(e) { }
340
+ onMouseOver() { }
341
+ onMouseOut() { }
342
+ ```
343
+
344
+ ## Next Steps
345
+
346
+ - [Game Module](../modules/game/README.md) - Full Game API reference
347
+ - [Motion Patterns](../modules/motion/README.md) - Animation functions
348
+ - [Input Handling](../modules/io/README.md) - Mouse, keyboard, touch
349
+
350
+ ## Related
351
+
352
+ - [Hello World](./hello-world.md)
353
+ - [Two-Layer Architecture](../concepts/two-layer-architecture.md)
354
+ - [Game Lifecycle](../concepts/lifecycle.md)