@guinetik/gcanvas 1.0.0
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/.github/workflows/release.yaml +70 -0
- package/.jshintrc +4 -0
- package/.vscode/settings.json +22 -0
- package/CLAUDE.md +310 -0
- package/blackhole.jpg +0 -0
- package/demo.png +0 -0
- package/demos/CNAME +1 -0
- package/demos/animations.html +31 -0
- package/demos/basic.html +38 -0
- package/demos/baskara.html +31 -0
- package/demos/bezier.html +35 -0
- package/demos/beziersignature.html +29 -0
- package/demos/blackhole.html +28 -0
- package/demos/blob.html +35 -0
- package/demos/demos.css +289 -0
- package/demos/easing.html +28 -0
- package/demos/events.html +195 -0
- package/demos/fluent.html +647 -0
- package/demos/fractals.html +36 -0
- package/demos/genart.html +26 -0
- package/demos/gendream.html +26 -0
- package/demos/group.html +36 -0
- package/demos/home.html +587 -0
- package/demos/index.html +364 -0
- package/demos/isometric.html +34 -0
- package/demos/js/animations.js +452 -0
- package/demos/js/basic.js +204 -0
- package/demos/js/baskara.js +751 -0
- package/demos/js/bezier.js +692 -0
- package/demos/js/beziersignature.js +241 -0
- package/demos/js/blackhole/accretiondisk.obj.js +379 -0
- package/demos/js/blackhole/blackhole.obj.js +318 -0
- package/demos/js/blackhole/index.js +409 -0
- package/demos/js/blackhole/particle.js +56 -0
- package/demos/js/blackhole/starfield.obj.js +218 -0
- package/demos/js/blob.js +2263 -0
- package/demos/js/easing.js +477 -0
- package/demos/js/fluent.js +183 -0
- package/demos/js/fractals.js +931 -0
- package/demos/js/fractalworker.js +93 -0
- package/demos/js/genart.js +268 -0
- package/demos/js/gendream.js +209 -0
- package/demos/js/group.js +140 -0
- package/demos/js/info-toggle.js +25 -0
- package/demos/js/isometric.js +863 -0
- package/demos/js/kerr.js +1556 -0
- package/demos/js/lavalamp.js +590 -0
- package/demos/js/layout.js +354 -0
- package/demos/js/mondrian.js +285 -0
- package/demos/js/opacity.js +275 -0
- package/demos/js/painter.js +484 -0
- package/demos/js/particles-showcase.js +514 -0
- package/demos/js/particles.js +299 -0
- package/demos/js/patterns.js +397 -0
- package/demos/js/penrose/artifact.js +69 -0
- package/demos/js/penrose/blackhole.js +121 -0
- package/demos/js/penrose/constants.js +73 -0
- package/demos/js/penrose/game.js +943 -0
- package/demos/js/penrose/lore.js +278 -0
- package/demos/js/penrose/penrosescene.js +892 -0
- package/demos/js/penrose/ship.js +216 -0
- package/demos/js/penrose/sounds.js +211 -0
- package/demos/js/penrose/voidparticle.js +55 -0
- package/demos/js/penrose/voidscene.js +258 -0
- package/demos/js/penrose/voidship.js +144 -0
- package/demos/js/penrose/wormhole.js +46 -0
- package/demos/js/pipeline.js +555 -0
- package/demos/js/scene.js +304 -0
- package/demos/js/scenes.js +320 -0
- package/demos/js/schrodinger.js +410 -0
- package/demos/js/schwarzschild.js +1023 -0
- package/demos/js/shapes.js +628 -0
- package/demos/js/space/alien.js +171 -0
- package/demos/js/space/boom.js +98 -0
- package/demos/js/space/boss.js +353 -0
- package/demos/js/space/buff.js +73 -0
- package/demos/js/space/bullet.js +102 -0
- package/demos/js/space/constants.js +85 -0
- package/demos/js/space/game.js +1884 -0
- package/demos/js/space/hud.js +112 -0
- package/demos/js/space/laserbeam.js +179 -0
- package/demos/js/space/lightning.js +277 -0
- package/demos/js/space/minion.js +192 -0
- package/demos/js/space/missile.js +212 -0
- package/demos/js/space/player.js +430 -0
- package/demos/js/space/powerup.js +90 -0
- package/demos/js/space/starfield.js +58 -0
- package/demos/js/space/starpower.js +90 -0
- package/demos/js/spacetime.js +559 -0
- package/demos/js/svgtween.js +204 -0
- package/demos/js/tde/accretiondisk.js +418 -0
- package/demos/js/tde/blackhole.js +219 -0
- package/demos/js/tde/blackholescene.js +209 -0
- package/demos/js/tde/config.js +59 -0
- package/demos/js/tde/index.js +695 -0
- package/demos/js/tde/jets.js +290 -0
- package/demos/js/tde/lensedstarfield.js +147 -0
- package/demos/js/tde/tdestar.js +317 -0
- package/demos/js/tde/tidalstream.js +356 -0
- package/demos/js/tde_old/blackhole.obj.js +354 -0
- package/demos/js/tde_old/debris.obj.js +791 -0
- package/demos/js/tde_old/flare.obj.js +239 -0
- package/demos/js/tde_old/index.js +448 -0
- package/demos/js/tde_old/star.obj.js +812 -0
- package/demos/js/tiles.js +312 -0
- package/demos/js/tweendemo.js +79 -0
- package/demos/js/visibility.js +102 -0
- package/demos/kerr.html +28 -0
- package/demos/lavalamp.html +27 -0
- package/demos/layouts.html +37 -0
- package/demos/logo.svg +4 -0
- package/demos/loop.html +84 -0
- package/demos/mondrian.html +32 -0
- package/demos/og_image.png +0 -0
- package/demos/opacity.html +36 -0
- package/demos/painter.html +39 -0
- package/demos/particles-showcase.html +28 -0
- package/demos/particles.html +24 -0
- package/demos/patterns.html +33 -0
- package/demos/penrose-game.html +31 -0
- package/demos/pipeline.html +737 -0
- package/demos/scene.html +33 -0
- package/demos/scenes.html +96 -0
- package/demos/schrodinger.html +27 -0
- package/demos/schwarzschild.html +27 -0
- package/demos/shapes.html +16 -0
- package/demos/space.html +85 -0
- package/demos/spacetime.html +27 -0
- package/demos/svgtween.html +29 -0
- package/demos/tde.html +28 -0
- package/demos/tiles.html +28 -0
- package/demos/transforms.html +400 -0
- package/demos/tween.html +45 -0
- package/demos/visibility.html +33 -0
- package/disk_example.png +0 -0
- package/docs/README.md +222 -0
- package/docs/concepts/architecture-overview.md +204 -0
- package/docs/concepts/lifecycle.md +255 -0
- package/docs/concepts/rendering-pipeline.md +279 -0
- package/docs/concepts/tde-zorder.md +106 -0
- package/docs/concepts/two-layer-architecture.md +229 -0
- package/docs/getting-started/first-game.md +354 -0
- package/docs/getting-started/hello-world.md +269 -0
- package/docs/getting-started/installation.md +157 -0
- package/docs/modules/collision/README.md +453 -0
- package/docs/modules/fluent/README.md +1075 -0
- package/docs/modules/game/README.md +303 -0
- package/docs/modules/isometric-camera.md +210 -0
- package/docs/modules/isometric.md +275 -0
- package/docs/modules/painter/README.md +328 -0
- package/docs/modules/particle/README.md +559 -0
- package/docs/modules/shapes/README.md +221 -0
- package/docs/modules/shapes/base/euclidian.md +123 -0
- package/docs/modules/shapes/base/geometry2d.md +204 -0
- package/docs/modules/shapes/base/renderable.md +215 -0
- package/docs/modules/shapes/base/shape.md +262 -0
- package/docs/modules/shapes/base/transformable.md +243 -0
- package/docs/modules/shapes/hierarchy.md +218 -0
- package/docs/modules/state/README.md +577 -0
- package/docs/modules/util/README.md +99 -0
- package/docs/modules/util/camera3d.md +412 -0
- package/docs/modules/util/scene3d.md +395 -0
- package/index.html +17 -0
- package/jsdoc.json +50 -0
- package/package.json +55 -0
- package/readme.md +599 -0
- package/scripts/build-demo.js +69 -0
- package/scripts/bundle4llm.js +276 -0
- package/scripts/clearconsole.js +48 -0
- package/src/collision/collision-system.js +332 -0
- package/src/collision/collision.js +303 -0
- package/src/collision/index.js +10 -0
- package/src/fluent/fluent-game.js +430 -0
- package/src/fluent/fluent-go.js +1060 -0
- package/src/fluent/fluent-layer.js +152 -0
- package/src/fluent/fluent-scene.js +291 -0
- package/src/fluent/index.js +98 -0
- package/src/fluent/sketch.js +380 -0
- package/src/game/game.js +467 -0
- package/src/game/index.js +49 -0
- package/src/game/objects/go.js +220 -0
- package/src/game/objects/imagego.js +30 -0
- package/src/game/objects/index.js +54 -0
- package/src/game/objects/isometric-scene.js +260 -0
- package/src/game/objects/layoutscene.js +549 -0
- package/src/game/objects/scene.js +175 -0
- package/src/game/objects/scene3d.js +118 -0
- package/src/game/objects/text.js +221 -0
- package/src/game/objects/wrapper.js +232 -0
- package/src/game/pipeline.js +243 -0
- package/src/game/ui/button.js +396 -0
- package/src/game/ui/cursor.js +93 -0
- package/src/game/ui/fps.js +91 -0
- package/src/game/ui/index.js +5 -0
- package/src/game/ui/togglebutton.js +93 -0
- package/src/game/ui/tooltip.js +249 -0
- package/src/index.js +25 -0
- package/src/io/events.js +20 -0
- package/src/io/index.js +86 -0
- package/src/io/input.js +70 -0
- package/src/io/keys.js +152 -0
- package/src/io/mouse.js +61 -0
- package/src/io/touch.js +39 -0
- package/src/logger/debugtab.js +138 -0
- package/src/logger/index.js +3 -0
- package/src/logger/loggable.js +47 -0
- package/src/logger/logger.js +113 -0
- package/src/math/complex.js +37 -0
- package/src/math/constants.js +1 -0
- package/src/math/fractal.js +1271 -0
- package/src/math/gr.js +201 -0
- package/src/math/heat.js +202 -0
- package/src/math/index.js +12 -0
- package/src/math/noise.js +433 -0
- package/src/math/orbital.js +191 -0
- package/src/math/patterns.js +1339 -0
- package/src/math/penrose.js +259 -0
- package/src/math/quantum.js +115 -0
- package/src/math/random.js +195 -0
- package/src/math/tensor.js +1009 -0
- package/src/mixins/anchor.js +131 -0
- package/src/mixins/draggable.js +72 -0
- package/src/mixins/index.js +2 -0
- package/src/motion/bezier.js +132 -0
- package/src/motion/bounce.js +58 -0
- package/src/motion/easing.js +349 -0
- package/src/motion/float.js +130 -0
- package/src/motion/follow.js +125 -0
- package/src/motion/hop.js +52 -0
- package/src/motion/index.js +82 -0
- package/src/motion/motion.js +1124 -0
- package/src/motion/orbit.js +49 -0
- package/src/motion/oscillate.js +39 -0
- package/src/motion/parabolic.js +141 -0
- package/src/motion/patrol.js +147 -0
- package/src/motion/pendulum.js +48 -0
- package/src/motion/pulse.js +88 -0
- package/src/motion/shake.js +83 -0
- package/src/motion/spiral.js +144 -0
- package/src/motion/spring.js +150 -0
- package/src/motion/swing.js +47 -0
- package/src/motion/tween.js +92 -0
- package/src/motion/tweenetik.js +139 -0
- package/src/motion/waypoint.js +210 -0
- package/src/painter/index.js +8 -0
- package/src/painter/painter.colors.js +331 -0
- package/src/painter/painter.effects.js +230 -0
- package/src/painter/painter.img.js +229 -0
- package/src/painter/painter.js +295 -0
- package/src/painter/painter.lines.js +189 -0
- package/src/painter/painter.opacity.js +41 -0
- package/src/painter/painter.shapes.js +277 -0
- package/src/painter/painter.text.js +273 -0
- package/src/particle/emitter.js +124 -0
- package/src/particle/index.js +11 -0
- package/src/particle/particle-system.js +322 -0
- package/src/particle/particle.js +71 -0
- package/src/particle/updaters.js +170 -0
- package/src/shapes/arc.js +43 -0
- package/src/shapes/arrow.js +33 -0
- package/src/shapes/bezier.js +42 -0
- package/src/shapes/circle.js +62 -0
- package/src/shapes/clouds.js +56 -0
- package/src/shapes/cone.js +219 -0
- package/src/shapes/cross.js +70 -0
- package/src/shapes/cube.js +244 -0
- package/src/shapes/cylinder.js +254 -0
- package/src/shapes/diamond.js +48 -0
- package/src/shapes/euclidian.js +111 -0
- package/src/shapes/figure.js +115 -0
- package/src/shapes/geometry.js +220 -0
- package/src/shapes/group.js +375 -0
- package/src/shapes/heart.js +42 -0
- package/src/shapes/hexagon.js +26 -0
- package/src/shapes/image.js +192 -0
- package/src/shapes/index.js +111 -0
- package/src/shapes/line.js +29 -0
- package/src/shapes/pattern.js +90 -0
- package/src/shapes/pin.js +44 -0
- package/src/shapes/poly.js +31 -0
- package/src/shapes/prism.js +226 -0
- package/src/shapes/rect.js +35 -0
- package/src/shapes/renderable.js +333 -0
- package/src/shapes/ring.js +26 -0
- package/src/shapes/roundrect.js +95 -0
- package/src/shapes/shape.js +117 -0
- package/src/shapes/slice.js +26 -0
- package/src/shapes/sphere.js +314 -0
- package/src/shapes/sphere3d.js +537 -0
- package/src/shapes/square.js +15 -0
- package/src/shapes/star.js +99 -0
- package/src/shapes/svg.js +408 -0
- package/src/shapes/text.js +553 -0
- package/src/shapes/traceable.js +83 -0
- package/src/shapes/transform.js +357 -0
- package/src/shapes/transformable.js +172 -0
- package/src/shapes/triangle.js +26 -0
- package/src/sound/index.js +17 -0
- package/src/sound/sound.js +473 -0
- package/src/sound/synth.analyzer.js +149 -0
- package/src/sound/synth.effects.js +207 -0
- package/src/sound/synth.envelope.js +59 -0
- package/src/sound/synth.js +229 -0
- package/src/sound/synth.musical.js +160 -0
- package/src/sound/synth.noise.js +85 -0
- package/src/sound/synth.oscillators.js +293 -0
- package/src/state/index.js +10 -0
- package/src/state/state-machine.js +371 -0
- package/src/util/camera3d.js +438 -0
- package/src/util/index.js +6 -0
- package/src/util/isometric-camera.js +235 -0
- package/src/util/layout.js +317 -0
- package/src/util/position.js +147 -0
- package/src/util/tasks.js +47 -0
- package/src/util/zindex.js +287 -0
- package/src/webgl/index.js +9 -0
- package/src/webgl/shaders/sphere-shaders.js +994 -0
- package/src/webgl/webgl-renderer.js +388 -0
- package/tde.png +0 -0
- package/test/math/orbital.test.js +61 -0
- package/test/math/tensor.test.js +114 -0
- package/test/particle/emitter.test.js +204 -0
- package/test/particle/particle-system.test.js +310 -0
- package/test/particle/particle.test.js +116 -0
- package/test/particle/updaters.test.js +386 -0
- package/test/setup.js +120 -0
- package/test/shapes/euclidian.test.js +44 -0
- package/test/shapes/geometry.test.js +86 -0
- package/test/shapes/group.test.js +86 -0
- package/test/shapes/rectangle.test.js +64 -0
- package/test/shapes/transform.test.js +379 -0
- package/test/util/camera3d.test.js +428 -0
- package/test/util/scene3d.test.js +352 -0
- package/types/collision.d.ts +249 -0
- package/types/common.d.ts +155 -0
- package/types/game.d.ts +497 -0
- package/types/index.d.ts +309 -0
- package/types/io.d.ts +188 -0
- package/types/logger.d.ts +127 -0
- package/types/math.d.ts +268 -0
- package/types/mixins.d.ts +92 -0
- package/types/motion.d.ts +678 -0
- package/types/painter.d.ts +378 -0
- package/types/shapes.d.ts +864 -0
- package/types/sound.d.ts +672 -0
- package/types/state.d.ts +251 -0
- package/types/util.d.ts +253 -0
- package/vite.config.js +50 -0
- package/vitest.config.js +13 -0
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
# Scene3D
|
|
2
|
+
|
|
3
|
+
> A Scene that automatically projects children through Camera3D for pseudo-3D effects.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Scene3D bridges the GameObject/Scene system with Camera3D. It allows you to position GameObjects in 3D space (x, y, z) and automatically projects them through the camera for rendering.
|
|
8
|
+
|
|
9
|
+
**Key Features:**
|
|
10
|
+
- Extends the standard Scene class
|
|
11
|
+
- Projects children through Camera3D automatically
|
|
12
|
+
- Supports z-coordinate on any GameObject
|
|
13
|
+
- Depth sorting (back-to-front rendering)
|
|
14
|
+
- Perspective scaling based on depth
|
|
15
|
+
|
|
16
|
+
## Quick Start
|
|
17
|
+
|
|
18
|
+
```js
|
|
19
|
+
import { Game, Camera3D, Scene3D, GameObject, Rectangle } from 'gcanvas';
|
|
20
|
+
|
|
21
|
+
class BoxObject extends GameObject {
|
|
22
|
+
constructor(game) {
|
|
23
|
+
super(game);
|
|
24
|
+
this.z = 0; // Add z coordinate
|
|
25
|
+
this.shape = new Rectangle({
|
|
26
|
+
width: 60,
|
|
27
|
+
height: 60,
|
|
28
|
+
color: '#4a9eff',
|
|
29
|
+
stroke: '#fff',
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
draw() {
|
|
34
|
+
this.shape.draw();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
class My3DDemo extends Game {
|
|
39
|
+
init() {
|
|
40
|
+
super.init();
|
|
41
|
+
|
|
42
|
+
// Create camera
|
|
43
|
+
this.camera = new Camera3D({
|
|
44
|
+
rotationX: 0.3,
|
|
45
|
+
perspective: 800,
|
|
46
|
+
});
|
|
47
|
+
this.camera.enableMouseControl(this.canvas);
|
|
48
|
+
|
|
49
|
+
// Create 3D scene (centered on screen)
|
|
50
|
+
this.scene3d = new Scene3D(this, {
|
|
51
|
+
x: this.width / 2,
|
|
52
|
+
y: this.height / 2,
|
|
53
|
+
camera: this.camera,
|
|
54
|
+
depthSort: true,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// Add objects with different z positions
|
|
58
|
+
const front = new BoxObject(this);
|
|
59
|
+
front.x = -80;
|
|
60
|
+
front.z = 100; // In front
|
|
61
|
+
|
|
62
|
+
const middle = new BoxObject(this);
|
|
63
|
+
middle.x = 0;
|
|
64
|
+
middle.z = 0; // Center
|
|
65
|
+
|
|
66
|
+
const back = new BoxObject(this);
|
|
67
|
+
back.x = 80;
|
|
68
|
+
back.z = -100; // Behind
|
|
69
|
+
|
|
70
|
+
this.scene3d.add(front);
|
|
71
|
+
this.scene3d.add(middle);
|
|
72
|
+
this.scene3d.add(back);
|
|
73
|
+
|
|
74
|
+
this.pipeline.add(this.scene3d);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
update(dt) {
|
|
78
|
+
super.update(dt);
|
|
79
|
+
this.camera.update(dt);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Constructor Options
|
|
85
|
+
|
|
86
|
+
```js
|
|
87
|
+
const scene3d = new Scene3D(game, {
|
|
88
|
+
// Position (screen coordinates where scene is centered)
|
|
89
|
+
x: game.width / 2,
|
|
90
|
+
y: game.height / 2,
|
|
91
|
+
|
|
92
|
+
// Required: Camera for projection
|
|
93
|
+
camera: myCamera,
|
|
94
|
+
|
|
95
|
+
// Optional settings
|
|
96
|
+
depthSort: true, // Sort children by depth (back-to-front)
|
|
97
|
+
scaleByDepth: true, // Scale children based on perspective
|
|
98
|
+
});
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
| Option | Type | Default | Description |
|
|
102
|
+
|--------|------|---------|-------------|
|
|
103
|
+
| `camera` | `Camera3D` | **required** | Camera for 3D projection |
|
|
104
|
+
| `depthSort` | `boolean` | `true` | Sort children back-to-front |
|
|
105
|
+
| `scaleByDepth` | `boolean` | `true` | Apply perspective scaling |
|
|
106
|
+
| `x`, `y` | `number` | `0` | Scene position (typically screen center) |
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## Adding Objects
|
|
111
|
+
|
|
112
|
+
Scene3D works with any GameObject. Just add a `z` property:
|
|
113
|
+
|
|
114
|
+
```js
|
|
115
|
+
// Standard GameObject
|
|
116
|
+
class MyObject extends GameObject {
|
|
117
|
+
constructor(game) {
|
|
118
|
+
super(game);
|
|
119
|
+
this.z = 0; // Initialize z coordinate
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Add to scene
|
|
124
|
+
const obj = new MyObject(this);
|
|
125
|
+
obj.x = 100; // Horizontal position
|
|
126
|
+
obj.y = 50; // Vertical position
|
|
127
|
+
obj.z = -200; // Depth (negative = behind, positive = in front)
|
|
128
|
+
scene3d.add(obj);
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
If an object doesn't have a `z` property, it defaults to `0` (center plane).
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Depth Sorting
|
|
136
|
+
|
|
137
|
+
When `depthSort: true`, Scene3D renders objects from back to front, ensuring correct overlap:
|
|
138
|
+
|
|
139
|
+
```js
|
|
140
|
+
// Objects overlap correctly
|
|
141
|
+
const scene3d = new Scene3D(this, {
|
|
142
|
+
camera: this.camera,
|
|
143
|
+
depthSort: true, // Enable depth sorting
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
// Back object won't obscure front object
|
|
147
|
+
backObj.z = -100; // Behind
|
|
148
|
+
frontObj.z = 100; // In front
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Disable for performance if objects don't overlap:
|
|
152
|
+
|
|
153
|
+
```js
|
|
154
|
+
// All objects at same z - no need to sort
|
|
155
|
+
const scene3d = new Scene3D(this, {
|
|
156
|
+
camera: this.camera,
|
|
157
|
+
depthSort: false,
|
|
158
|
+
});
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Perspective Scaling
|
|
164
|
+
|
|
165
|
+
When `scaleByDepth: true`, objects scale based on their distance from the camera:
|
|
166
|
+
|
|
167
|
+
```js
|
|
168
|
+
// Objects shrink as they move away
|
|
169
|
+
const scene3d = new Scene3D(this, {
|
|
170
|
+
camera: this.camera,
|
|
171
|
+
scaleByDepth: true, // Enable perspective scaling
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
nearObj.z = 200; // Appears larger
|
|
175
|
+
farObj.z = -300; // Appears smaller
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Disable for flat rendering (no size change with depth):
|
|
179
|
+
|
|
180
|
+
```js
|
|
181
|
+
// All objects same size regardless of z
|
|
182
|
+
const scene3d = new Scene3D(this, {
|
|
183
|
+
camera: this.camera,
|
|
184
|
+
scaleByDepth: false,
|
|
185
|
+
});
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## Common Patterns
|
|
191
|
+
|
|
192
|
+
### Responsive Centering
|
|
193
|
+
|
|
194
|
+
Keep Scene3D centered when window resizes:
|
|
195
|
+
|
|
196
|
+
```js
|
|
197
|
+
class MyDemo extends Game {
|
|
198
|
+
init() {
|
|
199
|
+
super.init();
|
|
200
|
+
this.enableFluidSize();
|
|
201
|
+
|
|
202
|
+
this.scene3d = new Scene3D(this, {
|
|
203
|
+
x: this.width / 2,
|
|
204
|
+
y: this.height / 2,
|
|
205
|
+
camera: this.camera,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
update(dt) {
|
|
210
|
+
super.update(dt);
|
|
211
|
+
|
|
212
|
+
// Keep centered on resize
|
|
213
|
+
this.scene3d.x = this.width / 2;
|
|
214
|
+
this.scene3d.y = this.height / 2;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Grid of Objects
|
|
220
|
+
|
|
221
|
+
Create a 3D grid layout:
|
|
222
|
+
|
|
223
|
+
```js
|
|
224
|
+
const spacing = 80;
|
|
225
|
+
const gridSize = 5;
|
|
226
|
+
|
|
227
|
+
for (let x = 0; x < gridSize; x++) {
|
|
228
|
+
for (let z = 0; z < gridSize; z++) {
|
|
229
|
+
const obj = new GridCell(this);
|
|
230
|
+
obj.x = (x - gridSize / 2) * spacing;
|
|
231
|
+
obj.y = 0;
|
|
232
|
+
obj.z = (z - gridSize / 2) * spacing;
|
|
233
|
+
this.scene3d.add(obj);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Orbiting Objects
|
|
239
|
+
|
|
240
|
+
Animate z-coordinates for 3D motion:
|
|
241
|
+
|
|
242
|
+
```js
|
|
243
|
+
class OrbitingObject extends GameObject {
|
|
244
|
+
constructor(game, angle, radius) {
|
|
245
|
+
super(game);
|
|
246
|
+
this.angle = angle;
|
|
247
|
+
this.radius = radius;
|
|
248
|
+
this.z = 0;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
update(dt) {
|
|
252
|
+
this.angle += dt;
|
|
253
|
+
this.x = Math.cos(this.angle) * this.radius;
|
|
254
|
+
this.z = Math.sin(this.angle) * this.radius;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### Multiple Layers
|
|
260
|
+
|
|
261
|
+
Use multiple Scene3D instances for layered effects:
|
|
262
|
+
|
|
263
|
+
```js
|
|
264
|
+
// Background layer (far away, slow parallax)
|
|
265
|
+
this.bgScene = new Scene3D(this, {
|
|
266
|
+
x: cx, y: cy,
|
|
267
|
+
camera: this.camera,
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
// Main layer
|
|
271
|
+
this.mainScene = new Scene3D(this, {
|
|
272
|
+
x: cx, y: cy,
|
|
273
|
+
camera: this.camera,
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
// Foreground layer (close, fast parallax)
|
|
277
|
+
this.fgScene = new Scene3D(this, {
|
|
278
|
+
x: cx, y: cy,
|
|
279
|
+
camera: this.camera,
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
// Add to pipeline in order
|
|
283
|
+
this.pipeline.add(this.bgScene);
|
|
284
|
+
this.pipeline.add(this.mainScene);
|
|
285
|
+
this.pipeline.add(this.fgScene);
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
## With ParticleSystem
|
|
291
|
+
|
|
292
|
+
Scene3D and ParticleSystem both use Camera3D independently. Add them to the same pipeline:
|
|
293
|
+
|
|
294
|
+
```js
|
|
295
|
+
class EffectsDemo extends Game {
|
|
296
|
+
init() {
|
|
297
|
+
super.init();
|
|
298
|
+
|
|
299
|
+
this.camera = new Camera3D({ rotationX: 0.3 });
|
|
300
|
+
this.camera.enableMouseControl(this.canvas);
|
|
301
|
+
|
|
302
|
+
// 3D scene for objects
|
|
303
|
+
this.scene3d = new Scene3D(this, {
|
|
304
|
+
x: this.width / 2,
|
|
305
|
+
y: this.height / 2,
|
|
306
|
+
camera: this.camera,
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
// Particle system with same camera
|
|
310
|
+
this.particles = new ParticleSystem(this, {
|
|
311
|
+
camera: this.camera,
|
|
312
|
+
depthSort: true,
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
// Both in pipeline
|
|
316
|
+
this.pipeline.add(this.scene3d);
|
|
317
|
+
this.pipeline.add(this.particles);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## How It Works
|
|
325
|
+
|
|
326
|
+
Scene3D overrides the Scene's `draw()` method to:
|
|
327
|
+
|
|
328
|
+
1. **Build render list** - Collect visible children with their 3D positions
|
|
329
|
+
2. **Project through camera** - Convert 3D (x, y, z) to 2D screen coordinates
|
|
330
|
+
3. **Cull behind camera** - Skip objects behind the camera plane
|
|
331
|
+
4. **Sort by depth** - Order back-to-front (if enabled)
|
|
332
|
+
5. **Render with scaling** - Draw each child at projected position with perspective scale
|
|
333
|
+
|
|
334
|
+
```
|
|
335
|
+
Child Object (x, y, z)
|
|
336
|
+
│
|
|
337
|
+
â–¼
|
|
338
|
+
Camera3D.project()
|
|
339
|
+
│
|
|
340
|
+
â–¼
|
|
341
|
+
Screen Position (x, y, scale)
|
|
342
|
+
│
|
|
343
|
+
â–¼
|
|
344
|
+
Painter.translateTo() + scale()
|
|
345
|
+
│
|
|
346
|
+
â–¼
|
|
347
|
+
child.draw()
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
---
|
|
351
|
+
|
|
352
|
+
## Differences from Scene
|
|
353
|
+
|
|
354
|
+
| Feature | Scene | Scene3D |
|
|
355
|
+
|---------|-------|---------|
|
|
356
|
+
| Coordinate system | 2D (x, y) | 3D (x, y, z) |
|
|
357
|
+
| Projection | None | Camera3D |
|
|
358
|
+
| Depth sorting | By zIndex | By projected z |
|
|
359
|
+
| Perspective scaling | No | Yes (optional) |
|
|
360
|
+
| Camera required | No | Yes |
|
|
361
|
+
|
|
362
|
+
---
|
|
363
|
+
|
|
364
|
+
## API Reference
|
|
365
|
+
|
|
366
|
+
### Properties
|
|
367
|
+
|
|
368
|
+
| Property | Type | Description |
|
|
369
|
+
|----------|------|-------------|
|
|
370
|
+
| `camera` | `Camera3D` | Camera used for projection |
|
|
371
|
+
| `depthSort` | `boolean` | Whether to sort by depth |
|
|
372
|
+
| `scaleByDepth` | `boolean` | Whether to scale by perspective |
|
|
373
|
+
| `children` | `Array` | Child GameObjects (inherited) |
|
|
374
|
+
|
|
375
|
+
### Methods
|
|
376
|
+
|
|
377
|
+
Inherits all methods from Scene:
|
|
378
|
+
|
|
379
|
+
| Method | Description |
|
|
380
|
+
|--------|-------------|
|
|
381
|
+
| `add(child)` | Add a GameObject |
|
|
382
|
+
| `remove(child)` | Remove a GameObject |
|
|
383
|
+
| `clear()` | Remove all children |
|
|
384
|
+
|
|
385
|
+
---
|
|
386
|
+
|
|
387
|
+
## Related
|
|
388
|
+
|
|
389
|
+
- [Camera3D](./camera3d.md) - Camera projection and controls
|
|
390
|
+
- [Game Module](../game/README.md) - Scene base class
|
|
391
|
+
|
|
392
|
+
## See Also
|
|
393
|
+
|
|
394
|
+
- [Particle Module](../particle/README.md) - 3D particle effects
|
|
395
|
+
- [Shapes Module](../shapes/README.md) - Shape primitives
|
package/index.html
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="UTF-8" />
|
|
6
|
+
<title>GCanvas Demos</title>
|
|
7
|
+
</head>
|
|
8
|
+
|
|
9
|
+
<body>
|
|
10
|
+
<div id="info">
|
|
11
|
+
<h1>🧪 GCanvas Demo Gallery</h1>
|
|
12
|
+
<p>Explore demos powered by the GCanvas engine:</p>
|
|
13
|
+
<a href="demos/index.html">Go to demos</a>
|
|
14
|
+
</div>
|
|
15
|
+
</body>
|
|
16
|
+
|
|
17
|
+
</html>
|
package/jsdoc.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"tags": {
|
|
3
|
+
"allowUnknownTags": ["category"]
|
|
4
|
+
},
|
|
5
|
+
"source": {
|
|
6
|
+
"include": ["./src"],
|
|
7
|
+
"includePattern": ".js$",
|
|
8
|
+
"excludePattern": "(node_modules/|docs)"
|
|
9
|
+
},
|
|
10
|
+
"plugins": [
|
|
11
|
+
"./node_modules/better-docs/category"
|
|
12
|
+
],
|
|
13
|
+
"opts": {
|
|
14
|
+
"encoding": "utf8",
|
|
15
|
+
"destination": "docs-gen",
|
|
16
|
+
"readme": "readme.md",
|
|
17
|
+
"recurse": true,
|
|
18
|
+
"verbose": true,
|
|
19
|
+
"tutorials": "",
|
|
20
|
+
"template": "./node_modules/better-docs"
|
|
21
|
+
},
|
|
22
|
+
"templates": {
|
|
23
|
+
"cleverLinks": false,
|
|
24
|
+
"monospaceLinks": false,
|
|
25
|
+
"search": true,
|
|
26
|
+
"default": {
|
|
27
|
+
"staticFiles": {
|
|
28
|
+
"include": [""]
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"better-docs": {
|
|
32
|
+
"name": "GCanvas",
|
|
33
|
+
"logo": "images/logo.png",
|
|
34
|
+
"title": "GCanvas",
|
|
35
|
+
"css": "style.css",
|
|
36
|
+
"trackingCode": "",
|
|
37
|
+
"hideGenerator": false,
|
|
38
|
+
"navLinks": [
|
|
39
|
+
{
|
|
40
|
+
"label": "Github",
|
|
41
|
+
"href": "https://github.com/guinetik/gcanvas"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"label": "Tech Demo",
|
|
45
|
+
"href": "https://gcanvas.guinetik.com"
|
|
46
|
+
}
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@guinetik/gcanvas",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Canvas Utilities and 2d Primitives",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"types": "types/index.d.ts",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"dev": "vite",
|
|
10
|
+
"build": "vite build && npm run minify",
|
|
11
|
+
"build:debug": "vite build --mode debug",
|
|
12
|
+
"build:llm": "npx bundle4llm --src=./src --out=./llm-docs --file=gcanvas-4-llm.js -v",
|
|
13
|
+
"build:demo": "node scripts/build-demo.js",
|
|
14
|
+
"clean:logs": "node scripts/clearconsole.js ./src",
|
|
15
|
+
"minify": "terser dist/gcanvas.umd.js -o dist/gcanvas.umd.min.js --compress --mangle && terser dist/gcanvas.es.js -o dist/gcanvas.es.min.js --compress --mangle",
|
|
16
|
+
"preview": "vite preview",
|
|
17
|
+
"docs": "jsdoc -c jsdoc.json --verbose",
|
|
18
|
+
"deploy:demo": "gh-pages --dist public --branch gh-pages",
|
|
19
|
+
"test": "vitest --no-watch",
|
|
20
|
+
"test:watch": "vitest watch",
|
|
21
|
+
"test:coverage": "vitest run --coverage"
|
|
22
|
+
},
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "git+https://github.com/guinetik/gcanvas.git"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"canvas",
|
|
29
|
+
"html5",
|
|
30
|
+
"no-dependencies"
|
|
31
|
+
],
|
|
32
|
+
"author": "guinetik",
|
|
33
|
+
"license": "ISC",
|
|
34
|
+
"exports": {
|
|
35
|
+
".": {
|
|
36
|
+
"import": "./dist/gcanvas.es.js",
|
|
37
|
+
"require": "./dist/gcanvas.umd.js"
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"bugs": {
|
|
41
|
+
"url": "https://github.com/guinetik/gcanvas/issues"
|
|
42
|
+
},
|
|
43
|
+
"homepage": "https://github.com/guinetik/gcanvas#readme",
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@testing-library/jest-dom": "^6.6.3",
|
|
46
|
+
"gh-pages": "^6.3.0",
|
|
47
|
+
"jsdom": "^26.1.0",
|
|
48
|
+
"terser": "^5.39.0",
|
|
49
|
+
"vite": "^6.2.5",
|
|
50
|
+
"vitest": "^3.1.1"
|
|
51
|
+
},
|
|
52
|
+
"optionalDependencies": {
|
|
53
|
+
"@rollup/rollup-linux-x64-gnu": "^4.53.3"
|
|
54
|
+
}
|
|
55
|
+
}
|