@guinetik/gcanvas 1.0.4 → 1.0.5

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.
Files changed (193) hide show
  1. package/dist/CNAME +1 -0
  2. package/dist/animations.html +31 -0
  3. package/dist/basic.html +38 -0
  4. package/dist/baskara.html +31 -0
  5. package/dist/bezier.html +35 -0
  6. package/dist/beziersignature.html +29 -0
  7. package/dist/blackhole.html +28 -0
  8. package/dist/blob.html +35 -0
  9. package/dist/coordinates.html +698 -0
  10. package/dist/cube3d.html +23 -0
  11. package/dist/demos.css +303 -0
  12. package/dist/dino.html +42 -0
  13. package/dist/easing.html +28 -0
  14. package/dist/events.html +195 -0
  15. package/dist/fluent.html +647 -0
  16. package/dist/fluid-simple.html +22 -0
  17. package/dist/fluid.html +37 -0
  18. package/dist/fractals.html +36 -0
  19. package/dist/gameobjects.html +626 -0
  20. package/dist/gcanvas.es.js +517 -0
  21. package/dist/gcanvas.es.min.js +1 -1
  22. package/dist/gcanvas.umd.js +1 -1
  23. package/dist/gcanvas.umd.min.js +1 -1
  24. package/dist/genart.html +26 -0
  25. package/dist/gendream.html +26 -0
  26. package/dist/group.html +36 -0
  27. package/dist/home.html +587 -0
  28. package/dist/hyperbolic001.html +23 -0
  29. package/dist/hyperbolic002.html +23 -0
  30. package/dist/hyperbolic003.html +23 -0
  31. package/dist/hyperbolic004.html +23 -0
  32. package/dist/hyperbolic005.html +22 -0
  33. package/dist/index.html +398 -0
  34. package/dist/isometric.html +34 -0
  35. package/dist/js/animations.js +452 -0
  36. package/dist/js/basic.js +204 -0
  37. package/dist/js/baskara.js +751 -0
  38. package/dist/js/bezier.js +692 -0
  39. package/dist/js/beziersignature.js +241 -0
  40. package/dist/js/blackhole/accretiondisk.obj.js +379 -0
  41. package/dist/js/blackhole/blackhole.obj.js +318 -0
  42. package/dist/js/blackhole/index.js +409 -0
  43. package/dist/js/blackhole/particle.js +56 -0
  44. package/dist/js/blackhole/starfield.obj.js +218 -0
  45. package/dist/js/blob.js +2276 -0
  46. package/dist/js/coordinates.js +840 -0
  47. package/dist/js/cube3d.js +789 -0
  48. package/dist/js/dino.js +1420 -0
  49. package/dist/js/easing.js +477 -0
  50. package/dist/js/fluent.js +183 -0
  51. package/dist/js/fluid-simple.js +253 -0
  52. package/dist/js/fluid.js +527 -0
  53. package/dist/js/fractals.js +932 -0
  54. package/dist/js/fractalworker.js +93 -0
  55. package/dist/js/gameobjects.js +176 -0
  56. package/dist/js/genart.js +268 -0
  57. package/dist/js/gendream.js +209 -0
  58. package/dist/js/group.js +140 -0
  59. package/dist/js/hyperbolic001.js +310 -0
  60. package/dist/js/hyperbolic002.js +388 -0
  61. package/dist/js/hyperbolic003.js +319 -0
  62. package/dist/js/hyperbolic004.js +345 -0
  63. package/dist/js/hyperbolic005.js +340 -0
  64. package/dist/js/info-toggle.js +25 -0
  65. package/dist/js/isometric.js +863 -0
  66. package/dist/js/kerr.js +1547 -0
  67. package/dist/js/lavalamp.js +590 -0
  68. package/dist/js/layout.js +354 -0
  69. package/dist/js/mondrian.js +285 -0
  70. package/dist/js/opacity.js +275 -0
  71. package/dist/js/painter.js +484 -0
  72. package/dist/js/particles-showcase.js +514 -0
  73. package/dist/js/particles.js +299 -0
  74. package/dist/js/patterns.js +397 -0
  75. package/dist/js/penrose/artifact.js +69 -0
  76. package/dist/js/penrose/blackhole.js +121 -0
  77. package/dist/js/penrose/constants.js +73 -0
  78. package/dist/js/penrose/game.js +943 -0
  79. package/dist/js/penrose/lore.js +278 -0
  80. package/dist/js/penrose/penrosescene.js +892 -0
  81. package/dist/js/penrose/ship.js +216 -0
  82. package/dist/js/penrose/sounds.js +211 -0
  83. package/dist/js/penrose/voidparticle.js +55 -0
  84. package/dist/js/penrose/voidscene.js +258 -0
  85. package/dist/js/penrose/voidship.js +144 -0
  86. package/dist/js/penrose/wormhole.js +46 -0
  87. package/dist/js/pipeline.js +555 -0
  88. package/dist/js/plane3d.js +256 -0
  89. package/dist/js/platformer.js +1579 -0
  90. package/dist/js/scene.js +304 -0
  91. package/dist/js/scenes.js +320 -0
  92. package/dist/js/schrodinger.js +410 -0
  93. package/dist/js/schwarzschild.js +1015 -0
  94. package/dist/js/shapes.js +628 -0
  95. package/dist/js/space/alien.js +171 -0
  96. package/dist/js/space/boom.js +98 -0
  97. package/dist/js/space/boss.js +353 -0
  98. package/dist/js/space/buff.js +73 -0
  99. package/dist/js/space/bullet.js +102 -0
  100. package/dist/js/space/constants.js +85 -0
  101. package/dist/js/space/game.js +1884 -0
  102. package/dist/js/space/hud.js +112 -0
  103. package/dist/js/space/laserbeam.js +179 -0
  104. package/dist/js/space/lightning.js +277 -0
  105. package/dist/js/space/minion.js +192 -0
  106. package/dist/js/space/missile.js +212 -0
  107. package/dist/js/space/player.js +430 -0
  108. package/dist/js/space/powerup.js +90 -0
  109. package/dist/js/space/starfield.js +58 -0
  110. package/dist/js/space/starpower.js +90 -0
  111. package/dist/js/spacetime.js +559 -0
  112. package/dist/js/sphere3d.js +229 -0
  113. package/dist/js/sprite.js +473 -0
  114. package/dist/js/starfaux/config.js +118 -0
  115. package/dist/js/starfaux/enemy.js +353 -0
  116. package/dist/js/starfaux/hud.js +78 -0
  117. package/dist/js/starfaux/index.js +482 -0
  118. package/dist/js/starfaux/laser.js +182 -0
  119. package/dist/js/starfaux/player.js +468 -0
  120. package/dist/js/starfaux/terrain.js +560 -0
  121. package/dist/js/study001.js +275 -0
  122. package/dist/js/study002.js +366 -0
  123. package/dist/js/study003.js +331 -0
  124. package/dist/js/study004.js +389 -0
  125. package/dist/js/study005.js +209 -0
  126. package/dist/js/study006.js +194 -0
  127. package/dist/js/study007.js +192 -0
  128. package/dist/js/study008.js +413 -0
  129. package/dist/js/svgtween.js +204 -0
  130. package/dist/js/tde/accretiondisk.js +471 -0
  131. package/dist/js/tde/blackhole.js +219 -0
  132. package/dist/js/tde/blackholescene.js +209 -0
  133. package/dist/js/tde/config.js +59 -0
  134. package/dist/js/tde/index.js +820 -0
  135. package/dist/js/tde/jets.js +290 -0
  136. package/dist/js/tde/lensedstarfield.js +154 -0
  137. package/dist/js/tde/tdestar.js +297 -0
  138. package/dist/js/tde/tidalstream.js +372 -0
  139. package/dist/js/tde_old/blackhole.obj.js +354 -0
  140. package/dist/js/tde_old/debris.obj.js +791 -0
  141. package/dist/js/tde_old/flare.obj.js +239 -0
  142. package/dist/js/tde_old/index.js +448 -0
  143. package/dist/js/tde_old/star.obj.js +812 -0
  144. package/dist/js/tetris/config.js +157 -0
  145. package/dist/js/tetris/grid.js +286 -0
  146. package/dist/js/tetris/index.js +1195 -0
  147. package/dist/js/tetris/renderer.js +634 -0
  148. package/dist/js/tetris/tetrominos.js +280 -0
  149. package/dist/js/tiles.js +312 -0
  150. package/dist/js/tweendemo.js +79 -0
  151. package/dist/js/visibility.js +102 -0
  152. package/dist/kerr.html +28 -0
  153. package/dist/lavalamp.html +27 -0
  154. package/dist/layouts.html +37 -0
  155. package/dist/logo.svg +4 -0
  156. package/dist/loop.html +84 -0
  157. package/dist/mondrian.html +32 -0
  158. package/dist/og_image.png +0 -0
  159. package/dist/opacity.html +36 -0
  160. package/dist/painter.html +39 -0
  161. package/dist/particles-showcase.html +28 -0
  162. package/dist/particles.html +24 -0
  163. package/dist/patterns.html +33 -0
  164. package/dist/penrose-game.html +31 -0
  165. package/dist/pipeline.html +737 -0
  166. package/dist/plane3d.html +24 -0
  167. package/dist/platformer.html +43 -0
  168. package/dist/scene.html +33 -0
  169. package/dist/scenes.html +96 -0
  170. package/dist/schrodinger.html +27 -0
  171. package/dist/schwarzschild.html +27 -0
  172. package/dist/shapes.html +16 -0
  173. package/dist/space.html +85 -0
  174. package/dist/spacetime.html +27 -0
  175. package/dist/sphere3d.html +24 -0
  176. package/dist/sprite.html +18 -0
  177. package/dist/starfaux.html +22 -0
  178. package/dist/study001.html +23 -0
  179. package/dist/study002.html +23 -0
  180. package/dist/study003.html +23 -0
  181. package/dist/study004.html +23 -0
  182. package/dist/study005.html +22 -0
  183. package/dist/study006.html +24 -0
  184. package/dist/study007.html +24 -0
  185. package/dist/study008.html +22 -0
  186. package/dist/svgtween.html +29 -0
  187. package/dist/tde.html +28 -0
  188. package/dist/tetris3d.html +25 -0
  189. package/dist/tiles.html +28 -0
  190. package/dist/transforms.html +400 -0
  191. package/dist/tween.html +45 -0
  192. package/dist/visibility.html +33 -0
  193. package/package.json +1 -1
