@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,400 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="UTF-8" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<title>Transform API Demo</title>
|
|
8
|
+
<link rel="stylesheet" href="demos.css" />
|
|
9
|
+
<script src="./js/info-toggle.js"></script>
|
|
10
|
+
<style>
|
|
11
|
+
#debug-toggle {
|
|
12
|
+
position: absolute;
|
|
13
|
+
bottom: 20px;
|
|
14
|
+
left: 20px;
|
|
15
|
+
z-index: 100;
|
|
16
|
+
padding: 10px 20px;
|
|
17
|
+
font-family: monospace;
|
|
18
|
+
font-size: 14px;
|
|
19
|
+
background: #333;
|
|
20
|
+
color: #ff00ff;
|
|
21
|
+
border: 2px solid #ff00ff;
|
|
22
|
+
cursor: pointer;
|
|
23
|
+
transition: all 0.2s ease;
|
|
24
|
+
}
|
|
25
|
+
#debug-toggle:hover {
|
|
26
|
+
background: #ff00ff;
|
|
27
|
+
color: #000;
|
|
28
|
+
}
|
|
29
|
+
#debug-toggle.active {
|
|
30
|
+
background: #ff00ff;
|
|
31
|
+
color: #000;
|
|
32
|
+
}
|
|
33
|
+
</style>
|
|
34
|
+
</head>
|
|
35
|
+
|
|
36
|
+
<body>
|
|
37
|
+
<div id="info" class="light">
|
|
38
|
+
<strong>Transform API Demo</strong> — The <code>Transform</code> API provides a consistent, chainable interface for modifying shape properties.
|
|
39
|
+
Use <code>shape.transform.x(100).y(200).rotation(45).scale(0.8)</code> for fluent chaining,
|
|
40
|
+
<code>shape.transform.set({ x: 100, rotation: 45 })</code> for batch updates, or
|
|
41
|
+
<code>shape.transform.translateBy(10, 20)</code> for relative transforms.
|
|
42
|
+
Click to randomize colors.
|
|
43
|
+
</div>
|
|
44
|
+
<button id="debug-toggle">Toggle Debug</button>
|
|
45
|
+
<canvas id="game"></canvas>
|
|
46
|
+
|
|
47
|
+
<script type="module">
|
|
48
|
+
import {
|
|
49
|
+
Game,
|
|
50
|
+
Scene,
|
|
51
|
+
GameObject,
|
|
52
|
+
FPSCounter,
|
|
53
|
+
Rectangle,
|
|
54
|
+
Circle,
|
|
55
|
+
Star,
|
|
56
|
+
Triangle,
|
|
57
|
+
TextShape,
|
|
58
|
+
Group,
|
|
59
|
+
Transform,
|
|
60
|
+
Painter,
|
|
61
|
+
Easing
|
|
62
|
+
} from "../src/index";
|
|
63
|
+
|
|
64
|
+
// Track all shapes for debug toggle
|
|
65
|
+
const allShapes = [];
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* TransformDemo Game
|
|
69
|
+
* Showcases the new Transform API with animated shapes
|
|
70
|
+
*/
|
|
71
|
+
class TransformDemoGame extends Game {
|
|
72
|
+
constructor(canvas) {
|
|
73
|
+
super(canvas);
|
|
74
|
+
this.enableFluidSize();
|
|
75
|
+
this.backgroundColor = "black";
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
onResize() {
|
|
79
|
+
if (this.scene) {
|
|
80
|
+
this.scene.width = this.width - 20;
|
|
81
|
+
this.scene.height = this.height - 20;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
init() {
|
|
86
|
+
super.init();
|
|
87
|
+
// Main scene
|
|
88
|
+
this.scene = new Scene(this, {
|
|
89
|
+
width: this.width - 20,
|
|
90
|
+
height: this.height - 20,
|
|
91
|
+
debug: false,
|
|
92
|
+
anchor: "center"
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
this.pipeline.add(this.scene);
|
|
96
|
+
|
|
97
|
+
// Add demos
|
|
98
|
+
this.scene.add(new FluentAPIDemo(this));
|
|
99
|
+
this.scene.add(new GroupTransformDemo(this));
|
|
100
|
+
this.scene.add(new BatchUpdateDemo(this));
|
|
101
|
+
this.scene.add(new RelativeTransformDemo(this));
|
|
102
|
+
|
|
103
|
+
// FPS counter
|
|
104
|
+
this.pipeline.add(new FPSCounter(this, { anchor: "bottom-right" }));
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Demo 1: Fluent API Chaining
|
|
110
|
+
* Shows basic chained transform calls
|
|
111
|
+
*/
|
|
112
|
+
class FluentAPIDemo extends GameObject {
|
|
113
|
+
constructor(game) {
|
|
114
|
+
super(game);
|
|
115
|
+
|
|
116
|
+
// Create a rectangle using the new Transform API
|
|
117
|
+
this.rect = new Rectangle({
|
|
118
|
+
width: 80,
|
|
119
|
+
height: 60,
|
|
120
|
+
color: "#e94560",
|
|
121
|
+
stroke: "#fff",
|
|
122
|
+
lineWidth: 2,
|
|
123
|
+
debug: false,
|
|
124
|
+
debugColor: "#ff00ff"
|
|
125
|
+
});
|
|
126
|
+
allShapes.push(this.rect);
|
|
127
|
+
|
|
128
|
+
// Use fluent API to set initial position
|
|
129
|
+
this.rect.transform
|
|
130
|
+
.x(-200)
|
|
131
|
+
.y(-120);
|
|
132
|
+
|
|
133
|
+
// Label
|
|
134
|
+
this.label = new TextShape("Fluent API", {
|
|
135
|
+
x: -200,
|
|
136
|
+
y: -170,
|
|
137
|
+
font: "bold 14px monospace",
|
|
138
|
+
color: "#fff",
|
|
139
|
+
align: "center"
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
this.elapsed = 0;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
update(dt) {
|
|
146
|
+
super.update(dt);
|
|
147
|
+
this.elapsed += dt;
|
|
148
|
+
|
|
149
|
+
// Animate using the transform API
|
|
150
|
+
this.rect.transform
|
|
151
|
+
.rotation(this.elapsed * 45)
|
|
152
|
+
.scaleX(0.8 + Math.sin(this.elapsed * 2) * 0.3)
|
|
153
|
+
.scaleY(0.8 + Math.cos(this.elapsed * 2) * 0.3);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
draw() {
|
|
157
|
+
super.draw();
|
|
158
|
+
this.rect.render();
|
|
159
|
+
this.label.render();
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Demo 2: Group Transform Operations
|
|
165
|
+
* Shows group-wide transform operations
|
|
166
|
+
*/
|
|
167
|
+
class GroupTransformDemo extends GameObject {
|
|
168
|
+
constructor(game) {
|
|
169
|
+
super(game);
|
|
170
|
+
|
|
171
|
+
// Create a group with multiple shapes
|
|
172
|
+
this.group = new Group({ debug: false, debugColor: "#ff00ff" });
|
|
173
|
+
allShapes.push(this.group);
|
|
174
|
+
|
|
175
|
+
// Add shapes to group using transform API
|
|
176
|
+
for (let i = 0; i < 3; i++) {
|
|
177
|
+
const circle = new Circle(15 + i * 5, {
|
|
178
|
+
color: Painter.colors.randomColorHSL(),
|
|
179
|
+
stroke: "#fff",
|
|
180
|
+
lineWidth: 1,
|
|
181
|
+
debug: false,
|
|
182
|
+
debugColor: "#ff00ff"
|
|
183
|
+
});
|
|
184
|
+
allShapes.push(circle);
|
|
185
|
+
// Position using transform
|
|
186
|
+
circle.transform.position(i * 40 - 40, 0);
|
|
187
|
+
this.group.add(circle);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Position the group
|
|
191
|
+
this.group.transform.position(0, -120);
|
|
192
|
+
|
|
193
|
+
// Label
|
|
194
|
+
this.label = new TextShape("Group Transforms", {
|
|
195
|
+
x: 0,
|
|
196
|
+
y: -170,
|
|
197
|
+
font: "bold 14px monospace",
|
|
198
|
+
color: "#fff",
|
|
199
|
+
align: "center"
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
this.elapsed = 0;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
update(dt) {
|
|
206
|
+
super.update(dt);
|
|
207
|
+
this.elapsed += dt;
|
|
208
|
+
|
|
209
|
+
// Animate group transform
|
|
210
|
+
this.group.transform
|
|
211
|
+
.rotation(this.elapsed * 30)
|
|
212
|
+
.scale(0.9 + Math.sin(this.elapsed * 1.5) * 0.2);
|
|
213
|
+
|
|
214
|
+
// Animate individual children using forEachTransform
|
|
215
|
+
this.group.forEachTransform((t, child, i) => {
|
|
216
|
+
// Each child rotates at different speed
|
|
217
|
+
t.rotation(-this.elapsed * (60 + i * 30));
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
draw() {
|
|
222
|
+
super.draw();
|
|
223
|
+
this.group.render();
|
|
224
|
+
this.label.render();
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Demo 3: Batch Updates
|
|
230
|
+
* Shows using set() for multiple properties at once
|
|
231
|
+
*/
|
|
232
|
+
class BatchUpdateDemo extends GameObject {
|
|
233
|
+
constructor(game) {
|
|
234
|
+
super(game);
|
|
235
|
+
|
|
236
|
+
this.star = new Star(30, 5, 0.5, {
|
|
237
|
+
color: "#ffc107",
|
|
238
|
+
stroke: "#fff",
|
|
239
|
+
lineWidth: 2,
|
|
240
|
+
debug: false,
|
|
241
|
+
debugColor: "#ff00ff"
|
|
242
|
+
});
|
|
243
|
+
allShapes.push(this.star);
|
|
244
|
+
|
|
245
|
+
// Use batch set for initial state
|
|
246
|
+
this.star.transform.set({
|
|
247
|
+
x: 200,
|
|
248
|
+
y: -120,
|
|
249
|
+
rotation: 0,
|
|
250
|
+
scaleX: 1,
|
|
251
|
+
scaleY: 1
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
// Label
|
|
255
|
+
this.label = new TextShape("Batch set()", {
|
|
256
|
+
x: 200,
|
|
257
|
+
y: -170,
|
|
258
|
+
font: "bold 14px monospace",
|
|
259
|
+
color: "#fff",
|
|
260
|
+
align: "center"
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
this.elapsed = 0;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
update(dt) {
|
|
267
|
+
super.update(dt);
|
|
268
|
+
this.elapsed += dt;
|
|
269
|
+
|
|
270
|
+
// Use batch update for animation
|
|
271
|
+
const pulse = Math.sin(this.elapsed * 3);
|
|
272
|
+
const wobble = Math.sin(this.elapsed * 5) * 5;
|
|
273
|
+
|
|
274
|
+
this.star.transform.set({
|
|
275
|
+
rotation: this.elapsed * 60,
|
|
276
|
+
scaleX: 1 + pulse * 0.3,
|
|
277
|
+
scaleY: 1 - pulse * 0.3
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
// Also translate using relative method
|
|
281
|
+
this.star.transform.x(200 + wobble);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
draw() {
|
|
285
|
+
super.draw();
|
|
286
|
+
this.star.render();
|
|
287
|
+
this.label.render();
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Demo 4: Animated Transforms
|
|
293
|
+
* Shows position, rotation, and scale animations
|
|
294
|
+
*/
|
|
295
|
+
class RelativeTransformDemo extends GameObject {
|
|
296
|
+
constructor(game) {
|
|
297
|
+
super(game);
|
|
298
|
+
|
|
299
|
+
// Create shapes for demonstrating animated transforms
|
|
300
|
+
this.shapes = [];
|
|
301
|
+
const positions = [
|
|
302
|
+
{ x: -200, y: 80 },
|
|
303
|
+
{ x: 0, y: 80 },
|
|
304
|
+
{ x: 200, y: 80 }
|
|
305
|
+
];
|
|
306
|
+
|
|
307
|
+
const types = [
|
|
308
|
+
{ name: "position", shape: new Rectangle({ width: 50, height: 50, color: "#00d9ff", stroke: "#fff", lineWidth: 2, debug: false, debugColor: "#ff00ff" }) },
|
|
309
|
+
{ name: "rotation", shape: new Triangle(40, { color: "#ff6b6b", stroke: "#fff", lineWidth: 2, debug: false, debugColor: "#ff00ff" }) },
|
|
310
|
+
{ name: "scale", shape: new Circle(25, { color: "#7bed9f", stroke: "#fff", lineWidth: 2, debug: false, debugColor: "#ff00ff" }) }
|
|
311
|
+
];
|
|
312
|
+
|
|
313
|
+
types.forEach((type, i) => {
|
|
314
|
+
allShapes.push(type.shape);
|
|
315
|
+
type.shape.transform.position(positions[i].x, positions[i].y);
|
|
316
|
+
type.label = new TextShape(type.name + "()", {
|
|
317
|
+
x: positions[i].x,
|
|
318
|
+
y: 30,
|
|
319
|
+
font: "bold 14px monospace",
|
|
320
|
+
color: "#fff",
|
|
321
|
+
align: "center"
|
|
322
|
+
});
|
|
323
|
+
type.baseX = positions[i].x;
|
|
324
|
+
type.baseY = positions[i].y;
|
|
325
|
+
this.shapes.push(type);
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
this.elapsed = 0;
|
|
329
|
+
this.lastUpdate = 0;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
update(dt) {
|
|
333
|
+
super.update(dt);
|
|
334
|
+
this.elapsed += dt;
|
|
335
|
+
|
|
336
|
+
// position demo - oscillate position
|
|
337
|
+
const tx = Math.sin(this.elapsed * 2) * 30;
|
|
338
|
+
const ty = Math.cos(this.elapsed * 3) * 15;
|
|
339
|
+
this.shapes[0].shape.transform.position(this.shapes[0].baseX + tx, this.shapes[0].baseY + ty);
|
|
340
|
+
|
|
341
|
+
// rotation demo - continuous rotation
|
|
342
|
+
this.shapes[1].shape.transform.rotation(this.elapsed * 90);
|
|
343
|
+
|
|
344
|
+
// scale demo - pulsing scale
|
|
345
|
+
const scale = 0.7 + Math.abs(Math.sin(this.elapsed * 2)) * 0.6;
|
|
346
|
+
this.shapes[2].shape.transform.scale(scale);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
draw() {
|
|
350
|
+
super.draw();
|
|
351
|
+
this.shapes.forEach(s => {
|
|
352
|
+
s.shape.render();
|
|
353
|
+
s.label.render();
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// Start the game
|
|
359
|
+
window.addEventListener("load", () => {
|
|
360
|
+
const canvas = document.getElementById("game");
|
|
361
|
+
const game = new TransformDemoGame(canvas);
|
|
362
|
+
game.start();
|
|
363
|
+
|
|
364
|
+
// Debug toggle button
|
|
365
|
+
let debugEnabled = false;
|
|
366
|
+
const debugBtn = document.getElementById("debug-toggle");
|
|
367
|
+
|
|
368
|
+
debugBtn.addEventListener("click", () => {
|
|
369
|
+
debugEnabled = !debugEnabled;
|
|
370
|
+
debugBtn.classList.toggle("active", debugEnabled);
|
|
371
|
+
debugBtn.textContent = debugEnabled ? "Debug: ON" : "Toggle Debug";
|
|
372
|
+
|
|
373
|
+
// Toggle debug on all shapes
|
|
374
|
+
allShapes.forEach(shape => {
|
|
375
|
+
shape._debug = debugEnabled;
|
|
376
|
+
});
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
// Randomize colors on click
|
|
380
|
+
canvas.addEventListener("click", () => {
|
|
381
|
+
game.scene.children.forEach(child => {
|
|
382
|
+
if (child.rect) child.rect.color = Painter.colors.randomColorHSL();
|
|
383
|
+
if (child.star) child.star.color = Painter.colors.randomColorHSL();
|
|
384
|
+
if (child.group) {
|
|
385
|
+
child.group.children.forEach(c => {
|
|
386
|
+
c.color = Painter.colors.randomColorHSL();
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
if (child.shapes) {
|
|
390
|
+
child.shapes.forEach(s => {
|
|
391
|
+
s.shape.color = Painter.colors.randomColorHSL();
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
});
|
|
396
|
+
});
|
|
397
|
+
</script>
|
|
398
|
+
</body>
|
|
399
|
+
|
|
400
|
+
</html>
|
package/demos/tween.html
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="UTF-8" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<title>Tween</title>
|
|
8
|
+
<link rel="stylesheet" href="demos.css" />
|
|
9
|
+
<script src="./js/info-toggle.js"></script>
|
|
10
|
+
</head>
|
|
11
|
+
|
|
12
|
+
<body>
|
|
13
|
+
<div id="info">
|
|
14
|
+
<strong>Tween Demo</strong> - A box animated over time. The library features two motion-related classes:
|
|
15
|
+
<span style="color:#CCC">
|
|
16
|
+
<li><code>Tween</code> - Contains motion primitives, lerps and easing functions.</li>
|
|
17
|
+
<li><code>Tweenetik</code> - A shorcut class that leverates Tween to interpolate object properties over time</li>
|
|
18
|
+
<pre>
|
|
19
|
+
Tweenetik.to(
|
|
20
|
+
mySprite, // an object or sprite
|
|
21
|
+
{ scaleX: scale, scaleY: scale}, // the properties & end-values
|
|
22
|
+
2.0, // duration in seconds
|
|
23
|
+
Easing.easeOutBounce, // easing function
|
|
24
|
+
{
|
|
25
|
+
delay: 0.5, // optional 0.5s delay
|
|
26
|
+
onStart: () => console.log("Tween started!"),
|
|
27
|
+
onComplete: () => console.log("Tween done!"),
|
|
28
|
+
onUpdate: () => console.log("Updated frame"),
|
|
29
|
+
}
|
|
30
|
+
);</pre>
|
|
31
|
+
</span>
|
|
32
|
+
</div>
|
|
33
|
+
<canvas id="game"></canvas>
|
|
34
|
+
<script type="module">
|
|
35
|
+
import { MyGame } from './js/tweendemo.js';
|
|
36
|
+
|
|
37
|
+
window.addEventListener("load", () => {
|
|
38
|
+
const canvas = document.getElementById("game");
|
|
39
|
+
const game = new MyGame(canvas);
|
|
40
|
+
game.start();
|
|
41
|
+
});
|
|
42
|
+
</script>
|
|
43
|
+
</body>
|
|
44
|
+
|
|
45
|
+
</html>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="UTF-8" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<title>Opacity</title>
|
|
8
|
+
<link rel="stylesheet" href="demos.css" />
|
|
9
|
+
<script src="./js/info-toggle.js"></script>
|
|
10
|
+
</head>
|
|
11
|
+
|
|
12
|
+
<body>
|
|
13
|
+
<div id="info">
|
|
14
|
+
<strong>Visibility Toggle Demo</strong> - Shows how game objects can be dynamically shown or hidden.
|
|
15
|
+
<span style="color:#CCC">
|
|
16
|
+
<li><code>Transformable</code> — The base class providing the <code>visible</code> property.</li>
|
|
17
|
+
<li><code>Pipeline Integration</code> — The pipeline skips invisible objects during rendering.</li>
|
|
18
|
+
<li><code>Dynamic Toggling</code> — Click the button to toggle visibility of a random square.</li>
|
|
19
|
+
</span>
|
|
20
|
+
</div>
|
|
21
|
+
<canvas id="game"></canvas>
|
|
22
|
+
<script type="module">
|
|
23
|
+
import { MyGame } from './js/visibility.js';
|
|
24
|
+
|
|
25
|
+
window.addEventListener("load", () => {
|
|
26
|
+
const canvas = document.getElementById("game");
|
|
27
|
+
const game = new MyGame(canvas);
|
|
28
|
+
game.start();
|
|
29
|
+
});
|
|
30
|
+
</script>
|
|
31
|
+
</body>
|
|
32
|
+
|
|
33
|
+
</html>
|
package/disk_example.png
ADDED
|
Binary file
|
package/docs/README.md
ADDED
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
# GCanvas Documentation
|
|
2
|
+
|
|
3
|
+
> A minimalist 2D canvas rendering library built for learning, expression, and creative coding.
|
|
4
|
+
|
|
5
|
+
GCanvas is a modular 2D rendering and game framework built on top of the HTML5 Canvas API. Inspired by the simplicity of p5.js and the composability of game engines.
|
|
6
|
+
|
|
7
|
+
## Quick Navigation
|
|
8
|
+
|
|
9
|
+
| Section | Description |
|
|
10
|
+
|---------|-------------|
|
|
11
|
+
| [Getting Started](./getting-started/installation.md) | Installation and first steps |
|
|
12
|
+
| [Concepts](./concepts/architecture-overview.md) | Core architecture and design |
|
|
13
|
+
| [Shapes Module](./modules/shapes/README.md) | Drawing primitives and hierarchy |
|
|
14
|
+
| [Game Module](./modules/game/README.md) | Game loop and GameObjects |
|
|
15
|
+
| [Particle Module](./modules/particle/README.md) | High-performance particle systems |
|
|
16
|
+
| [Util Module](./modules/util/README.md) | Camera3D, Scene3D, layouts |
|
|
17
|
+
| [Collision Module](./modules/collision/README.md) | Collision detection and management |
|
|
18
|
+
| [State Module](./modules/state/README.md) | State machines for entities and games |
|
|
19
|
+
| [Painter Module](./modules/painter/README.md) | Low-level canvas API |
|
|
20
|
+
|
|
21
|
+
## Architecture Overview
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
25
|
+
│ GCanvas │
|
|
26
|
+
├─────────────────────────────────────────────────────────────┤
|
|
27
|
+
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
|
|
28
|
+
│ │ Shapes │ │ Game │ │ Painter │ │
|
|
29
|
+
│ │ (Drawing) │ │ (Lifecycle) │ │ (Canvas API) │ │
|
|
30
|
+
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
|
|
31
|
+
├─────────────────────────────────────────────────────────────┤
|
|
32
|
+
│ ┌───────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
|
|
33
|
+
│ │ Collision │ │ State │ │ Motion │ │ IO │ ... │
|
|
34
|
+
│ │ (Physics) │ │ (FSM) │ │ (Anim) │ │ (Input) │ │
|
|
35
|
+
│ └───────────┘ └─────────┘ └─────────┘ └─────────┘ │
|
|
36
|
+
└─────────────────────────────────────────────────────────────┘
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
GCanvas is organized into **12 core modules**:
|
|
40
|
+
|
|
41
|
+
| Module | Purpose |
|
|
42
|
+
|--------|---------|
|
|
43
|
+
| **[shapes](./modules/shapes/README.md)** | 40+ drawable primitives and shape classes |
|
|
44
|
+
| **[game](./modules/game/README.md)** | Core game loop, Pipeline, GameObjects, Scenes |
|
|
45
|
+
| **[particle](./modules/particle/README.md)** | High-performance particle systems with pooling |
|
|
46
|
+
| **[collision](./modules/collision/README.md)** | Collision detection algorithms and group management |
|
|
47
|
+
| **[state](./modules/state/README.md)** | State machines with lifecycle callbacks |
|
|
48
|
+
| **[painter](./modules/painter/README.md)** | Low-level canvas drawing API |
|
|
49
|
+
| **[util](./modules/util/README.md)** | Camera3D, Scene3D, Layout, Position utilities |
|
|
50
|
+
| **motion** | Animation with Tweenetik and Motion patterns |
|
|
51
|
+
| **io** | Input handling (Mouse, Keyboard, Touch, Events) |
|
|
52
|
+
| **math** | Random, Noise, Fractals, Patterns |
|
|
53
|
+
| **mixins** | Draggable, Anchor behaviors |
|
|
54
|
+
| **logger** | Debug logging system |
|
|
55
|
+
|
|
56
|
+
## Two-Layer Architecture
|
|
57
|
+
|
|
58
|
+
GCanvas provides two complementary ways to work:
|
|
59
|
+
|
|
60
|
+
### Shape Layer (Declarative Drawing)
|
|
61
|
+
|
|
62
|
+
For static visuals and simple graphics. Use shapes directly without a game loop:
|
|
63
|
+
|
|
64
|
+
```js
|
|
65
|
+
import { Circle, Rectangle, Painter } from 'gcanvas';
|
|
66
|
+
|
|
67
|
+
Painter.init(ctx);
|
|
68
|
+
|
|
69
|
+
const circle = new Circle(100, { x: 200, y: 150, color: 'red' });
|
|
70
|
+
circle.draw();
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Game Layer (Interactive Entities)
|
|
74
|
+
|
|
75
|
+
For games, simulations, and interactive applications:
|
|
76
|
+
|
|
77
|
+
```js
|
|
78
|
+
import { Game, Scene, GameObject, Circle } from 'gcanvas';
|
|
79
|
+
|
|
80
|
+
class Player extends GameObject {
|
|
81
|
+
constructor(game) {
|
|
82
|
+
super(game);
|
|
83
|
+
this.shape = new Circle(40, { color: 'blue' });
|
|
84
|
+
this.enableInteractivity(this.shape);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
update(dt) {
|
|
88
|
+
// Game logic here
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
render() {
|
|
92
|
+
this.shape.draw();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
[Learn more about the Two-Layer Architecture](./concepts/two-layer-architecture.md)
|
|
98
|
+
|
|
99
|
+
## The Rendering Pipeline
|
|
100
|
+
|
|
101
|
+
Every visual element inherits from a chain of base classes:
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
Euclidian ─── Position (x, y) and size (width, height)
|
|
105
|
+
│
|
|
106
|
+
Geometry2d ─── Bounding boxes and constraints
|
|
107
|
+
│
|
|
108
|
+
Traceable ─── Debug visualization
|
|
109
|
+
│
|
|
110
|
+
Renderable ─── Visibility, opacity, shadows
|
|
111
|
+
│
|
|
112
|
+
Transformable ─── Rotation and scaling
|
|
113
|
+
│
|
|
114
|
+
Shape ─── Fill color, stroke, line styling
|
|
115
|
+
│
|
|
116
|
+
[Circle, Rectangle, Star, Cube, ...] ─── Concrete implementations
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
[Learn more about the Rendering Pipeline](./concepts/rendering-pipeline.md)
|
|
120
|
+
|
|
121
|
+
## Quick Start
|
|
122
|
+
|
|
123
|
+
### Installation
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
git clone https://github.com/guinetik/gcanvas.git
|
|
127
|
+
cd gcanvas
|
|
128
|
+
npm install
|
|
129
|
+
npm run dev
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Hello World
|
|
133
|
+
|
|
134
|
+
```html
|
|
135
|
+
<canvas id="game"></canvas>
|
|
136
|
+
<script type="module">
|
|
137
|
+
import { Game, Scene, Rectangle, TextShape, Group } from 'gcanvas';
|
|
138
|
+
|
|
139
|
+
class HelloWorld extends Game {
|
|
140
|
+
init() {
|
|
141
|
+
this.enableFluidSize();
|
|
142
|
+
this.backgroundColor = 'black';
|
|
143
|
+
|
|
144
|
+
const box = new Rectangle(200, 80, {
|
|
145
|
+
color: '#111',
|
|
146
|
+
stroke: '#0f0',
|
|
147
|
+
lineWidth: 2
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
const label = new TextShape('Hello World!', {
|
|
151
|
+
font: '18px monospace',
|
|
152
|
+
color: '#0f0',
|
|
153
|
+
align: 'center',
|
|
154
|
+
baseline: 'middle'
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
const group = new Group({ x: this.width / 2, y: this.height / 2 });
|
|
158
|
+
group.add(box);
|
|
159
|
+
group.add(label);
|
|
160
|
+
|
|
161
|
+
const scene = new Scene(this);
|
|
162
|
+
scene.add(group);
|
|
163
|
+
this.pipeline.add(scene);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const game = new HelloWorld(document.getElementById('game'));
|
|
168
|
+
game.start();
|
|
169
|
+
</script>
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
[Full getting started guide](./getting-started/hello-world.md)
|
|
173
|
+
|
|
174
|
+
## Features
|
|
175
|
+
|
|
176
|
+
- **40+ Shape Primitives** - Circle, Rectangle, Star, Polygon, Heart, and more
|
|
177
|
+
- **2.5D Shapes** - Cube, Cylinder, Sphere, Cone, Prism with pseudo-3D rendering
|
|
178
|
+
- **Groups** - Composite shapes with collective transforms
|
|
179
|
+
- **Transforms** - Rotation, scale, opacity, constraints
|
|
180
|
+
- **Painter API** - Direct canvas control when needed
|
|
181
|
+
- **GameObjects** - Interactive entities with lifecycle methods
|
|
182
|
+
- **Scenes & Scene3D** - Hierarchical organization with optional 3D projection
|
|
183
|
+
- **Camera3D** - Pseudo-3D projection with mouse-controlled rotation
|
|
184
|
+
- **Particle Systems** - High-performance particles with object pooling and composable updaters
|
|
185
|
+
- **Collision Detection** - AABB, circles, lines, sweep tests, and group management
|
|
186
|
+
- **State Machines** - FSM with enter/update/exit lifecycle, timed transitions
|
|
187
|
+
- **UI Components** - Button, ToggleButton, Cursor, Layout managers
|
|
188
|
+
- **Motion System** - Stateless animation patterns (orbit, bounce, spiral...)
|
|
189
|
+
- **Tweenetik** - Property-based tweening with easing
|
|
190
|
+
- **Event System** - Mouse, touch, keyboard with unified input
|
|
191
|
+
- **Zero Dependencies** - Pure JavaScript, works everywhere
|
|
192
|
+
|
|
193
|
+
## Demo
|
|
194
|
+
|
|
195
|
+
See GCanvas in action: [gcanvas.guinetik.com](https://gcanvas.guinetik.com)
|
|
196
|
+
|
|
197
|
+
Or run locally:
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
npm run dev
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## API Documentation
|
|
204
|
+
|
|
205
|
+
- [Shapes Module](./modules/shapes/README.md) - All drawable primitives
|
|
206
|
+
- [Game Module](./modules/game/README.md) - Game loop and objects
|
|
207
|
+
- [Particle Module](./modules/particle/README.md) - Particle systems
|
|
208
|
+
- [Util Module](./modules/util/README.md) - Camera3D, Scene3D, layouts
|
|
209
|
+
- [Collision Module](./modules/collision/README.md) - Collision detection
|
|
210
|
+
- [State Module](./modules/state/README.md) - State machines
|
|
211
|
+
- [Painter Module](./modules/painter/README.md) - Canvas abstraction
|
|
212
|
+
|
|
213
|
+
## Learn More
|
|
214
|
+
|
|
215
|
+
- [Architecture Overview](./concepts/architecture-overview.md)
|
|
216
|
+
- [Rendering Pipeline](./concepts/rendering-pipeline.md)
|
|
217
|
+
- [Game Lifecycle](./concepts/lifecycle.md)
|
|
218
|
+
- [Installation Guide](./getting-started/installation.md)
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
**Source:** [github.com/guinetik/gcanvas](https://github.com/guinetik/gcanvas)
|