@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,692 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Game,
|
|
3
|
+
Scene,
|
|
4
|
+
FPSCounter,
|
|
5
|
+
Button,
|
|
6
|
+
HorizontalLayout,
|
|
7
|
+
VerticalLayout,
|
|
8
|
+
Painter,
|
|
9
|
+
ToggleButton,
|
|
10
|
+
Cursor,
|
|
11
|
+
TextShape,
|
|
12
|
+
Circle,
|
|
13
|
+
Rectangle,
|
|
14
|
+
BezierShape,
|
|
15
|
+
ShapeGOFactory,
|
|
16
|
+
Position,
|
|
17
|
+
} from "../../src/index";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Main Game class for the Bezier Demo
|
|
21
|
+
*/
|
|
22
|
+
class BezierDemoGame extends Game {
|
|
23
|
+
constructor(canvas) {
|
|
24
|
+
super(canvas);
|
|
25
|
+
this.enableFluidSize();
|
|
26
|
+
this.backgroundColor = "black";
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Check if we're on a touch device
|
|
31
|
+
*/
|
|
32
|
+
isTouchDevice() {
|
|
33
|
+
return (
|
|
34
|
+
"ontouchstart" in window ||
|
|
35
|
+
navigator.maxTouchPoints > 0 ||
|
|
36
|
+
navigator.msMaxTouchPoints > 0
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Check if screen is narrow (mobile width)
|
|
42
|
+
*/
|
|
43
|
+
isMobile() {
|
|
44
|
+
return this.width < 600;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Get responsive configuration based on screen size
|
|
49
|
+
*/
|
|
50
|
+
getResponsiveConfig() {
|
|
51
|
+
const isMobile = this.isMobile();
|
|
52
|
+
return {
|
|
53
|
+
// Use shorter labels on mobile
|
|
54
|
+
addLabel: isMobile ? "➕ Add" : "➕ Add Points",
|
|
55
|
+
editLabel: isMobile ? "✋ Edit" : "✋ Edit Points",
|
|
56
|
+
cutLabel: isMobile ? "✂️ Cut" : "✂️ Cut Shape",
|
|
57
|
+
clearLabel: isMobile ? "🧼" : "🧼 Clear",
|
|
58
|
+
// Narrower buttons on mobile
|
|
59
|
+
buttonWidth: isMobile ? 70 : 125,
|
|
60
|
+
clearWidth: isMobile ? 40 : 100,
|
|
61
|
+
// UI layout dimensions
|
|
62
|
+
layoutWidth: isMobile ? 280 : 500,
|
|
63
|
+
layoutHeight: 50,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
init() {
|
|
68
|
+
super.init();
|
|
69
|
+
// Create the scenes
|
|
70
|
+
this.bezierScene = new BezierScene(this, {
|
|
71
|
+
debug: true,
|
|
72
|
+
debugColor: "yellow",
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
const config = this.getResponsiveConfig();
|
|
76
|
+
|
|
77
|
+
this.uiScene = new BezierUIScene(this, this.bezierScene, {
|
|
78
|
+
debug: true,
|
|
79
|
+
debugColor: "magenta",
|
|
80
|
+
width: config.layoutWidth,
|
|
81
|
+
height: config.layoutHeight,
|
|
82
|
+
padding: 10,
|
|
83
|
+
anchor: Position.BOTTOM_CENTER,
|
|
84
|
+
anchorOffsetY: -20,
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// Add them to the pipeline
|
|
88
|
+
this.pipeline.add(this.bezierScene);
|
|
89
|
+
this.pipeline.add(this.uiScene);
|
|
90
|
+
this.uiScene.init();
|
|
91
|
+
|
|
92
|
+
// Show FPS counter
|
|
93
|
+
this.pipeline.add(new FPSCounter(this, { anchor: "bottom-right" }));
|
|
94
|
+
|
|
95
|
+
// Only setup custom cursor on non-touch devices
|
|
96
|
+
if (!this.isTouchDevice()) {
|
|
97
|
+
this.addCursor = new TextShape("➕", {
|
|
98
|
+
font: "24px monospace",
|
|
99
|
+
color: "white",
|
|
100
|
+
});
|
|
101
|
+
this.editCursor = new TextShape("✋", {
|
|
102
|
+
font: "24px monospace",
|
|
103
|
+
color: "white",
|
|
104
|
+
});
|
|
105
|
+
this.cursor = new Cursor(this, this.addCursor, this.addCursor, {
|
|
106
|
+
x: 0,
|
|
107
|
+
y: 0,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
onResize() {
|
|
113
|
+
if (this.uiScene) {
|
|
114
|
+
this.uiScene.onResize();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* The BezierScene:
|
|
121
|
+
* - Allows users to place control points by clicking
|
|
122
|
+
* - Visualizes the Bezier curve as it's being created
|
|
123
|
+
* - Provides UI to finish/clear the curve
|
|
124
|
+
*/
|
|
125
|
+
class BezierScene extends Scene {
|
|
126
|
+
constructor(game, options = {}) {
|
|
127
|
+
super(game, options);
|
|
128
|
+
this.MARGIN = 0;
|
|
129
|
+
this.interactive = true;
|
|
130
|
+
// Control points the user has placed
|
|
131
|
+
this.points = [];
|
|
132
|
+
// Current bezier path that will be visualized
|
|
133
|
+
this.bezierPath = [];
|
|
134
|
+
// The bezier shape that will be rendered
|
|
135
|
+
this.bezierShape = null;
|
|
136
|
+
// Point being dragged (if any)
|
|
137
|
+
this.draggedPointIndex = -1;
|
|
138
|
+
// Visual elements for control points
|
|
139
|
+
this.controlPointShapes = [];
|
|
140
|
+
// User interface state
|
|
141
|
+
this.mode = "add"; // "add" or "edit"
|
|
142
|
+
// Forward input events to the bezier scene
|
|
143
|
+
this.game.events.on("inputdown", (e) => {
|
|
144
|
+
//console.log("inputdown", e);
|
|
145
|
+
const x = e.x - this.width / 2;
|
|
146
|
+
const y = e.y - this.height / 2;
|
|
147
|
+
this.pointerDown(x, y);
|
|
148
|
+
});
|
|
149
|
+
// Forward input move event to the bezier scene
|
|
150
|
+
this.game.events.on("inputmove", (e) => {
|
|
151
|
+
const x = e.x - this.width / 2;
|
|
152
|
+
const y = e.y - this.height / 2;
|
|
153
|
+
this.pointerMove(x, y);
|
|
154
|
+
});
|
|
155
|
+
// Forward input up event to the bezier scene
|
|
156
|
+
this.game.events.on("inputup", (e) => {
|
|
157
|
+
this.pointerUp();
|
|
158
|
+
});
|
|
159
|
+
//
|
|
160
|
+
this.userBeziers = [];
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Set the current mode (add points or edit existing points)
|
|
165
|
+
*/
|
|
166
|
+
setMode(mode) {
|
|
167
|
+
this.mode = mode;
|
|
168
|
+
|
|
169
|
+
// Only update cursor on non-touch devices
|
|
170
|
+
if (this.game.cursor) {
|
|
171
|
+
if (mode === "add") {
|
|
172
|
+
this.game.cursor.normalShape = this.game.cursor.pressedShape =
|
|
173
|
+
this.game.addCursor;
|
|
174
|
+
this.game.cursor.offsetX = 1;
|
|
175
|
+
this.game.cursor.offsetY = -6;
|
|
176
|
+
} else {
|
|
177
|
+
this.game.cursor.normalShape = this.game.cursor.pressedShape =
|
|
178
|
+
this.game.editCursor;
|
|
179
|
+
this.game.cursor.offsetX = 3;
|
|
180
|
+
this.game.cursor.offsetY = -3;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Add a control point at the specified position
|
|
187
|
+
*/
|
|
188
|
+
addPoint(x, y) {
|
|
189
|
+
x = x - 50;
|
|
190
|
+
y = y - 50;
|
|
191
|
+
this.points.push({ x, y });
|
|
192
|
+
// Create a visual representation of the control point
|
|
193
|
+
const pointShape = new Circle(6, {
|
|
194
|
+
color: "#00FF00",
|
|
195
|
+
stroke: "#e2FFe2",
|
|
196
|
+
lineWidth: 2,
|
|
197
|
+
});
|
|
198
|
+
const go = ShapeGOFactory.create(this.game, pointShape, { x: x, y: y });
|
|
199
|
+
this.controlPointShapes.push(go);
|
|
200
|
+
this.add(go);
|
|
201
|
+
// Update the bezier path
|
|
202
|
+
this.updateBezierPath();
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Updates the Bezier path based on current points
|
|
207
|
+
* This is where we convert our points array into path commands
|
|
208
|
+
*/
|
|
209
|
+
/**
|
|
210
|
+
* Updates the Bezier path based on current points
|
|
211
|
+
* This is where we convert our points array into path commands
|
|
212
|
+
*/
|
|
213
|
+
updateBezierPath() {
|
|
214
|
+
if (this.points.length < 2) {
|
|
215
|
+
// Need at least 2 points to create a path
|
|
216
|
+
this.bezierPath = [];
|
|
217
|
+
if (this.bezierShape) {
|
|
218
|
+
this.remove(this.bezierShape);
|
|
219
|
+
this.bezierShape = null;
|
|
220
|
+
}
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
// Start with a move command to the first point
|
|
224
|
+
const path = [["M", this.points[0].x, this.points[0].y]];
|
|
225
|
+
// Create appropriate curve segments based on the number of points
|
|
226
|
+
if (this.points.length === 2) {
|
|
227
|
+
// With just 2 points, create a line
|
|
228
|
+
path.push(["L", this.points[1].x, this.points[1].y]);
|
|
229
|
+
} else if (this.points.length === 3) {
|
|
230
|
+
// With 3 points, create a quadratic curve (one control point)
|
|
231
|
+
path.push([
|
|
232
|
+
"Q",
|
|
233
|
+
this.points[1].x,
|
|
234
|
+
this.points[1].y,
|
|
235
|
+
this.points[2].x,
|
|
236
|
+
this.points[2].y,
|
|
237
|
+
]);
|
|
238
|
+
} else {
|
|
239
|
+
// For 4+ points, create cubic Bezier segments
|
|
240
|
+
for (let i = 1; i < this.points.length; i += 3) {
|
|
241
|
+
if (i + 2 < this.points.length) {
|
|
242
|
+
// We have enough points for a cubic curve
|
|
243
|
+
path.push([
|
|
244
|
+
"C",
|
|
245
|
+
this.points[i].x,
|
|
246
|
+
this.points[i].y,
|
|
247
|
+
this.points[i + 1].x,
|
|
248
|
+
this.points[i + 1].y,
|
|
249
|
+
this.points[i + 2].x,
|
|
250
|
+
this.points[i + 2].y,
|
|
251
|
+
]);
|
|
252
|
+
} else if (i + 1 < this.points.length) {
|
|
253
|
+
// Just enough for a quadratic curve
|
|
254
|
+
path.push([
|
|
255
|
+
"Q",
|
|
256
|
+
this.points[i].x,
|
|
257
|
+
this.points[i].y,
|
|
258
|
+
this.points[i + 1].x,
|
|
259
|
+
this.points[i + 1].y,
|
|
260
|
+
]);
|
|
261
|
+
} else {
|
|
262
|
+
// Just add a line to the last point
|
|
263
|
+
path.push(["L", this.points[i].x, this.points[i].y]);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
this.bezierPath = path;
|
|
269
|
+
|
|
270
|
+
// If we already have a shape, update its path
|
|
271
|
+
if (this.bezierShape) {
|
|
272
|
+
this.bezierShape.shape.path = path;
|
|
273
|
+
this.bezierShape.render();
|
|
274
|
+
} else {
|
|
275
|
+
const centerX = 0;
|
|
276
|
+
const centerY = 0;
|
|
277
|
+
// Create the bezier shape
|
|
278
|
+
const bezierShapeObj = new BezierShape(path, {
|
|
279
|
+
color: Painter.colors.randomColorHSL(),
|
|
280
|
+
stroke: "rgba(255, 255, 255, 0.8)",
|
|
281
|
+
lineWidth: 3,
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
// Create a GameObject using the factory
|
|
285
|
+
this.bezierShape = ShapeGOFactory.create(this.game, bezierShapeObj, {
|
|
286
|
+
x: centerX,
|
|
287
|
+
y: centerY,
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
// Add the GameObject to the scene
|
|
291
|
+
this.add(this.bezierShape);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Cut the current bezier shape and store it with jitter animation
|
|
297
|
+
*/
|
|
298
|
+
cutShape() {
|
|
299
|
+
// Only proceed if we have a valid bezier curve
|
|
300
|
+
if (this.points.length >= 2 && this.bezierShape) {
|
|
301
|
+
// Create a deep copy of the current bezier data
|
|
302
|
+
const cutBezier = {
|
|
303
|
+
points: [...this.points.map((p) => ({ ...p }))],
|
|
304
|
+
path: [...this.bezierPath.map((cmd) => [...cmd])],
|
|
305
|
+
shape: this.bezierShape,
|
|
306
|
+
originalPath: [...this.bezierPath.map((cmd) => [...cmd])], // Store original path for animation
|
|
307
|
+
jitterAmount: 5, // Base jitter amount
|
|
308
|
+
jitterSpeed: 1.5 + Math.random() * 0.5, // Random speed variation
|
|
309
|
+
jitterPhase: Math.random() * Math.PI * 2, // Random starting phase
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
cutBezier.jitterAmount = 5 * cutBezier.points.length;
|
|
313
|
+
|
|
314
|
+
// Add to our collection of user beziers
|
|
315
|
+
this.userBeziers.push(cutBezier);
|
|
316
|
+
|
|
317
|
+
// Remove the current bezier shape from control but keep it in the scene
|
|
318
|
+
this.bezierShape = null;
|
|
319
|
+
|
|
320
|
+
// Clear current editing points but keep the shape visible
|
|
321
|
+
this.points = [];
|
|
322
|
+
this.bezierPath = [];
|
|
323
|
+
|
|
324
|
+
// Remove visual control points
|
|
325
|
+
for (const pointShape of this.controlPointShapes) {
|
|
326
|
+
this.remove(pointShape);
|
|
327
|
+
}
|
|
328
|
+
this.controlPointShapes = [];
|
|
329
|
+
this.draggedPointIndex = -1;
|
|
330
|
+
|
|
331
|
+
//console.log(`Cut bezier shape - ${this.userBeziers.length} total shapes`);
|
|
332
|
+
} else {
|
|
333
|
+
//console.log("Need at least 2 points to cut a shape");
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Clear all points and reset the demo
|
|
339
|
+
* Updated to also clear all cut bezier shapes
|
|
340
|
+
*/
|
|
341
|
+
clear() {
|
|
342
|
+
// Remove visual elements
|
|
343
|
+
for (const shape of this.controlPointShapes) {
|
|
344
|
+
this.remove(shape);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// Remove the current bezier shape if exists
|
|
348
|
+
if (this.bezierShape) {
|
|
349
|
+
this.remove(this.bezierShape);
|
|
350
|
+
this.bezierShape = null;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// Additionally remove all cut bezier shapes
|
|
354
|
+
for (const bezier of this.userBeziers) {
|
|
355
|
+
this.remove(bezier.shape);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// Reset all data
|
|
359
|
+
this.points = [];
|
|
360
|
+
this.bezierPath = [];
|
|
361
|
+
this.controlPointShapes = [];
|
|
362
|
+
this.draggedPointIndex = -1;
|
|
363
|
+
this.userBeziers = [];
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Return the bezier path as a string for display/export
|
|
368
|
+
*/
|
|
369
|
+
getPathString() {
|
|
370
|
+
if (!this.bezierPath.length) return "No path defined";
|
|
371
|
+
|
|
372
|
+
return JSON.stringify(this.bezierPath);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Find the index of a control point near the given coordinates
|
|
377
|
+
*/
|
|
378
|
+
findNearbyPoint(x, y, radius = 20) {
|
|
379
|
+
for (let i = 0; i < this.points.length; i++) {
|
|
380
|
+
const point = this.points[i];
|
|
381
|
+
const dx = point.x - x;
|
|
382
|
+
const dy = point.y - y;
|
|
383
|
+
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
384
|
+
|
|
385
|
+
if (distance <= radius) {
|
|
386
|
+
return i;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
return -1;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Check if a point is within the UI area
|
|
394
|
+
*/
|
|
395
|
+
isInUIArea(x, y) {
|
|
396
|
+
// Get screen coordinates (input coords are already screen coords)
|
|
397
|
+
const screenY = y + this.height / 2;
|
|
398
|
+
// UI is at bottom, check if click is in bottom 80px
|
|
399
|
+
return screenY > this.game.height - 80;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Pointer down handler
|
|
404
|
+
*/
|
|
405
|
+
pointerDown(x, y) {
|
|
406
|
+
// Skip if clicking on UI area (buttons)
|
|
407
|
+
if (this.game.canvas.style.cursor === "pointer" || this.isInUIArea(x, y)) {
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
if (this.mode === "add") {
|
|
411
|
+
// In add mode, place a new control point
|
|
412
|
+
this.addPoint(x, y);
|
|
413
|
+
} else {
|
|
414
|
+
// In edit mode, check if we're clicking on an existing point
|
|
415
|
+
const pointIndex = this.findNearbyPoint(x - 50, y - 50);
|
|
416
|
+
if (pointIndex >= 0) {
|
|
417
|
+
this.draggedPointIndex = pointIndex;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Pointer move handler
|
|
424
|
+
*/
|
|
425
|
+
pointerMove(x, y) {
|
|
426
|
+
if (this.draggedPointIndex >= 0) {
|
|
427
|
+
// Update the dragged point position
|
|
428
|
+
this.points[this.draggedPointIndex].x = x - 50;
|
|
429
|
+
this.points[this.draggedPointIndex].y = y - 50;
|
|
430
|
+
|
|
431
|
+
// Update the visual control point
|
|
432
|
+
const pointShape = this.controlPointShapes[this.draggedPointIndex];
|
|
433
|
+
pointShape.x = x - 50;
|
|
434
|
+
pointShape.y = y - 50;
|
|
435
|
+
|
|
436
|
+
// Update the Bezier curve
|
|
437
|
+
this.updateBezierPath();
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* Pointer up handler
|
|
443
|
+
*/
|
|
444
|
+
pointerUp() {
|
|
445
|
+
this.draggedPointIndex = -1;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* Render additional visual helpers
|
|
450
|
+
*/
|
|
451
|
+
draw() {
|
|
452
|
+
super.draw();
|
|
453
|
+
// If we have at least 2 points, draw guide lines between control points
|
|
454
|
+
if (this.points.length >= 2) {
|
|
455
|
+
Painter.save();
|
|
456
|
+
// Draw dashed lines connecting control points
|
|
457
|
+
Painter.colors.setStrokeColor("rgba(0, 255, 0, 0.8)");
|
|
458
|
+
Painter.lines.setLineWidth(1);
|
|
459
|
+
// Set up a dashed line style
|
|
460
|
+
Painter.ctx.setLineDash([5, 5]);
|
|
461
|
+
Painter.lines.beginPath();
|
|
462
|
+
Painter.lines.moveTo(this.points[0].x, this.points[0].y);
|
|
463
|
+
|
|
464
|
+
for (let i = 1; i < this.points.length; i++) {
|
|
465
|
+
Painter.lines.lineTo(this.points[i].x, this.points[i].y);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
Painter.colors.stroke();
|
|
469
|
+
Painter.ctx.setLineDash([]); // Reset dash
|
|
470
|
+
Painter.restore();
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
static gco = [
|
|
475
|
+
"source-over",
|
|
476
|
+
"multiply",
|
|
477
|
+
"screen",
|
|
478
|
+
"overlay",
|
|
479
|
+
"darken",
|
|
480
|
+
"lighten",
|
|
481
|
+
"color-dodge",
|
|
482
|
+
"color-burn",
|
|
483
|
+
"hard-light",
|
|
484
|
+
"soft-light",
|
|
485
|
+
"difference",
|
|
486
|
+
"exclusion",
|
|
487
|
+
"hue",
|
|
488
|
+
"saturation",
|
|
489
|
+
"color",
|
|
490
|
+
"luminosity",
|
|
491
|
+
];
|
|
492
|
+
|
|
493
|
+
#prevWidth = 0;
|
|
494
|
+
#prevHeight = 0;
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* Update method that adds the jitter animation to cut bezier shapes
|
|
498
|
+
*/
|
|
499
|
+
update(dt) {
|
|
500
|
+
// Update scene dimensions based on margin
|
|
501
|
+
this.width = this.game.width - this.MARGIN * 2;
|
|
502
|
+
this.height = this.game.height - this.MARGIN * 2;
|
|
503
|
+
|
|
504
|
+
// Center the scene in the game
|
|
505
|
+
this.x = this.game.width / 2;
|
|
506
|
+
this.y = this.game.height / 2;
|
|
507
|
+
const filter = Painter.ctx.globalCompositeOperation;
|
|
508
|
+
Painter.ctx.globalCompositeOperation = "screen";
|
|
509
|
+
// Update jitter animation for all cut beziers
|
|
510
|
+
for (const bezier of this.userBeziers) {
|
|
511
|
+
// Update the jitter phase
|
|
512
|
+
bezier.jitterPhase += dt * bezier.jitterSpeed * 5;
|
|
513
|
+
|
|
514
|
+
// Create a new jittered path based on the original
|
|
515
|
+
const jitteredPath = [];
|
|
516
|
+
for (
|
|
517
|
+
let cmdIndex = 0;
|
|
518
|
+
cmdIndex < bezier.originalPath.length;
|
|
519
|
+
cmdIndex++
|
|
520
|
+
) {
|
|
521
|
+
const originalCmd = bezier.originalPath[cmdIndex];
|
|
522
|
+
const newCmd = [...originalCmd]; // Make a copy
|
|
523
|
+
|
|
524
|
+
// Only modify coordinate values (not the command type at index 0)
|
|
525
|
+
for (let i = 1; i < newCmd.length; i++) {
|
|
526
|
+
if (typeof newCmd[i] === "number") {
|
|
527
|
+
// Apply a sine wave jitter with unique offset for each point
|
|
528
|
+
const offset =
|
|
529
|
+
Math.sin(bezier.jitterPhase + i * 0.3 + cmdIndex * 0.7) *
|
|
530
|
+
bezier.jitterAmount;
|
|
531
|
+
newCmd[i] = originalCmd[i] + offset;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
jitteredPath.push(newCmd);
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
// Apply the jittered path to the shape
|
|
538
|
+
bezier.shape.shape.path = jitteredPath;
|
|
539
|
+
}
|
|
540
|
+
//Painter.effects.setBlendMode(filter);
|
|
541
|
+
super.update(dt);
|
|
542
|
+
|
|
543
|
+
if (this.#prevWidth !== this.width || this.#prevHeight !== this.height) {
|
|
544
|
+
this.markBoundsDirty();
|
|
545
|
+
}
|
|
546
|
+
this.#prevWidth = this.width;
|
|
547
|
+
this.#prevHeight = this.height;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
/**
|
|
552
|
+
* UI for the Bezier Demo with controls for adding/editing points,
|
|
553
|
+
* clearing the canvas, and switching between modes.
|
|
554
|
+
*/
|
|
555
|
+
class BezierUIScene extends Scene {
|
|
556
|
+
constructor(game, bezierScene, options = {}) {
|
|
557
|
+
super(game, options);
|
|
558
|
+
this.bezierScene = bezierScene;
|
|
559
|
+
this.onMenu = false;
|
|
560
|
+
this.currentMode = null;
|
|
561
|
+
this._lastMobileState = null;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
/**
|
|
565
|
+
* Get button style configuration (transparent background)
|
|
566
|
+
*/
|
|
567
|
+
getButtonStyle() {
|
|
568
|
+
return {
|
|
569
|
+
colorHoverBg: "transparent",
|
|
570
|
+
colorDefaultBg: "transparent",
|
|
571
|
+
colorPressedBg: "transparent",
|
|
572
|
+
colorDefaultText: "white",
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
init() {
|
|
577
|
+
this.createButtons();
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* Create buttons with current responsive config
|
|
582
|
+
*/
|
|
583
|
+
createButtons() {
|
|
584
|
+
// Clear existing layout
|
|
585
|
+
if (this.layout) {
|
|
586
|
+
this.remove(this.layout);
|
|
587
|
+
this.layout = null;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
const config = this.game.getResponsiveConfig();
|
|
591
|
+
const buttonStyle = this.getButtonStyle();
|
|
592
|
+
|
|
593
|
+
this.layout = new HorizontalLayout(this.game, {
|
|
594
|
+
width: config.layoutWidth,
|
|
595
|
+
height: config.layoutHeight,
|
|
596
|
+
spacing: 5,
|
|
597
|
+
});
|
|
598
|
+
|
|
599
|
+
this.addModeButton = this.layout.add(
|
|
600
|
+
new ToggleButton(this.game, {
|
|
601
|
+
text: config.addLabel,
|
|
602
|
+
width: config.buttonWidth,
|
|
603
|
+
height: 32,
|
|
604
|
+
...buttonStyle,
|
|
605
|
+
startToggled: true,
|
|
606
|
+
onToggle: (active) => {
|
|
607
|
+
if (this.currentMode && this.currentMode !== this.addModeButton) {
|
|
608
|
+
this.currentMode.toggle(false);
|
|
609
|
+
}
|
|
610
|
+
if (active) {
|
|
611
|
+
this.bezierScene.setMode("add");
|
|
612
|
+
this.currentMode = this.addModeButton;
|
|
613
|
+
}
|
|
614
|
+
},
|
|
615
|
+
})
|
|
616
|
+
);
|
|
617
|
+
|
|
618
|
+
this.editModeButton = this.layout.add(
|
|
619
|
+
new ToggleButton(this.game, {
|
|
620
|
+
text: config.editLabel,
|
|
621
|
+
width: config.buttonWidth,
|
|
622
|
+
height: 32,
|
|
623
|
+
...buttonStyle,
|
|
624
|
+
onToggle: (active) => {
|
|
625
|
+
if (this.currentMode && this.currentMode !== this.editModeButton) {
|
|
626
|
+
this.currentMode.toggle(false);
|
|
627
|
+
}
|
|
628
|
+
if (active) {
|
|
629
|
+
this.bezierScene.setMode("edit");
|
|
630
|
+
this.currentMode = this.editModeButton;
|
|
631
|
+
}
|
|
632
|
+
},
|
|
633
|
+
})
|
|
634
|
+
);
|
|
635
|
+
|
|
636
|
+
this.cutModeButton = this.layout.add(
|
|
637
|
+
new Button(this.game, {
|
|
638
|
+
text: config.cutLabel,
|
|
639
|
+
width: config.buttonWidth,
|
|
640
|
+
height: 32,
|
|
641
|
+
...buttonStyle,
|
|
642
|
+
onClick: () => {
|
|
643
|
+
if (this.editModeButton) this.editModeButton.toggle(false);
|
|
644
|
+
if (this.addModeButton) this.addModeButton.toggle(false);
|
|
645
|
+
this.currentMode = null;
|
|
646
|
+
this.bezierScene.cutShape();
|
|
647
|
+
},
|
|
648
|
+
})
|
|
649
|
+
);
|
|
650
|
+
|
|
651
|
+
this.clearButton = this.layout.add(
|
|
652
|
+
new Button(this.game, {
|
|
653
|
+
text: config.clearLabel,
|
|
654
|
+
width: config.clearWidth,
|
|
655
|
+
height: 32,
|
|
656
|
+
...buttonStyle,
|
|
657
|
+
onClick: () => {
|
|
658
|
+
this.bezierScene.clear();
|
|
659
|
+
},
|
|
660
|
+
})
|
|
661
|
+
);
|
|
662
|
+
|
|
663
|
+
this.add(this.layout);
|
|
664
|
+
this.currentMode = this.addModeButton;
|
|
665
|
+
|
|
666
|
+
// Update scene dimensions
|
|
667
|
+
this.width = config.layoutWidth;
|
|
668
|
+
this.height = config.layoutHeight;
|
|
669
|
+
this.markBoundsDirty();
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
/**
|
|
673
|
+
* Handle resize - recreate buttons if mobile state changed
|
|
674
|
+
*/
|
|
675
|
+
onResize() {
|
|
676
|
+
const isMobile = this.game.isMobile();
|
|
677
|
+
|
|
678
|
+
// Only recreate if mobile state changed
|
|
679
|
+
if (this._lastMobileState !== isMobile) {
|
|
680
|
+
this._lastMobileState = isMobile;
|
|
681
|
+
this.createButtons();
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
// Update scene dimensions
|
|
685
|
+
const config = this.game.getResponsiveConfig();
|
|
686
|
+
this.width = config.layoutWidth;
|
|
687
|
+
this.height = config.layoutHeight;
|
|
688
|
+
this.markBoundsDirty();
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
/// Main game class
|
|
692
|
+
window.BezierDemoGame = BezierDemoGame;
|