@@ -0,0 +1,628 @@
1
+ import {
2
+ Game,
3
+ GameObject,
4
+ FPSCounter,
5
+ Text,
6
+ Tween,
7
+ Painter,
8
+ Scene,
9
+ ShapeGOFactory,
10
+ TileLayout,
11
+ Motion,
12
+ Tweenetik,
13
+ Easing,
14
+ Line,
15
+ Rectangle,
16
+ Square,
17
+ RoundedRectangle,
18
+ Diamond,
19
+ Triangle,
20
+ Hexagon,
21
+ Polygon,
22
+ Star,
23
+ PieSlice,
24
+ Circle,
25
+ Arc,
26
+ BezierShape,
27
+ Ring,
28
+ Cube,
29
+ Prism,
30
+ Cylinder,
31
+ Cone,
32
+ Sphere,
33
+ Arrow,
34
+ Pin,
35
+ Cross,
36
+ StickFigure,
37
+ Heart,
38
+ Group,
39
+ TextShape,
40
+ applyAnchor,
41
+ Position,
42
+ } from "/gcanvas.es.min.js";
43
+
44
+ const CONFIG = {
45
+ headerHeight: 80, // Space reserved for title + subtitle (30px title offset + 60px subtitle offset + spacing)
46
+ margin: 40, // Horizontal/vertical margins for viewport calculation
47
+ bottomMargin: 70, // Space reserved for FPS counter at bottom (with margin above it)
48
+ };
49
+
50
+ class ShapeGalleryGame extends Game {
51
+ constructor(canvas) {
52
+ super(canvas);
53
+ this.backgroundColor = "#fff";
54
+ this.enableFluidSize();
55
+ this.cellSize = 120;
56
+ this.maxColumns = 5;
57
+ }
58
+
59
+ /**
60
+ * Get viewport dimensions for scrolling based on available space.
61
+ * Accounts for header (title + subtitle), bottom margin (FPS counter), and margins.
62
+ * @returns {{width: number, height: number}} Viewport dimensions
63
+ */
64
+ getViewportDimensions() {
65
+ const availableHeight = this.canvas.height - CONFIG.headerHeight - CONFIG.bottomMargin - CONFIG.margin;
66
+ const availableWidth = this.canvas.width - CONFIG.margin * 2;
67
+ return {
68
+ width: Math.max(200, availableWidth),
69
+ height: Math.max(200, availableHeight),
70
+ };
71
+ }
72
+
73
+ init() {
74
+ super.init();
75
+ this.shapeEntries = [
76
+ {
77
+ name: "Cube",
78
+ class: Cube,
79
+ args: [50],
80
+ options: {
81
+ y: -10,
82
+ opacity: 0.8,
83
+ scaleX: 0.7,
84
+ scaleY: 0.7,
85
+ faceTopColor: Painter.colors.randomColorHSL(),
86
+ faceLeftColor: Painter.colors.randomColorHSL(),
87
+ faceRightColor: Painter.colors.randomColorHSL(),
88
+ faceFrontColor: Painter.colors.randomColorHSL(),
89
+ faceBackColor: Painter.colors.randomColorHSL(),
90
+ faceBottomColor: Painter.colors.randomColorHSL(),
91
+ strokeColor: "black",
92
+ lineWidth: 1,
93
+ },
94
+ },
95
+ {
96
+ name: "Sphere",
97
+ class: Sphere,
98
+ args: [25],
99
+ options: {
100
+ y: -10,
101
+ width: 50,
102
+ height: 50,
103
+ color: Painter.colors.randomColorHSL(),
104
+ highlightColor: "white",
105
+ hSegments: 16, // Fewer segments for wireframe
106
+ vSegments: 16,
107
+ wireframe: true, // Wireframe rendering
108
+ stroke: "#CCC",
109
+ lineWidth: 1,
110
+ rotationX: Math.PI / 8,
111
+ rotationY: 0,
112
+ rotationZ: 0,
113
+ },
114
+ },
115
+ {
116
+ name: "Cone",
117
+ class: Cone,
118
+ args: [20, 40],
119
+ options: {
120
+ x: -2,
121
+ y: -10,
122
+ bottomColor: "#FF00FF",
123
+ sideColor: "#00FF00",
124
+ segments: 16, // Higher for smoother appearance
125
+ stroke: "#333",
126
+ lineWidth: 1,
127
+ },
128
+ },
129
+ {
130
+ name: "Cylinder",
131
+ class: Cylinder,
132
+ args: [10],
133
+ options: {
134
+ y: -10,
135
+ width: 40,
136
+ height: 60,
137
+ topColor: Painter.colors.randomColorHSL(),
138
+ bottomColor: Painter.colors.randomColorHSL(),
139
+ sideColor: Painter.colors.randomColorHSL(),
140
+ rotationX: -45,
141
+ segments: 16, // Higher number for smoother curve
142
+ stroke: "black",
143
+ lineWidth: 1,
144
+ },
145
+ },
146
+ {
147
+ name: "Prism",
148
+ class: Prism,
149
+ args: [50],
150
+ options: {
151
+ y: -20,
152
+ width: 50,
153
+ height: 50,
154
+ scaleX: 0.7,
155
+ scaleY: 0.7,
156
+ faceFrontColor: "#6495ED",
157
+ faceBackColor: "#4169E1",
158
+ faceBottomColor: "#1E90FF",
159
+ faceLeftColor: "#00BFFF",
160
+ faceRightColor: "#87CEFA",
161
+ stroke: "#000",
162
+ lineWidth: 1,
163
+ },
164
+ },
165
+ {
166
+ name: "Line",
167
+ class: Line,
168
+ args: [40],
169
+ options: { stroke: "black", lineWidth: 3 },
170
+ },
171
+ {
172
+ name: "Bezier",
173
+ class: BezierShape,
174
+ args: [
175
+ [
176
+ ["M", -40, 0],
177
+ ["C", -30, -30, -10, -30, 0, 0],
178
+ ["C", 10, 30, 30, 30, 40, 0],
179
+ ],
180
+ ],
181
+ options: {
182
+ y: -10,
183
+ color: Painter.colors.randomColorHSL(),
184
+ stroke: Painter.colors.randomColorHSL(),
185
+ lineWidth: 3,
186
+ },
187
+ },
188
+ {
189
+ name: "Bezier (Filled)",
190
+ class: BezierShape,
191
+ args: [
192
+ [
193
+ ["M", -60, 0],
194
+ ["C", -60, -20, -20, -20, 0, 0],
195
+ ["C", 20, 20, 60, 20, 60, 0],
196
+ ["C", 60, -20, 20, -20, 0, 0],
197
+ ["C", -20, 20, -60, 20, -60, 0],
198
+ ["Z"],
199
+ ],
200
+ ],
201
+ options: {
202
+ scaleX: 0.7,
203
+ scaleY: 0.7,
204
+ y: -10,
205
+ color: Painter.colors.randomColorHSL(),
206
+ stroke: Painter.colors.randomColorHSL(),
207
+ lineWidth: 3,
208
+ },
209
+ },
210
+ {
211
+ name: "Pin",
212
+ class: Pin,
213
+ args: [16],
214
+ options: {
215
+ color: Painter.colors.randomColorHSL(),
216
+ stroke: "black",
217
+ lineWidth: 2,
218
+ scaleX: 0.9,
219
+ scaleY: 0.9,
220
+ y: -20,
221
+ },
222
+ },
223
+ {
224
+ name: "Heart",
225
+ class: Heart,
226
+ args: [],
227
+ options: {
228
+ width: 50,
229
+ height: 50,
230
+ color: Painter.colors.randomColorHSL(),
231
+ stroke: "black",
232
+ lineWidth: 2,
233
+ y: -35,
234
+ },
235
+ },
236
+ {
237
+ name: "Rounded Rect",
238
+ class: RoundedRectangle,
239
+ args: [10],
240
+ options: {
241
+ width: 50,
242
+ height: 50,
243
+ y: -10,
244
+ color: Painter.colors.randomColorHSL(),
245
+ stroke: "black",
246
+ lineWidth: 2,
247
+ crisp: true,
248
+ },
249
+ },
250
+ {
251
+ name: "Rectangle",
252
+ class: Rectangle,
253
+ args: [],
254
+ options: {
255
+ width: 70,
256
+ height: 50,
257
+ y: -5,
258
+ color: Painter.colors.randomColorHSL(),
259
+ stroke: "black",
260
+ lineWidth: 2,
261
+ crisp: true,
262
+ },
263
+ },
264
+ {
265
+ name: "Square",
266
+ class: Square,
267
+ args: [50],
268
+ options: {
269
+ y: -5,
270
+ color: Painter.colors.randomColorHSL(),
271
+ stroke: "black",
272
+ lineWidth: 2,
273
+ crisp: true,
274
+ },
275
+ },
276
+ {
277
+ name: "Diamond",
278
+ class: Diamond,
279
+ args: [],
280
+ options: {
281
+ y: -10,
282
+ width: 60,
283
+ height: 60,
284
+ color: Painter.colors.randomColorHSL(),
285
+ stroke: "black",
286
+ lineWidth: 2,
287
+ },
288
+ },
289
+
290
+ {
291
+ name: "Triangle",
292
+ class: Triangle,
293
+ args: [50],
294
+ options: {
295
+ y: -10,
296
+ color: Painter.colors.randomColorHSL(),
297
+ stroke: "black",
298
+ lineWidth: 2,
299
+ },
300
+ },
301
+ {
302
+ name: "Hexagon",
303
+ class: Hexagon,
304
+ args: [30],
305
+ options: {
306
+ y: -10,
307
+ color: Painter.colors.randomColorHSL(),
308
+ stroke: "black",
309
+ lineWidth: 2,
310
+ },
311
+ },
312
+ {
313
+ name: "Polygon",
314
+ class: Polygon,
315
+ args: [9, 30],
316
+ options: {
317
+ y: -10,
318
+ color: Painter.colors.randomColorHSL(),
319
+ stroke: "black",
320
+ lineWidth: 2,
321
+ },
322
+ },
323
+ {
324
+ name: "Star",
325
+ class: Star,
326
+ args: [30, 5, 0.5],
327
+ options: {
328
+ y: -10,
329
+ color: Painter.colors.randomColorHSL(),
330
+ stroke: "black",
331
+ lineWidth: 2,
332
+ },
333
+ },
334
+ {
335
+ name: "Circle",
336
+ class: Circle,
337
+ args: [30],
338
+ options: {
339
+ color: Painter.colors.randomColorHSL(),
340
+ stroke: "black",
341
+ lineWidth: 2,
342
+ y: -10,
343
+ },
344
+ },
345
+ {
346
+ name: "PieSlice",
347
+ class: PieSlice,
348
+ args: [30, 0, Math.PI * 1.5],
349
+ options: {
350
+ color: Painter.colors.randomColorHSL(),
351
+ stroke: "black",
352
+ lineWidth: 2,
353
+ y: -10,
354
+ },
355
+ },
356
+ {
357
+ name: "Arc",
358
+ class: Arc,
359
+ args: [28, 0, Math.PI * 1.5],
360
+ options: {
361
+ y: -10,
362
+ stroke: Painter.colors.randomColorHSL(),
363
+ lineWidth: 10,
364
+ },
365
+ },
366
+ {
367
+ name: "Ring",
368
+ class: Ring,
369
+ args: [30, 20],
370
+ options: {
371
+ color: Painter.colors.randomColorHSL(),
372
+ y: -10,
373
+ },
374
+ },
375
+ {
376
+ name: "Arrow",
377
+ class: Arrow,
378
+ args: [60],
379
+ options: {
380
+ width: 20,
381
+ height: 25,
382
+ color: Painter.colors.randomColorHSL(),
383
+ stroke: "black",
384
+ lineWidth: 2,
385
+ x: -5,
386
+ y: -10,
387
+ },
388
+ },
389
+ {
390
+ name: "Cross",
391
+ class: Cross,
392
+ args: [50, 10],
393
+ options: {
394
+ color: Painter.colors.randomColorHSL(),
395
+ stroke: "black",
396
+ lineWidth: 2,
397
+ y: -10,
398
+ },
399
+ },
400
+ {
401
+ name: "StickFigure",
402
+ class: StickFigure,
403
+ args: [0.5],
404
+ options: {
405
+ y: -10,
406
+ strokeColor: "#111",
407
+ headColor: Painter.colors.randomColorHSL(),
408
+ jointColor: "#111",
409
+ lineWidth: 2,
410
+ showJoints: false,
411
+ },
412
+ },
413
+ ];
414
+ // FPS Counter
415
+ this.pipeline.add(
416
+ new FPSCounter(this, { color: "black", anchor: "bottom-right" })
417
+ );
418
+ // Title
419
+ this.pipeline.add(
420
+ applyAnchor(new Text(this, "GCanvas Shape Gallery", {
421
+ font: "bold 24px monospace",
422
+ color: "#222",
423
+ }), { anchor: Position.TOP_CENTER, anchorOffsetY: 30 })
424
+ );
425
+
426
+ // Subtitle
427
+ this.pipeline.add(
428
+ applyAnchor(new Text(this, "Mouse over any shape to rotate or animate it", {
429
+ font: "16px monospace",
430
+ color: "#666",
431
+ }), { anchor: Position.TOP_CENTER, anchorOffsetY: 60 })
432
+ );
433
+ this.events.on("click", (e) => {
434
+ this.gallery.children.forEach((go) => {
435
+ go.entry.shape.color = Painter.colors.randomColorHSL();
436
+ if (
437
+ go.entry.class.name === "BezierShape" ||
438
+ go.entry.class.name == "Arc" ||
439
+ go.entry.class.name == "StickFigure"
440
+ ) {
441
+ go.entry.shape.headColor = Painter.colors.randomColorHSL();
442
+ go.entry.shape.stroke = Painter.colors.randomColorHSL();
443
+ }
444
+ if (
445
+ go.entry.name === "Sphere" ||
446
+ go.entry.name == "Cube" ||
447
+ go.entry.name === "Prism" ||
448
+ go.entry.name === "Cylinder" ||
449
+ go.entry.name === "Cone"
450
+ ) {
451
+ go.entry.shape.faceTopColor = Painter.colors.randomColorHSL();
452
+ go.entry.shape.faceBottomColor = Painter.colors.randomColorHSL();
453
+ go.entry.shape.faceLeftColor = Painter.colors.randomColorHSL();
454
+ go.entry.shape.faceRightColor = Painter.colors.randomColorHSL();
455
+ go.entry.shape.faceFrontColor = Painter.colors.randomColorHSL();
456
+ go.entry.shape.faceBackColor = Painter.colors.randomColorHSL();
457
+ go.entry.shape.topColor = Painter.colors.randomColorHSL();
458
+ go.entry.shape.bottomColor = Painter.colors.randomColorHSL();
459
+ go.entry.shape.sideColor = Painter.colors.randomColorHSL();
460
+ }
461
+ });
462
+ });
463
+ this.createGallery();
464
+ this.onResize();
465
+ }
466
+
467
+ onResize() {
468
+ if (this.gallery) {
469
+ // Calculate responsive columns based on available width
470
+ const availableWidth = this.canvas.width - CONFIG.margin;
471
+ const columns = Math.min(this.maxColumns, Math.max(1, Math.floor(availableWidth / this.cellSize)));
472
+
473
+ if (this.gallery.columns !== columns) {
474
+ this.gallery.columns = columns;
475
+ // Trigger layout update
476
+ this.gallery.markBoundsDirty();
477
+ }
478
+
479
+ // Update viewport dimensions for scrolling
480
+ const viewport = this.getViewportDimensions();
481
+ this.gallery._viewportWidth = viewport.width;
482
+ this.gallery._viewportHeight = viewport.height;
483
+
484
+ // Update anchor offset to position gallery below header
485
+ this.gallery.anchorOffsetY = CONFIG.headerHeight / 2 + 20; // Position below header with spacing
486
+
487
+ // Mark bounds dirty to trigger layout recalculation
488
+ this.gallery.markBoundsDirty();
489
+ }
490
+ }
491
+
492
+ createGallery() {
493
+ const cellSize = this.cellSize;
494
+ const initialColumns = Math.min(this.maxColumns, Math.max(1, Math.floor((this.canvas.width - CONFIG.margin) / cellSize)));
495
+ const viewport = this.getViewportDimensions();
496
+
497
+ const gallery = new TileLayout(this, {
498
+ debug: true,
499
+ debugColor: "grey",
500
+ columns: initialColumns,
501
+ spacing: 10,
502
+ // Enable scrolling with responsive viewport
503
+ scrollable: true,
504
+ viewportWidth: viewport.width,
505
+ viewportHeight: viewport.height,
506
+ // Use anchor positioning instead of manual transform.position()
507
+ anchor: Position.CENTER,
508
+ anchorOffsetY: CONFIG.headerHeight / 2 + 20, // Position below header with spacing
509
+ autoSize: true,
510
+ });
511
+
512
+ this.shapeEntries.forEach((entry, index) => {
513
+ //const col = index % cols;
514
+ //const row = Math.floor(index / cols);
515
+ //const x = originX + col * (cellSize + spacing) + cellSize / 2;
516
+ //const y = originY + row * (cellSize + spacing) + cellSize / 2;
517
+ //
518
+ const group = new Group();
519
+ // Use Transform API to set group dimensions
520
+ group.transform.size(cellSize, cellSize);
521
+ const bg = new Rectangle({
522
+ width: cellSize - 10,
523
+ height: cellSize - 10,
524
+ stroke: "rgba(0,0,0,0.1)",
525
+ lineWidth: 1,
526
+ });
527
+ const shape = new entry.class(...entry.args, entry.options);
528
+ entry.shape = shape;
529
+ const label = new TextShape(entry.name, {
530
+ x: 0,
531
+ y: (cellSize - 10) / 2 - 12,
532
+ font: "12px monospace",
533
+ color: "#333",
534
+ align: "center",
535
+ baseline: "bottom",
536
+ });
537
+ group.add(bg);
538
+ group.add(shape);
539
+ group.add(label);
540
+ //
541
+ //
542
+ const go = ShapeGOFactory.create(this, group, {
543
+ interactive: true,
544
+ name: entry.name,
545
+ width: cellSize,
546
+ height: cellSize,
547
+ scaleX: 1,
548
+ scaleY: 1,
549
+ });
550
+ go.entry = entry;
551
+ // Use Transform API for initial state
552
+ go.transform
553
+ .rotation(0)
554
+ .size(cellSize, cellSize);
555
+ go.rotationVelocity = 0;
556
+ go.startTime = 0;
557
+ go.tweening = false;
558
+ const game = this;
559
+ go.on("mouseover", () => {
560
+ // Use Transform API to reset scale
561
+ go.transform.scale(1);
562
+ game.canvas.style.cursor = "pointer";
563
+ Tweenetik.to(
564
+ group,
565
+ { scaleX: 1.3, scaleY: 1.3 },
566
+ 1, // duration
567
+ Easing.easeOutElastic,
568
+ { onComplete: () => (go.tweening = false) }
569
+ );
570
+ go.tweening = true;
571
+ });
572
+ go.on("mouseout", () => {
573
+ game.canvas.style.cursor = "default";
574
+ Tweenetik.to(
575
+ group, // the shape to scale
576
+ { scaleX: 1, scaleY: 1 },
577
+ 1, // duration
578
+ Easing.easeOutElastic
579
+ );
580
+ });
581
+ function update(dt) {
582
+ if (go.entry.name === "Hexagon") {
583
+ //console.log(go.scaleX, go.scaleY);
584
+ }
585
+ if (
586
+ go.entry.name === "Sphere" ||
587
+ go.entry.name == "Cube" ||
588
+ go.entry.name === "Prism" ||
589
+ go.entry.name === "Cylinder" ||
590
+ go.entry.name === "Cone"
591
+ ) {
592
+ const entry = go.entry;
593
+ const game = go.game;
594
+ //console.log(e);
595
+ function animate() {
596
+ if (!go.startTime) go.startTime = game.lastTime;
597
+ const elapsed = game.lastTime - go.startTime;
598
+ // Calculate rotation angles
599
+ // Calculate rotation angles (convert to radians)
600
+ const rotationSpeed = 0.001;
601
+ const xRotation = (Math.sin(elapsed * 0.0005) * Math.PI) / 4;
602
+ const yRotation =
603
+ (elapsed * rotationSpeed * 0.0005) % (Math.PI * 2);
604
+ const zRotation = (Math.cos(elapsed * 0.0003) * Math.PI) / 6;
605
+
606
+ // Apply rotations
607
+ entry.shape.setRotation(xRotation, yRotation, zRotation);
608
+ }
609
+ animate();
610
+ }
611
+ }
612
+ gallery.add(go);
613
+ go.onUpdate = update;
614
+ });
615
+ this.gallery = gallery;
616
+ this.pipeline.add(this.gallery);
617
+ }
618
+ }
619
+
620
+ window.addEventListener("load", () => {
621
+ const canvas = document.getElementById("game");
622
+ const game = new ShapeGalleryGame(canvas);
623
+ game.setFPS(60);
624
+ game.enablePauseOnBlur(true);
625
+ //game.enableLogging();
626
+ game.start();
627
+ //setTimeout(game.stop.bind(game), 10000);
628
+ });