@guinetik/gcanvas 1.0.0 → 1.0.2
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/demos/coordinates.html +698 -0
- package/demos/cube3d.html +23 -0
- package/demos/demos.css +17 -3
- package/demos/dino.html +42 -0
- package/demos/fluid-simple.html +22 -0
- package/demos/fluid.html +37 -0
- package/demos/gameobjects.html +626 -0
- package/demos/index.html +19 -7
- package/demos/js/blob.js +18 -5
- package/demos/js/coordinates.js +840 -0
- package/demos/js/cube3d.js +789 -0
- package/demos/js/dino.js +1420 -0
- package/demos/js/fluid-simple.js +253 -0
- package/demos/js/fluid.js +527 -0
- package/demos/js/gameobjects.js +176 -0
- package/demos/js/plane3d.js +256 -0
- package/demos/js/platformer.js +1579 -0
- package/demos/js/sphere3d.js +229 -0
- package/demos/js/sprite.js +473 -0
- package/demos/js/tde/accretiondisk.js +65 -12
- package/demos/js/tde/blackholescene.js +2 -2
- package/demos/js/tde/config.js +2 -2
- package/demos/js/tde/index.js +152 -27
- package/demos/js/tde/lensedstarfield.js +32 -25
- package/demos/js/tde/tdestar.js +78 -98
- package/demos/js/tde/tidalstream.js +24 -8
- package/demos/plane3d.html +24 -0
- package/demos/platformer.html +43 -0
- package/demos/sphere3d.html +24 -0
- package/demos/sprite.html +18 -0
- package/docs/README.md +230 -222
- package/docs/api/FluidSystem.md +173 -0
- package/docs/concepts/architecture-overview.md +204 -204
- package/docs/concepts/coordinate-system.md +384 -0
- package/docs/concepts/rendering-pipeline.md +279 -279
- package/docs/concepts/shapes-vs-gameobjects.md +187 -0
- package/docs/concepts/two-layer-architecture.md +229 -229
- package/docs/fluid-dynamics.md +99 -0
- package/docs/getting-started/first-game.md +354 -354
- package/docs/getting-started/installation.md +175 -157
- package/docs/modules/collision/README.md +2 -2
- package/docs/modules/fluent/README.md +6 -6
- package/docs/modules/game/README.md +303 -303
- package/docs/modules/isometric-camera.md +2 -2
- package/docs/modules/isometric.md +1 -1
- package/docs/modules/painter/README.md +328 -328
- package/docs/modules/particle/README.md +3 -3
- package/docs/modules/shapes/README.md +221 -221
- package/docs/modules/shapes/base/euclidian.md +123 -123
- package/docs/modules/shapes/base/shape.md +262 -262
- package/docs/modules/shapes/base/transformable.md +243 -243
- package/docs/modules/state/README.md +2 -2
- package/docs/modules/util/README.md +1 -1
- package/docs/modules/util/camera3d.md +3 -3
- package/docs/modules/util/scene3d.md +1 -1
- package/package.json +3 -1
- package/readme.md +19 -5
- package/src/collision/collision.js +75 -0
- package/src/game/game.js +11 -5
- package/src/game/index.js +2 -1
- package/src/game/objects/index.js +3 -0
- package/src/game/objects/platformer-scene.js +411 -0
- package/src/game/objects/scene.js +14 -0
- package/src/game/objects/sprite.js +529 -0
- package/src/game/pipeline.js +20 -16
- package/src/game/systems/FluidSystem.js +835 -0
- package/src/game/systems/index.js +11 -0
- package/src/game/ui/button.js +39 -18
- package/src/game/ui/cursor.js +14 -0
- package/src/game/ui/fps.js +12 -4
- package/src/game/ui/index.js +2 -0
- package/src/game/ui/stepper.js +549 -0
- package/src/game/ui/theme.js +123 -0
- package/src/game/ui/togglebutton.js +9 -3
- package/src/game/ui/tooltip.js +11 -4
- package/src/io/input.js +75 -45
- package/src/io/mouse.js +44 -19
- package/src/io/touch.js +35 -12
- package/src/math/fluid.js +507 -0
- package/src/math/index.js +2 -0
- package/src/mixins/anchor.js +17 -7
- package/src/motion/tweenetik.js +16 -0
- package/src/shapes/cube3d.js +599 -0
- package/src/shapes/index.js +3 -0
- package/src/shapes/plane3d.js +687 -0
- package/src/shapes/sphere3d.js +75 -6
- package/src/util/camera2d.js +315 -0
- package/src/util/camera3d.js +218 -12
- package/src/util/index.js +1 -0
- package/src/webgl/shaders/plane-shaders.js +332 -0
- package/src/webgl/shaders/sphere-shaders.js +4 -2
- package/types/fluent.d.ts +361 -0
- package/types/game.d.ts +303 -0
- package/types/index.d.ts +144 -5
- package/types/math.d.ts +361 -0
- package/types/motion.d.ts +271 -0
- package/types/particle.d.ts +373 -0
- package/types/shapes.d.ts +107 -9
- package/types/util.d.ts +353 -0
- package/types/webgl.d.ts +109 -0
- package/disk_example.png +0 -0
- package/tde.png +0 -0
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
# Shapes vs GameObjects
|
|
2
|
+
|
|
3
|
+
GCanvas serves two distinct use cases with different abstractions. Understanding when to use each is key to working effectively with the library.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
| Aspect | Shapes | GameObjects |
|
|
8
|
+
|--------|--------|-------------|
|
|
9
|
+
| Purpose | Direct canvas rendering | Managed game pipeline |
|
|
10
|
+
| Game loop | Not required | Required |
|
|
11
|
+
| Rendering | Call `render()` manually | Automatic via pipeline |
|
|
12
|
+
| State | Stateless between frames | Maintains state |
|
|
13
|
+
| Lifecycle | None | `update(dt)` / `draw()` |
|
|
14
|
+
| Best for | Generative art, static visuals | Games, animations, interactive apps |
|
|
15
|
+
|
|
16
|
+
## The Two Hierarchies
|
|
17
|
+
|
|
18
|
+
### Shape Hierarchy (Drawing)
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
Euclidian → Geometry2d → Renderable → Transformable → Shape
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
- **Euclidian**: Basic positioning (x, y, width, height)
|
|
25
|
+
- **Geometry2d**: Bounds constraints, bounding box calculations
|
|
26
|
+
- **Renderable**: Visibility, opacity, shadows
|
|
27
|
+
- **Transformable**: Rotation, scaling
|
|
28
|
+
- **Shape**: Styling (fill, stroke, lineWidth)
|
|
29
|
+
|
|
30
|
+
### GameObject Hierarchy (Pipeline)
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
GameObject → Scene / Sprite / Text
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
- **GameObject**: Base class with `update(dt)` and `draw()` lifecycle
|
|
37
|
+
- **Scene**: Container for other GameObjects
|
|
38
|
+
- **Sprite**: Animated GameObject with frame-by-frame timeline
|
|
39
|
+
- **Text**: Text rendering with automatic updates
|
|
40
|
+
|
|
41
|
+
### Containers
|
|
42
|
+
|
|
43
|
+
| Container | Holds | Has update()? |
|
|
44
|
+
|-----------|-------|---------------|
|
|
45
|
+
| `Group` | Shapes | No |
|
|
46
|
+
| `Scene` | GameObjects | Yes |
|
|
47
|
+
|
|
48
|
+
## When to Use What
|
|
49
|
+
|
|
50
|
+
| Use Case | Use This | Why |
|
|
51
|
+
|----------|----------|-----|
|
|
52
|
+
| Static visualization | `Shape` + `render()` | No update loop needed |
|
|
53
|
+
| Generative art | `Shape`, `Group` | Direct control, no overhead |
|
|
54
|
+
| Game character | `Sprite` (GameObject) | Needs update cycle for animation |
|
|
55
|
+
| UI elements | `Text`, `Scene` | Pipeline handles positioning |
|
|
56
|
+
| Complex scene | `Scene` with children | Hierarchical transforms, lifecycle |
|
|
57
|
+
| Composite shape | `Group` | Transform multiple shapes together |
|
|
58
|
+
|
|
59
|
+
## Example: Shapes Only (No Game Loop)
|
|
60
|
+
|
|
61
|
+
You can use GCanvas purely for drawing without any game infrastructure:
|
|
62
|
+
|
|
63
|
+
```javascript
|
|
64
|
+
import { Circle, Rectangle, Group, Painter } from "gcanvas";
|
|
65
|
+
|
|
66
|
+
// Get canvas context
|
|
67
|
+
const canvas = document.getElementById("canvas");
|
|
68
|
+
const ctx = canvas.getContext("2d");
|
|
69
|
+
Painter.ctx = ctx;
|
|
70
|
+
|
|
71
|
+
// Create shapes
|
|
72
|
+
const circle = new Circle(50, { x: 100, y: 100, color: "#0f0" });
|
|
73
|
+
const rect = new Rectangle({ x: 200, y: 100, width: 80, height: 60, color: "#0ff" });
|
|
74
|
+
|
|
75
|
+
// Render directly - no game loop needed
|
|
76
|
+
circle.render();
|
|
77
|
+
rect.render();
|
|
78
|
+
|
|
79
|
+
// Group multiple shapes
|
|
80
|
+
const group = new Group({ x: 300, y: 100, rotation: Math.PI / 4 });
|
|
81
|
+
group.add(new Circle(20, { color: "#f0f" }));
|
|
82
|
+
group.add(new Rectangle({ y: 30, width: 40, height: 20, color: "#ff0" }));
|
|
83
|
+
group.render();
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
> **Note:** This is perfect for one-off drawings, generative art, or when you want full control over the render loop.
|
|
87
|
+
|
|
88
|
+
## Example: GameObjects with Pipeline
|
|
89
|
+
|
|
90
|
+
When you need animation, input handling, and managed lifecycles:
|
|
91
|
+
|
|
92
|
+
```javascript
|
|
93
|
+
import { Game, Scene, Sprite, Text, Circle, Keys } from "gcanvas";
|
|
94
|
+
|
|
95
|
+
class MyGame extends Game {
|
|
96
|
+
init() {
|
|
97
|
+
super.init();
|
|
98
|
+
|
|
99
|
+
// Create a scene (GameObject container)
|
|
100
|
+
this.scene = new Scene(this, { anchor: "center" });
|
|
101
|
+
|
|
102
|
+
// Create a sprite with animation (GameObject)
|
|
103
|
+
this.player = new Sprite(this, { x: 0, y: 0, frameRate: 10 });
|
|
104
|
+
this.player.addFrame(new Circle(20, { color: "#0f0" }));
|
|
105
|
+
this.player.addFrame(new Circle(25, { color: "#0ff" }));
|
|
106
|
+
this.player.play();
|
|
107
|
+
|
|
108
|
+
// Add to scene
|
|
109
|
+
this.scene.add(this.player);
|
|
110
|
+
|
|
111
|
+
// Add scene to pipeline - now it's managed
|
|
112
|
+
this.pipeline.add(this.scene);
|
|
113
|
+
|
|
114
|
+
// Input handling
|
|
115
|
+
this.events.on(Keys.SPACE, () => this.player.pause());
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
update(dt) {
|
|
119
|
+
super.update(dt);
|
|
120
|
+
// Player sprite automatically updates via pipeline
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
> **Note:** GameObjects get their `update(dt)` called automatically by the pipeline each frame.
|
|
126
|
+
|
|
127
|
+
## Bridging: Shape to GameObject
|
|
128
|
+
|
|
129
|
+
Sometimes you have a Shape (or Group of shapes) that you want to add to the pipeline. Use `ShapeGOFactory`:
|
|
130
|
+
|
|
131
|
+
```javascript
|
|
132
|
+
import { Game, Group, Circle, Rectangle, ShapeGOFactory } from "gcanvas";
|
|
133
|
+
|
|
134
|
+
class MyGame extends Game {
|
|
135
|
+
init() {
|
|
136
|
+
super.init();
|
|
137
|
+
|
|
138
|
+
// Create a Group of shapes
|
|
139
|
+
const avatar = new Group();
|
|
140
|
+
avatar.add(new Circle(30, { color: "#0f0" })); // head
|
|
141
|
+
avatar.add(new Rectangle({ y: 50, width: 40, height: 60, color: "#0f0" })); // body
|
|
142
|
+
|
|
143
|
+
// Wrap it as a GameObject so it can join the pipeline
|
|
144
|
+
const avatarGO = ShapeGOFactory.create(this, avatar, {
|
|
145
|
+
x: 100,
|
|
146
|
+
y: 100,
|
|
147
|
+
interactive: true // enables click/hover events
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
// Now it's a proper GameObject
|
|
151
|
+
this.pipeline.add(avatarGO);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
> **Important:** Never put GameObjects inside Groups. Group is a Shape container - it won't call `update()` on its children. Always use Scene for GameObjects.
|
|
157
|
+
|
|
158
|
+
## Quick Reference
|
|
159
|
+
|
|
160
|
+
| Class | Type | Container | Has update()? |
|
|
161
|
+
|-------|------|-----------|---------------|
|
|
162
|
+
| `Circle`, `Rectangle`, etc. | Shape | Group | No |
|
|
163
|
+
| `Group` | Shape container | Group | No |
|
|
164
|
+
| `TextShape` | Shape | Group | No |
|
|
165
|
+
| `GameObject` | Base GO | Scene / Pipeline | Yes |
|
|
166
|
+
| `Scene` | GO container | Scene / Pipeline | Yes |
|
|
167
|
+
| `Sprite` | Animated GO | Scene / Pipeline | Yes |
|
|
168
|
+
| `Text` | Text GO | Scene / Pipeline | Yes |
|
|
169
|
+
|
|
170
|
+
## TL;DR
|
|
171
|
+
|
|
172
|
+
**Just Drawing?**
|
|
173
|
+
- Use `Shape`, `Group`
|
|
174
|
+
- Call `.render()` yourself
|
|
175
|
+
- No Game class needed
|
|
176
|
+
|
|
177
|
+
**Building a Game?**
|
|
178
|
+
- Use `GameObject`, `Scene`, `Sprite`
|
|
179
|
+
- Add to `pipeline`
|
|
180
|
+
- Extend `Game` class
|
|
181
|
+
|
|
182
|
+
## See Also
|
|
183
|
+
|
|
184
|
+
- [Coordinate System](./coordinate-system.md) - How positioning works (center-based, parent-child, Camera3D)
|
|
185
|
+
- [Rendering Pipeline](./rendering-pipeline.md) - Deep dive into the Shape hierarchy
|
|
186
|
+
- [Architecture Overview](./architecture-overview.md) - High-level system design
|
|
187
|
+
- [Lifecycle](./lifecycle.md) - GameObject lifecycle details
|
|
@@ -1,229 +1,229 @@
|
|
|
1
|
-
# Two-Layer Architecture
|
|
2
|
-
|
|
3
|
-
> Understanding when to use the Shape Layer vs the Game Layer.
|
|
4
|
-
|
|
5
|
-
## Overview
|
|
6
|
-
|
|
7
|
-
GCanvas provides two complementary approaches to building canvas applications:
|
|
8
|
-
|
|
9
|
-
1. **Shape Layer** - For declarative, static graphics
|
|
10
|
-
2. **Game Layer** - For interactive, dynamic applications
|
|
11
|
-
|
|
12
|
-
You can use either layer independently or combine them for complex applications.
|
|
13
|
-
|
|
14
|
-
## Shape Layer
|
|
15
|
-
|
|
16
|
-
The Shape Layer is for drawing graphics without a game loop. Shapes are self-contained objects that know how to render themselves.
|
|
17
|
-
|
|
18
|
-
### When to Use
|
|
19
|
-
|
|
20
|
-
- Static visualizations
|
|
21
|
-
- Data charts and graphs
|
|
22
|
-
- Decorative graphics
|
|
23
|
-
- Simple animations (manual redraw)
|
|
24
|
-
- Learning canvas fundamentals
|
|
25
|
-
|
|
26
|
-
### Key Classes
|
|
27
|
-
|
|
28
|
-
- `Shape` and subclasses (`Circle`, `Rectangle`, `Star`, etc.)
|
|
29
|
-
- `Group` for composing shapes
|
|
30
|
-
- `Painter` for direct canvas control
|
|
31
|
-
|
|
32
|
-
### Example
|
|
33
|
-
|
|
34
|
-
```js
|
|
35
|
-
import { Circle, Rectangle, Group, Painter } from 'gcanvas';
|
|
36
|
-
|
|
37
|
-
// Initialize Painter with canvas context
|
|
38
|
-
const canvas = document.getElementById('canvas');
|
|
39
|
-
Painter.init(canvas.getContext('2d'));
|
|
40
|
-
|
|
41
|
-
// Create shapes
|
|
42
|
-
const circle = new Circle(50, { x: 100, y: 100, color: 'red' });
|
|
43
|
-
const rect = new Rectangle(80, 40, { x: 200, y: 100, color: 'blue' });
|
|
44
|
-
|
|
45
|
-
// Draw immediately
|
|
46
|
-
Painter.clear();
|
|
47
|
-
circle.draw();
|
|
48
|
-
rect.draw();
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
### Characteristics
|
|
52
|
-
|
|
53
|
-
| Aspect | Shape Layer |
|
|
54
|
-
|--------|-------------|
|
|
55
|
-
| Loop | None (manual redraw) |
|
|
56
|
-
| State | Shapes hold their own state |
|
|
57
|
-
| Input | Manual event handling |
|
|
58
|
-
| Animation | Call draw() on each frame manually |
|
|
59
|
-
| Complexity | Simple, direct |
|
|
60
|
-
|
|
61
|
-
## Game Layer
|
|
62
|
-
|
|
63
|
-
The Game Layer provides a complete game loop with automatic updates, rendering, and input handling.
|
|
64
|
-
|
|
65
|
-
### When to Use
|
|
66
|
-
|
|
67
|
-
- Games and simulations
|
|
68
|
-
- Interactive applications
|
|
69
|
-
- Real-time animations
|
|
70
|
-
- Complex state management
|
|
71
|
-
- Multi-object coordination
|
|
72
|
-
|
|
73
|
-
### Key Classes
|
|
74
|
-
|
|
75
|
-
- `Game` - Main loop and canvas management
|
|
76
|
-
- `Pipeline` - Object lifecycle management
|
|
77
|
-
- `GameObject` - Interactive entities
|
|
78
|
-
- `Scene` - Hierarchical organization
|
|
79
|
-
|
|
80
|
-
### Example
|
|
81
|
-
|
|
82
|
-
```js
|
|
83
|
-
import { Game, Scene, GameObject, Circle } from 'gcanvas';
|
|
84
|
-
|
|
85
|
-
class Player extends GameObject {
|
|
86
|
-
constructor(game) {
|
|
87
|
-
super(game);
|
|
88
|
-
this.shape = new Circle(40, { color: 'blue' });
|
|
89
|
-
this.enableInteractivity(this.shape);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
update(dt) {
|
|
93
|
-
// Called every frame
|
|
94
|
-
if (this.game.input.isKeyDown('ArrowRight')) {
|
|
95
|
-
this.shape.x += 200 * dt;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
render() {
|
|
100
|
-
// Called every frame after update
|
|
101
|
-
this.shape.draw();
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
onPointerDown(e) {
|
|
105
|
-
// Automatic input handling
|
|
106
|
-
console.log('Clicked!');
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
class MyGame extends Game {
|
|
111
|
-
init() {
|
|
112
|
-
this.enableFluidSize();
|
|
113
|
-
const scene = new Scene(this);
|
|
114
|
-
scene.add(new Player(this));
|
|
115
|
-
this.pipeline.add(scene);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const game = new MyGame(document.getElementById('canvas'));
|
|
120
|
-
game.start();
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
### Characteristics
|
|
124
|
-
|
|
125
|
-
| Aspect | Game Layer |
|
|
126
|
-
|--------|-------------|
|
|
127
|
-
| Loop | Automatic (requestAnimationFrame) |
|
|
128
|
-
| State | Managed by Pipeline |
|
|
129
|
-
| Input | Automatic dispatching to objects |
|
|
130
|
-
| Animation | Built-in with dt (delta time) |
|
|
131
|
-
| Complexity | Full-featured |
|
|
132
|
-
|
|
133
|
-
## Comparison
|
|
134
|
-
|
|
135
|
-
```
|
|
136
|
-
┌─────────────────────────────────────────────────────────────┐
|
|
137
|
-
│ Shape Layer │
|
|
138
|
-
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
|
|
139
|
-
│ │ Circle │ │Rectangle│ │ Star │ ... more shapes │
|
|
140
|
-
│ └────┬────┘ └────┬────┘ └────┬────┘ │
|
|
141
|
-
│ │ │ │ │
|
|
142
|
-
│ └────────────┼────────────┘ │
|
|
143
|
-
│ ▼ │
|
|
144
|
-
│ ┌──────────┐ │
|
|
145
|
-
│ │ Group │ (optional composition) │
|
|
146
|
-
│ └────┬─────┘ │
|
|
147
|
-
│ │ │
|
|
148
|
-
│ ▼ │
|
|
149
|
-
│ ┌──────────┐ │
|
|
150
|
-
│ │ draw() │ (manual call) │
|
|
151
|
-
│ └──────────┘ │
|
|
152
|
-
└─────────────────────────────────────────────────────────────┘
|
|
153
|
-
|
|
154
|
-
┌─────────────────────────────────────────────────────────────┐
|
|
155
|
-
│ Game Layer │
|
|
156
|
-
│ ┌─────────────────────────────────────────────────────┐ │
|
|
157
|
-
│ │ Game │ │
|
|
158
|
-
│ │ ┌─────────────────────────────────────────────┐ │ │
|
|
159
|
-
│ │ │ Pipeline │ │ │
|
|
160
|
-
│ │ │ ┌─────────────────────────────────────┐ │ │ │
|
|
161
|
-
│ │ │ │ Scene │ │ │ │
|
|
162
|
-
│ │ │ │ ┌───────────┐ ┌───────────┐ │ │ │ │
|
|
163
|
-
│ │ │ │ │GameObject │ │GameObject │ ... │ │ │ │
|
|
164
|
-
│ │ │ │ │ + Shape │ │ + Shape │ │ │ │ │
|
|
165
|
-
│ │ │ │ └───────────┘ └───────────┘ │ │ │ │
|
|
166
|
-
│ │ │ └─────────────────────────────────────┘ │ │ │
|
|
167
|
-
│ │ └─────────────────────────────────────────────┘ │ │
|
|
168
|
-
│ └─────────────────────────────────────────────────────┘ │
|
|
169
|
-
│ │ │
|
|
170
|
-
│ ▼ │
|
|
171
|
-
│ ┌────────────┐ │
|
|
172
|
-
│ │ Game Loop │ (automatic) │
|
|
173
|
-
│ │ update(dt) │ │
|
|
174
|
-
│ │ render() │ │
|
|
175
|
-
│ └────────────┘ │
|
|
176
|
-
└─────────────────────────────────────────────────────────────┘
|
|
177
|
-
```
|
|
178
|
-
|
|
179
|
-
## Mixing Layers
|
|
180
|
-
|
|
181
|
-
You can use shapes without GameObjects, or combine both approaches:
|
|
182
|
-
|
|
183
|
-
```js
|
|
184
|
-
class HybridGame extends Game {
|
|
185
|
-
init() {
|
|
186
|
-
// Game layer for interactive elements
|
|
187
|
-
const scene = new Scene(this);
|
|
188
|
-
scene.add(new Player(this));
|
|
189
|
-
this.pipeline.add(scene);
|
|
190
|
-
|
|
191
|
-
// Shape layer for static background
|
|
192
|
-
this.background = new Group();
|
|
193
|
-
this.background.add(new Rectangle(this.width, this.height, { color: '#222' }));
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
render() {
|
|
197
|
-
// Draw static shapes first
|
|
198
|
-
this.background.draw();
|
|
199
|
-
|
|
200
|
-
// Then let pipeline draw interactive objects
|
|
201
|
-
super.render();
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
## Decision Guide
|
|
207
|
-
|
|
208
|
-
| If you need... | Use |
|
|
209
|
-
|---------------|-----|
|
|
210
|
-
| Static graphics | Shape Layer |
|
|
211
|
-
| Simple animations | Shape Layer + manual loop |
|
|
212
|
-
| Keyboard/mouse input | Game Layer |
|
|
213
|
-
| Multiple interactive objects | Game Layer |
|
|
214
|
-
| Collision detection | Game Layer |
|
|
215
|
-
| Scene organization | Game Layer |
|
|
216
|
-
| Quick prototype | Shape Layer |
|
|
217
|
-
| Full game | Game Layer |
|
|
218
|
-
|
|
219
|
-
## Related
|
|
220
|
-
|
|
221
|
-
- [Architecture Overview](./architecture-overview.md) - Full system architecture
|
|
222
|
-
- [Rendering Pipeline](./rendering-pipeline.md) - Shape inheritance chain
|
|
223
|
-
- [Game Lifecycle](./lifecycle.md) - Update/render cycle
|
|
224
|
-
|
|
225
|
-
## See Also
|
|
226
|
-
|
|
227
|
-
- [Shapes Module](../modules/shapes/README.md)
|
|
228
|
-
- [Game Module](../modules/game/README.md)
|
|
229
|
-
- [Getting Started: Hello World](../getting-started/hello-world.md)
|
|
1
|
+
# Two-Layer Architecture
|
|
2
|
+
|
|
3
|
+
> Understanding when to use the Shape Layer vs the Game Layer.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
GCanvas provides two complementary approaches to building canvas applications:
|
|
8
|
+
|
|
9
|
+
1. **Shape Layer** - For declarative, static graphics
|
|
10
|
+
2. **Game Layer** - For interactive, dynamic applications
|
|
11
|
+
|
|
12
|
+
You can use either layer independently or combine them for complex applications.
|
|
13
|
+
|
|
14
|
+
## Shape Layer
|
|
15
|
+
|
|
16
|
+
The Shape Layer is for drawing graphics without a game loop. Shapes are self-contained objects that know how to render themselves.
|
|
17
|
+
|
|
18
|
+
### When to Use
|
|
19
|
+
|
|
20
|
+
- Static visualizations
|
|
21
|
+
- Data charts and graphs
|
|
22
|
+
- Decorative graphics
|
|
23
|
+
- Simple animations (manual redraw)
|
|
24
|
+
- Learning canvas fundamentals
|
|
25
|
+
|
|
26
|
+
### Key Classes
|
|
27
|
+
|
|
28
|
+
- `Shape` and subclasses (`Circle`, `Rectangle`, `Star`, etc.)
|
|
29
|
+
- `Group` for composing shapes
|
|
30
|
+
- `Painter` for direct canvas control
|
|
31
|
+
|
|
32
|
+
### Example
|
|
33
|
+
|
|
34
|
+
```js
|
|
35
|
+
import { Circle, Rectangle, Group, Painter } from '@guinetik/gcanvas';
|
|
36
|
+
|
|
37
|
+
// Initialize Painter with canvas context
|
|
38
|
+
const canvas = document.getElementById('canvas');
|
|
39
|
+
Painter.init(canvas.getContext('2d'));
|
|
40
|
+
|
|
41
|
+
// Create shapes
|
|
42
|
+
const circle = new Circle(50, { x: 100, y: 100, color: 'red' });
|
|
43
|
+
const rect = new Rectangle(80, 40, { x: 200, y: 100, color: 'blue' });
|
|
44
|
+
|
|
45
|
+
// Draw immediately
|
|
46
|
+
Painter.clear();
|
|
47
|
+
circle.draw();
|
|
48
|
+
rect.draw();
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Characteristics
|
|
52
|
+
|
|
53
|
+
| Aspect | Shape Layer |
|
|
54
|
+
|--------|-------------|
|
|
55
|
+
| Loop | None (manual redraw) |
|
|
56
|
+
| State | Shapes hold their own state |
|
|
57
|
+
| Input | Manual event handling |
|
|
58
|
+
| Animation | Call draw() on each frame manually |
|
|
59
|
+
| Complexity | Simple, direct |
|
|
60
|
+
|
|
61
|
+
## Game Layer
|
|
62
|
+
|
|
63
|
+
The Game Layer provides a complete game loop with automatic updates, rendering, and input handling.
|
|
64
|
+
|
|
65
|
+
### When to Use
|
|
66
|
+
|
|
67
|
+
- Games and simulations
|
|
68
|
+
- Interactive applications
|
|
69
|
+
- Real-time animations
|
|
70
|
+
- Complex state management
|
|
71
|
+
- Multi-object coordination
|
|
72
|
+
|
|
73
|
+
### Key Classes
|
|
74
|
+
|
|
75
|
+
- `Game` - Main loop and canvas management
|
|
76
|
+
- `Pipeline` - Object lifecycle management
|
|
77
|
+
- `GameObject` - Interactive entities
|
|
78
|
+
- `Scene` - Hierarchical organization
|
|
79
|
+
|
|
80
|
+
### Example
|
|
81
|
+
|
|
82
|
+
```js
|
|
83
|
+
import { Game, Scene, GameObject, Circle } from '@guinetik/gcanvas';
|
|
84
|
+
|
|
85
|
+
class Player extends GameObject {
|
|
86
|
+
constructor(game) {
|
|
87
|
+
super(game);
|
|
88
|
+
this.shape = new Circle(40, { color: 'blue' });
|
|
89
|
+
this.enableInteractivity(this.shape);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
update(dt) {
|
|
93
|
+
// Called every frame
|
|
94
|
+
if (this.game.input.isKeyDown('ArrowRight')) {
|
|
95
|
+
this.shape.x += 200 * dt;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
render() {
|
|
100
|
+
// Called every frame after update
|
|
101
|
+
this.shape.draw();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
onPointerDown(e) {
|
|
105
|
+
// Automatic input handling
|
|
106
|
+
console.log('Clicked!');
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
class MyGame extends Game {
|
|
111
|
+
init() {
|
|
112
|
+
this.enableFluidSize();
|
|
113
|
+
const scene = new Scene(this);
|
|
114
|
+
scene.add(new Player(this));
|
|
115
|
+
this.pipeline.add(scene);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const game = new MyGame(document.getElementById('canvas'));
|
|
120
|
+
game.start();
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Characteristics
|
|
124
|
+
|
|
125
|
+
| Aspect | Game Layer |
|
|
126
|
+
|--------|-------------|
|
|
127
|
+
| Loop | Automatic (requestAnimationFrame) |
|
|
128
|
+
| State | Managed by Pipeline |
|
|
129
|
+
| Input | Automatic dispatching to objects |
|
|
130
|
+
| Animation | Built-in with dt (delta time) |
|
|
131
|
+
| Complexity | Full-featured |
|
|
132
|
+
|
|
133
|
+
## Comparison
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
137
|
+
│ Shape Layer │
|
|
138
|
+
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
|
|
139
|
+
│ │ Circle │ │Rectangle│ │ Star │ ... more shapes │
|
|
140
|
+
│ └────┬────┘ └────┬────┘ └────┬────┘ │
|
|
141
|
+
│ │ │ │ │
|
|
142
|
+
│ └────────────┼────────────┘ │
|
|
143
|
+
│ ▼ │
|
|
144
|
+
│ ┌──────────┐ │
|
|
145
|
+
│ │ Group │ (optional composition) │
|
|
146
|
+
│ └────┬─────┘ │
|
|
147
|
+
│ │ │
|
|
148
|
+
│ ▼ │
|
|
149
|
+
│ ┌──────────┐ │
|
|
150
|
+
│ │ draw() │ (manual call) │
|
|
151
|
+
│ └──────────┘ │
|
|
152
|
+
└─────────────────────────────────────────────────────────────┘
|
|
153
|
+
|
|
154
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
155
|
+
│ Game Layer │
|
|
156
|
+
│ ┌─────────────────────────────────────────────────────┐ │
|
|
157
|
+
│ │ Game │ │
|
|
158
|
+
│ │ ┌─────────────────────────────────────────────┐ │ │
|
|
159
|
+
│ │ │ Pipeline │ │ │
|
|
160
|
+
│ │ │ ┌─────────────────────────────────────┐ │ │ │
|
|
161
|
+
│ │ │ │ Scene │ │ │ │
|
|
162
|
+
│ │ │ │ ┌───────────┐ ┌───────────┐ │ │ │ │
|
|
163
|
+
│ │ │ │ │GameObject │ │GameObject │ ... │ │ │ │
|
|
164
|
+
│ │ │ │ │ + Shape │ │ + Shape │ │ │ │ │
|
|
165
|
+
│ │ │ │ └───────────┘ └───────────┘ │ │ │ │
|
|
166
|
+
│ │ │ └─────────────────────────────────────┘ │ │ │
|
|
167
|
+
│ │ └─────────────────────────────────────────────┘ │ │
|
|
168
|
+
│ └─────────────────────────────────────────────────────┘ │
|
|
169
|
+
│ │ │
|
|
170
|
+
│ ▼ │
|
|
171
|
+
│ ┌────────────┐ │
|
|
172
|
+
│ │ Game Loop │ (automatic) │
|
|
173
|
+
│ │ update(dt) │ │
|
|
174
|
+
│ │ render() │ │
|
|
175
|
+
│ └────────────┘ │
|
|
176
|
+
└─────────────────────────────────────────────────────────────┘
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Mixing Layers
|
|
180
|
+
|
|
181
|
+
You can use shapes without GameObjects, or combine both approaches:
|
|
182
|
+
|
|
183
|
+
```js
|
|
184
|
+
class HybridGame extends Game {
|
|
185
|
+
init() {
|
|
186
|
+
// Game layer for interactive elements
|
|
187
|
+
const scene = new Scene(this);
|
|
188
|
+
scene.add(new Player(this));
|
|
189
|
+
this.pipeline.add(scene);
|
|
190
|
+
|
|
191
|
+
// Shape layer for static background
|
|
192
|
+
this.background = new Group();
|
|
193
|
+
this.background.add(new Rectangle(this.width, this.height, { color: '#222' }));
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
render() {
|
|
197
|
+
// Draw static shapes first
|
|
198
|
+
this.background.draw();
|
|
199
|
+
|
|
200
|
+
// Then let pipeline draw interactive objects
|
|
201
|
+
super.render();
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Decision Guide
|
|
207
|
+
|
|
208
|
+
| If you need... | Use |
|
|
209
|
+
|---------------|-----|
|
|
210
|
+
| Static graphics | Shape Layer |
|
|
211
|
+
| Simple animations | Shape Layer + manual loop |
|
|
212
|
+
| Keyboard/mouse input | Game Layer |
|
|
213
|
+
| Multiple interactive objects | Game Layer |
|
|
214
|
+
| Collision detection | Game Layer |
|
|
215
|
+
| Scene organization | Game Layer |
|
|
216
|
+
| Quick prototype | Shape Layer |
|
|
217
|
+
| Full game | Game Layer |
|
|
218
|
+
|
|
219
|
+
## Related
|
|
220
|
+
|
|
221
|
+
- [Architecture Overview](./architecture-overview.md) - Full system architecture
|
|
222
|
+
- [Rendering Pipeline](./rendering-pipeline.md) - Shape inheritance chain
|
|
223
|
+
- [Game Lifecycle](./lifecycle.md) - Update/render cycle
|
|
224
|
+
|
|
225
|
+
## See Also
|
|
226
|
+
|
|
227
|
+
- [Shapes Module](../modules/shapes/README.md)
|
|
228
|
+
- [Game Module](../modules/game/README.md)
|
|
229
|
+
- [Getting Started: Hello World](../getting-started/hello-world.md)
|