@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,192 @@
|
|
|
1
|
+
import { Shape } from "./shape.js";
|
|
2
|
+
import { Painter } from "../painter";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Draws an arbitrary pixel buffer inside the normal Shape pipeline.
|
|
6
|
+
*
|
|
7
|
+
* ───────────────────────────────────────────────────────────────────────────
|
|
8
|
+
* Usage:
|
|
9
|
+
* const data = Painter.img.getImageData(0, 0, 320, 200); // any ImageData
|
|
10
|
+
* const fract = new ImageShape(data, { x: 100, y: 50, anchor: "center" });
|
|
11
|
+
* scene.add(fract); // acts like any Shape
|
|
12
|
+
*/
|
|
13
|
+
export class ImageShape extends Shape {
|
|
14
|
+
/**
|
|
15
|
+
* @param {HTMLImageElement|HTMLCanvasElement|ImageBitmap|Video|ImageData} bitmap Anything the 2‑D API understands
|
|
16
|
+
* @param {object} [options] Usual Shape options + anchor, etc.
|
|
17
|
+
*/
|
|
18
|
+
constructor(bitmap, options = {}) {
|
|
19
|
+
if (!bitmap && !options.width && !options.height) {
|
|
20
|
+
throw new Error(
|
|
21
|
+
"ImageShape must be initialized with either a bitmap or width and height"
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
super(options);
|
|
25
|
+
|
|
26
|
+
// Store the bitmap passed in
|
|
27
|
+
this._bitmap = bitmap ?? Painter.img.createImageData(options.width, options.height);
|
|
28
|
+
|
|
29
|
+
// Set dimensions based on bitmap or options
|
|
30
|
+
this._width = options.width ?? bitmap?.width ?? 0;
|
|
31
|
+
this._height = options.height ?? bitmap?.height ?? 0;
|
|
32
|
+
|
|
33
|
+
// Set anchor point (default to center)
|
|
34
|
+
this.anchor = options.anchor ?? "center";
|
|
35
|
+
|
|
36
|
+
// Track anchor x/y offsets (0-1 range)
|
|
37
|
+
this._anchorX = 0.5;
|
|
38
|
+
this._anchorY = 0.5;
|
|
39
|
+
this._updateAnchorOffsets();
|
|
40
|
+
|
|
41
|
+
// Enable image smoothing by default
|
|
42
|
+
this.smoothing = options.smoothing !== false;
|
|
43
|
+
|
|
44
|
+
// ImageData can't be transformed directly; cache an off‑screen canvas
|
|
45
|
+
if (bitmap instanceof ImageData) {
|
|
46
|
+
this.buffer(bitmap);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Calculate anchor point offsets based on anchor string
|
|
52
|
+
* @private
|
|
53
|
+
*/
|
|
54
|
+
_updateAnchorOffsets() {
|
|
55
|
+
// Parse anchor string to get x/y offsets
|
|
56
|
+
const anchor = this.anchor?.toLowerCase() ?? "center";
|
|
57
|
+
|
|
58
|
+
// X offset: left=0, center=0.5, right=1
|
|
59
|
+
if (anchor.includes("left")) this._anchorX = 0;
|
|
60
|
+
else if (anchor.includes("right")) this._anchorX = 1;
|
|
61
|
+
else this._anchorX = 0.5;
|
|
62
|
+
|
|
63
|
+
// Y offset: top=0, center=0.5, bottom=1
|
|
64
|
+
if (anchor.includes("top")) this._anchorY = 0;
|
|
65
|
+
else if (anchor.includes("bottom")) this._anchorY = 1;
|
|
66
|
+
else this._anchorY = 0.5;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Access the internal bitmap
|
|
71
|
+
* @returns {HTMLImageElement|HTMLCanvasElement|ImageBitmap|Video|ImageData} Current bitmap
|
|
72
|
+
*/
|
|
73
|
+
get bitmap() {
|
|
74
|
+
return this._bitmap;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Change the internal bitmap
|
|
79
|
+
* @param {HTMLImageElement|HTMLCanvasElement|ImageBitmap|Video|ImageData} bmp New bitmap
|
|
80
|
+
*/
|
|
81
|
+
set bitmap(bmp) {
|
|
82
|
+
//console.log("setting bitmap", bmp);
|
|
83
|
+
if (!bmp) return;
|
|
84
|
+
|
|
85
|
+
this._bitmap = bmp;
|
|
86
|
+
|
|
87
|
+
// Update width and height if not already set
|
|
88
|
+
if (!this._width && bmp.width) this._width = bmp.width;
|
|
89
|
+
if (!this._height && bmp.height) this._height = bmp.height;
|
|
90
|
+
|
|
91
|
+
// If it's ImageData, prepare the buffer
|
|
92
|
+
if (bmp instanceof ImageData) {
|
|
93
|
+
this.buffer(bmp);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Create or update the canvas buffer for ImageData
|
|
99
|
+
* @param {ImageData} bitmap ImageData to put in the buffer
|
|
100
|
+
*/
|
|
101
|
+
buffer(bitmap) {
|
|
102
|
+
if (!bitmap) return;
|
|
103
|
+
|
|
104
|
+
//console.log("Creating buffer for ImageData", bitmap.width, "x", bitmap.height);
|
|
105
|
+
|
|
106
|
+
// Create the buffer canvas if needed
|
|
107
|
+
if (!this._buffer) {
|
|
108
|
+
this._buffer = document.createElement("canvas");
|
|
109
|
+
//console.log("Created new buffer canvas");
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Resize buffer if needed
|
|
113
|
+
if (this._buffer.width !== bitmap.width || this._buffer.height !== bitmap.height) {
|
|
114
|
+
this._buffer.width = bitmap.width;
|
|
115
|
+
this._buffer.height = bitmap.height;
|
|
116
|
+
//console.log("Resized buffer to", bitmap.width, "x", bitmap.height);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Draw the ImageData to the buffer canvas
|
|
120
|
+
const ctx = this._buffer.getContext("2d");
|
|
121
|
+
ctx.putImageData(bitmap, 0, 0);
|
|
122
|
+
//console.log("Updated buffer with ImageData");
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Reset the image to an empty state
|
|
127
|
+
*/
|
|
128
|
+
reset() {
|
|
129
|
+
this._buffer = null;
|
|
130
|
+
this._bitmap = Painter.img.createImageData(this.width, this.height);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Set the anchor point
|
|
135
|
+
* @param {string} anchor Anchor position (e.g. "center", "top-left")
|
|
136
|
+
*/
|
|
137
|
+
setAnchor(anchor) {
|
|
138
|
+
this.anchor = anchor;
|
|
139
|
+
this._updateAnchorOffsets();
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/* ------------------------------------------------------------------ draw */
|
|
143
|
+
/**
|
|
144
|
+
* Draw the image to the canvas
|
|
145
|
+
*/
|
|
146
|
+
draw() {
|
|
147
|
+
// Skip drawing if not visible or no bitmap available
|
|
148
|
+
if (!this.visible) return;
|
|
149
|
+
if (!this._bitmap && !this._buffer) return;
|
|
150
|
+
|
|
151
|
+
super.draw();
|
|
152
|
+
|
|
153
|
+
// For ImageData, we must use the buffer
|
|
154
|
+
let source = (this._bitmap instanceof ImageData) ? this._buffer : this._bitmap;
|
|
155
|
+
|
|
156
|
+
if (!source || (this._bitmap instanceof ImageData && !this._buffer)) {
|
|
157
|
+
// If we need a buffer but don't have one yet, try to create it
|
|
158
|
+
if (this._bitmap instanceof ImageData) {
|
|
159
|
+
this.buffer(this._bitmap);
|
|
160
|
+
source = this._buffer;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// If we still don't have a valid source, skip drawing
|
|
164
|
+
if (!source) return;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Delegates all transform/alpha/smoothing handling to Painter.img.draw
|
|
168
|
+
Painter.img.draw(source, 0, 0, {
|
|
169
|
+
width: this.width,
|
|
170
|
+
height: this.height,
|
|
171
|
+
anchor: this.anchor,
|
|
172
|
+
rotation: this.rotation,
|
|
173
|
+
scaleX: this.scaleX,
|
|
174
|
+
scaleY: this.scaleY,
|
|
175
|
+
alpha: this.opacity,
|
|
176
|
+
smoothing: this.smoothing,
|
|
177
|
+
flipX: this.scaleX < 0,
|
|
178
|
+
flipY: this.scaleY < 0,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/* ---------------------------------------------------- bounds & geometry */
|
|
183
|
+
/** Re‑compute bounding box (called by base class when something changes). */
|
|
184
|
+
calculateBounds() {
|
|
185
|
+
return {
|
|
186
|
+
x: -this._anchorX * this.width,
|
|
187
|
+
y: -this._anchorY * this.height,
|
|
188
|
+
width: this.width,
|
|
189
|
+
height: this.height,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module Shapes
|
|
3
|
+
* @description Comprehensive collection of drawable shapes and visual elements for canvas rendering.
|
|
4
|
+
*
|
|
5
|
+
* This module provides a rich library of shape primitives that can be used to create
|
|
6
|
+
* complex visual elements in canvas-based games and applications. All shapes are built on
|
|
7
|
+
* a consistent foundation that includes:
|
|
8
|
+
*
|
|
9
|
+
* - Common positioning and sizing (x, y, width, height)
|
|
10
|
+
* - Transformation capabilities (rotation, scaling)
|
|
11
|
+
* - Styling options (fill, stroke, opacity)
|
|
12
|
+
* - Shadow effects
|
|
13
|
+
* - Consistent bounding box calculations for hit detection
|
|
14
|
+
*
|
|
15
|
+
* The hierarchy is as follows:
|
|
16
|
+
* - {@link Transformable}: Base class providing transformation properties
|
|
17
|
+
* - {@link Shape}: Abstract base class adding drawing capabilities
|
|
18
|
+
* - Numerous concrete shape implementations like {@link Rectangle}, {@link Circle}, {@link Cube}, etc.
|
|
19
|
+
*
|
|
20
|
+
* Each shape can be used standalone with the Painter system or wrapped in a
|
|
21
|
+
* GameObject to participate in the game's update/render pipeline.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* // Creating and styling a simple rectangle
|
|
25
|
+
* import { Rectangle } from './core/shapes';
|
|
26
|
+
* import { Painter } from './core/painter';
|
|
27
|
+
*
|
|
28
|
+
* // Initialize painter with canvas context
|
|
29
|
+
* Painter.init(ctx);
|
|
30
|
+
*
|
|
31
|
+
* // Create and draw a rectangle
|
|
32
|
+
* const rect = new Rectangle(100, 100, 200, 150, {
|
|
33
|
+
* color: '#3498db',
|
|
34
|
+
* stroke: '#2980b9',
|
|
35
|
+
* lineWidth: 2,
|
|
36
|
+
* rotation: Math.PI / 6, // 30 degrees in radians
|
|
37
|
+
* opacity: 0.8
|
|
38
|
+
* });
|
|
39
|
+
* rect.draw();
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* // Creating a 3D-looking isometric cube
|
|
43
|
+
* import { Cube } from './core/shapes';
|
|
44
|
+
*
|
|
45
|
+
* const cube = new Cube(200, 200, 80, {
|
|
46
|
+
* faceTopColor: '#e74c3c',
|
|
47
|
+
* faceLeftColor: '#c0392b',
|
|
48
|
+
* faceRightColor: '#a93226',
|
|
49
|
+
* rotationX: Math.PI / 8,
|
|
50
|
+
* rotationY: Math.PI / 6
|
|
51
|
+
* });
|
|
52
|
+
* cube.draw();
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* // Adding text with wrapping capabilities
|
|
56
|
+
* import { WrappedText } from './core/shapes';
|
|
57
|
+
*
|
|
58
|
+
* const text = new WrappedText(50, 50,
|
|
59
|
+
* "This is a longer text that will automatically wrap to fit within the specified width.",
|
|
60
|
+
* 300, 24, {
|
|
61
|
+
* color: '#333',
|
|
62
|
+
* font: '18px Arial',
|
|
63
|
+
* align: 'center',
|
|
64
|
+
* outlineColor: '#fff',
|
|
65
|
+
* outlineWidth: 2
|
|
66
|
+
* }
|
|
67
|
+
* );
|
|
68
|
+
* text.draw();
|
|
69
|
+
*
|
|
70
|
+
* @see {@link GameObject} For wrapping shapes in game objects to add to the pipeline
|
|
71
|
+
* @see {@link ShapeGOFactory} For a utility to quickly create GameObject wrappers for shapes
|
|
72
|
+
*/
|
|
73
|
+
//Shape Abstracts
|
|
74
|
+
export { Euclidian } from "./euclidian.js";
|
|
75
|
+
export { Geometry2d } from "./geometry.js";
|
|
76
|
+
export { Traceable } from "./traceable.js";
|
|
77
|
+
export { Renderable } from "./renderable.js";
|
|
78
|
+
export { Transformable } from "./transformable.js";
|
|
79
|
+
export { Transform } from "./transform.js";
|
|
80
|
+
export { Shape } from "./shape.js";
|
|
81
|
+
export { Group } from "./group.js";
|
|
82
|
+
// Shape Primitives
|
|
83
|
+
export { Arc } from "./arc.js";
|
|
84
|
+
export { Circle } from "./circle.js";
|
|
85
|
+
export { Cloud } from "./clouds.js";
|
|
86
|
+
export { BezierShape } from "./bezier.js";
|
|
87
|
+
export { Rectangle } from "./rect.js";
|
|
88
|
+
export { RoundedRectangle } from "./roundrect.js";
|
|
89
|
+
export { PatternRectangle } from "./pattern";
|
|
90
|
+
export { Square } from "./square.js";
|
|
91
|
+
export { Cube } from "./cube.js";
|
|
92
|
+
export { Cone } from "./cone.js";
|
|
93
|
+
export { Prism } from "./prism.js";
|
|
94
|
+
export { Cylinder } from "./cylinder.js";
|
|
95
|
+
export { Diamond } from "./diamond.js";
|
|
96
|
+
export { Line } from "./line.js";
|
|
97
|
+
export { Triangle } from "./triangle.js";
|
|
98
|
+
export { Star } from "./star.js";
|
|
99
|
+
export { Sphere } from "./sphere.js";
|
|
100
|
+
export { Sphere3D } from "./sphere3d.js";
|
|
101
|
+
export { SVGShape } from "./svg.js";
|
|
102
|
+
export { StickFigure } from "./figure.js";
|
|
103
|
+
export { Ring } from "./ring.js";
|
|
104
|
+
export { Polygon } from "./poly.js";
|
|
105
|
+
export { Arrow } from "./arrow.js";
|
|
106
|
+
export { Pin } from "./pin.js";
|
|
107
|
+
export { PieSlice } from "./slice.js";
|
|
108
|
+
export { Hexagon } from "./hexagon.js";
|
|
109
|
+
export { Heart } from "./heart.js";
|
|
110
|
+
export { Cross } from "./cross.js";
|
|
111
|
+
export * from "./text.js";
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Shape } from "./shape.js";
|
|
2
|
+
import { Painter } from "../painter/painter.js";
|
|
3
|
+
|
|
4
|
+
export class Line extends Shape {
|
|
5
|
+
/**
|
|
6
|
+
* Creates a line shape centered around (x, y)
|
|
7
|
+
* @param {number} x - Center X
|
|
8
|
+
* @param {number} y - Center Y
|
|
9
|
+
* @param {number} length - Length of the line
|
|
10
|
+
* @param {Object} options - Style options
|
|
11
|
+
*/
|
|
12
|
+
constructor(length = 40, options = {}) {
|
|
13
|
+
super(options);
|
|
14
|
+
this.length = length;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
draw() {
|
|
18
|
+
super.draw();
|
|
19
|
+
const half = this.length / 2;
|
|
20
|
+
Painter.lines.line(
|
|
21
|
+
-half,
|
|
22
|
+
-half,
|
|
23
|
+
half,
|
|
24
|
+
half,
|
|
25
|
+
this.stroke,
|
|
26
|
+
this.lineWidth
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { Shape } from "./shape.js";
|
|
2
|
+
import { Painter } from "../painter/painter.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* PatternRectangle - A drawable centered rectangle filled with a pattern.
|
|
6
|
+
* Supports lazy image loading and CanvasImageSource types.
|
|
7
|
+
*/
|
|
8
|
+
export class PatternRectangle extends Shape {
|
|
9
|
+
/**
|
|
10
|
+
* @param {CanvasImageSource|null} image - Optional pattern source
|
|
11
|
+
* @param {string} [repetition='repeat'] - Pattern repetition mode
|
|
12
|
+
* @param {Object} [options] - Shape rendering options
|
|
13
|
+
*/
|
|
14
|
+
constructor(image = null, repetition = "repeat", options = {}) {
|
|
15
|
+
super(options);
|
|
16
|
+
this.image = image;
|
|
17
|
+
this.repetition = repetition;
|
|
18
|
+
this.pattern = null;
|
|
19
|
+
|
|
20
|
+
if (image) this._tryCreatePattern(image);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
_tryCreatePattern(image) {
|
|
24
|
+
const isAsyncImage =
|
|
25
|
+
image instanceof HTMLImageElement ||
|
|
26
|
+
(typeof image.complete === "boolean");
|
|
27
|
+
|
|
28
|
+
if (isAsyncImage) {
|
|
29
|
+
if (image.complete) {
|
|
30
|
+
this._createPattern();
|
|
31
|
+
} else {
|
|
32
|
+
image.addEventListener("load", () => this._createPattern(), {
|
|
33
|
+
once: true,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
} else {
|
|
37
|
+
this._createPattern();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
_createPattern() {
|
|
42
|
+
this.pattern = Painter.img.createPattern(this.image, this.repetition);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
setImage(image, repetition) {
|
|
46
|
+
this.image = image;
|
|
47
|
+
if (repetition) this.repetition = repetition;
|
|
48
|
+
this.pattern = null;
|
|
49
|
+
this._tryCreatePattern(image);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
draw() {
|
|
53
|
+
super.draw();
|
|
54
|
+
|
|
55
|
+
if (!this.pattern && this.image) {
|
|
56
|
+
this._tryCreatePattern(this.image);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const x = -this.width / 2;
|
|
60
|
+
const y = -this.height / 2;
|
|
61
|
+
|
|
62
|
+
if (this.pattern) {
|
|
63
|
+
Painter.img.fillPattern(
|
|
64
|
+
this.pattern,
|
|
65
|
+
x,
|
|
66
|
+
y,
|
|
67
|
+
this.width,
|
|
68
|
+
this.height
|
|
69
|
+
);
|
|
70
|
+
} else if (this.strokeColor) {
|
|
71
|
+
Painter.shapes.outlineRect(
|
|
72
|
+
x,
|
|
73
|
+
y,
|
|
74
|
+
this.width,
|
|
75
|
+
this.height,
|
|
76
|
+
this.strokeColor,
|
|
77
|
+
this.lineWidth
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
getBounds() {
|
|
83
|
+
return {
|
|
84
|
+
x: this.x,
|
|
85
|
+
y: this.y,
|
|
86
|
+
width: this.width,
|
|
87
|
+
height: this.height,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Shape } from "./shape.js";
|
|
2
|
+
import { Painter } from "../painter/painter.js";
|
|
3
|
+
|
|
4
|
+
export class Pin extends Shape {
|
|
5
|
+
constructor(radius = 20, options = {}) {
|
|
6
|
+
super(options);
|
|
7
|
+
this.radius = radius;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
draw() {
|
|
11
|
+
super.draw();
|
|
12
|
+
const r = this.radius;
|
|
13
|
+
const h = r * 2.5;
|
|
14
|
+
const baseY = 0;
|
|
15
|
+
|
|
16
|
+
Painter.lines.beginPath();
|
|
17
|
+
|
|
18
|
+
// Draw circle head
|
|
19
|
+
Painter.shapes.arc(0, baseY, r, Math.PI, 0);
|
|
20
|
+
|
|
21
|
+
// Draw tail (triangle)
|
|
22
|
+
Painter.lines.lineTo(r, baseY);
|
|
23
|
+
Painter.lines.lineTo(0, h);
|
|
24
|
+
Painter.lines.lineTo(-r, baseY);
|
|
25
|
+
Painter.lines.closePath();
|
|
26
|
+
|
|
27
|
+
if (this.color) {
|
|
28
|
+
Painter.colors.fill(this.color);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (this.stroke) {
|
|
32
|
+
Painter.colors.stroke(this.stroke, this.lineWidth);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
getBounds() {
|
|
37
|
+
return {
|
|
38
|
+
x: this.x,
|
|
39
|
+
y: this.y + this.radius * 0.98, // shift center lower
|
|
40
|
+
width: this.radius * 2,
|
|
41
|
+
height: this.radius * 2.5,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Shape } from "./shape.js";
|
|
2
|
+
import { Painter } from "../painter/painter.js";
|
|
3
|
+
|
|
4
|
+
export class Polygon extends Shape {
|
|
5
|
+
constructor(sides = 6, radius = 40, options = {}) {
|
|
6
|
+
super(options);
|
|
7
|
+
this.sides = sides;
|
|
8
|
+
this.radius = radius;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
draw() {
|
|
12
|
+
super.draw();
|
|
13
|
+
const points = [];
|
|
14
|
+
const step = (2 * Math.PI) / this.sides;
|
|
15
|
+
|
|
16
|
+
for (let i = 0; i < this.sides; i++) {
|
|
17
|
+
const angle = i * step;
|
|
18
|
+
points.push({
|
|
19
|
+
x: Math.cos(angle) * this.radius,
|
|
20
|
+
y: Math.sin(angle) * this.radius,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
Painter.shapes.polygon(
|
|
25
|
+
points,
|
|
26
|
+
this.color,
|
|
27
|
+
this.stroke,
|
|
28
|
+
this.lineWidth
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
}
|