Skip to content

Commit 6dbb31e

Browse files
committed
Add new test case
1 parent 7834049 commit 6dbb31e

File tree

4 files changed

+343
-37
lines changed

4 files changed

+343
-37
lines changed

docs/docs/prompts/shape-spinner-custom.md

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,3 +309,96 @@ new Phaser.Game(config);
309309
* **Rotating box**: first half fill; second half `rotateAround(cx, cy, angle)`.
310310

311311
> This document provides **all authority information GPT needs**—no external files required.
312+
313+
---
314+
315+
## 10) Build a Live Demo (drop-in `.html` that runs immediately)
316+
317+
> **Goal**: In addition to `Add<SpinnerName>Spinner(...)` and the minimal scene, include a **complete HTML file** in the reply. Save as `demo.html` and open in a browser to see the spinner.
318+
319+
**Rules (bake these into your reply template):**
320+
321+
1. Load Phaser 3 from the official CDN.
322+
2. In `preload()`, load the rexSpinner scene plugin using `this.load.scenePlugin(...)` (GitHub raw URL).
323+
3. In `create()`, call the just-generated `Add<SpinnerName>Spinner(...)`.
324+
4. Emit the HTML below and replace the `<Add...>` call, its parameters, and colors to match the user’s request.
325+
326+
**HTML template (runnable as-is):**
327+
328+
```html
329+
<!DOCTYPE html>
330+
<html lang="en">
331+
<head>
332+
<meta charset="UTF-8" />
333+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
334+
<title>Custom Spinner Live Demo</title>
335+
<style>
336+
html, body { height: 100%; margin: 0; background:#222; }
337+
#game-root { width: 100%; height: 100%; }
338+
</style>
339+
<!-- Phaser CDN -->
340+
<script src="https://cdn.jsdelivr.net/npm/phaser@3/dist/phaser.js"></script>
341+
</head>
342+
<body>
343+
<div id="game-root"></div>
344+
<script>
345+
class Demo extends Phaser.Scene {
346+
constructor(){ super('demo'); }
347+
preload(){
348+
this.load.scenePlugin({
349+
key: 'rexspinnerplugin',
350+
url: 'https://raw.githubusercontent.com/rexrainbow/phaser3-rex-notes/master/dist/rexspinnerplugin.min.js',
351+
sceneKey: 'rexSpinner'
352+
});
353+
}
354+
create(){
355+
// Call the spinner function you generated in your reply:
356+
AddOrbitDotsSpinner(this, 400, 300, 120, 120, {
357+
count: 10, thickness: 0.15, ring: 0.78, duration: 900
358+
});
359+
}
360+
}
361+
362+
// === Example spinner definition (replace/extend with the user-specific spinner you produce) ===
363+
function AddOrbitDotsSpinner(scene, x, y, width, height, options = {}) {
364+
const { count = 12, thickness = 0.12, ring = 0.8, duration = 1000, start = true } = options;
365+
return scene.rexSpinner.add.custom({
366+
x, y, width, height, duration, start,
367+
create: { circle: Array.from({ length: count }, (_, i) => `dot${i}`) },
368+
update: function () {
369+
const cx = this.centerX, cy = this.centerY, R = this.radius;
370+
const t = this.value; // 0..1
371+
const shapes = this.getShapes();
372+
const angleStep = 360 / count;
373+
const ringR = R * ring;
374+
const dotR = R * thickness;
375+
for (let i = 0; i < count; i++) {
376+
const phase = (i / count + t) % 1;
377+
const deg = i * angleStep + phase * 360;
378+
const rad = Phaser.Math.DEG_TO_RAD * deg;
379+
const x = cx + ringR * Math.cos(rad);
380+
const y = cy + ringR * Math.sin(rad);
381+
const s = shapes[i];
382+
const alpha = Phaser.Math.Linear(0.35, 1, 1 - phase);
383+
s.setCenterPosition(x, y).setRadius(dotR, dotR).fillStyle(this.color, alpha);
384+
}
385+
}
386+
});
387+
}
388+
389+
const config = {
390+
type: Phaser.AUTO,
391+
parent: 'game-root',
392+
width: 800,
393+
height: 600,
394+
backgroundColor: '#222222',
395+
scale: { mode: Phaser.Scale.FIT, autoCenter: Phaser.Scale.CENTER_BOTH },
396+
scene: Demo,
397+
};
398+
new Phaser.Game(config);
399+
</script>
400+
</body>
401+
</html>
402+
```
403+
404+
> When delivering, replace the `AddOrbitDotsSpinner(...)` call and the function body above with the spinner you generated for the user, and the demo will run instantly.

examples/spinner/custom-explode-ring.js

Lines changed: 55 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,23 @@ class Demo extends Phaser.Scene {
1111
preload() { }
1212

1313
create() {
14-
var spinner = AddExplodeBlobSpinner(this, 400, 300, 260, 260, {
14+
var spinner = AddDualBlobSpinner(this, 400, 300, 280, 280, {
1515
count: 64,
1616
base: 0.2,
1717
amp: 0.7,
1818
jitter: 0.8,
19+
innerMin: 0.60,
20+
innerMax: 0.85,
21+
1922
duration: 1100,
20-
stroke: true,
21-
strokeWidth: 1.5,
23+
strokeWidth: 0,
24+
25+
color: 0x4dabf7,
26+
innerColor: 0xffe066,
27+
2228
start: true
2329
});
30+
2431
var graphics = this.add.graphics({
2532
lineStyle: {
2633
width: 2, color: 0xff0000, alpha: 1
@@ -33,15 +40,18 @@ class Demo extends Phaser.Scene {
3340
update() { }
3441
}
3542

36-
function AddExplodeBlobSpinner(scene, x, y, width, height, options = {}) {
43+
function AddDualBlobSpinner(scene, x, y, width, height, options = {}) {
3744
const {
3845
count = 64,
3946
base = 0.55,
4047
amp = 0.35,
4148
jitter = 0.25,
49+
innerMin = 0.55,
50+
innerMax = 0.85,
4251
duration = 1000,
43-
stroke = true,
44-
strokeWidth = 1,
52+
strokeWidth = 0,
53+
innerColor = 0xffffff,
54+
color = 0x33aaff,
4555
start = true
4656
} = options;
4757

@@ -50,63 +60,71 @@ function AddExplodeBlobSpinner(scene, x, y, width, height, options = {}) {
5060

5161
return scene.rexSpinner.add.custom({
5262
x, y, width, height, duration, start,
63+
color,
5364

54-
create: { lines: ['rim'] },
65+
create: { lines: ['outer', 'inner'] },
5566

5667
update: function () {
5768
const cx = this.centerX, cy = this.centerY, R = this.radius;
58-
const t = this.value; // 0..1
69+
const t = this.value;
5970
const step = 360 / count;
6071
const rBase = R * base;
6172
const rAmp = R * amp;
6273

63-
const path = this.getShape('rim');
74+
const outer = this.getShape('outer');
75+
const inner = this.getShape('inner');
6476

65-
let prevT = path.getData('_prevT', 1);
66-
let targets = path.getData('targets', null);
77+
let prevT = outer.getData('_prevT', 1);
78+
let targets = outer.getData('targets', null);
79+
let scales = outer.getData('scales', null);
6780

68-
if (t < prevT || !targets) {
69-
if (!targets) {
70-
targets = new Array(count);
71-
path.setData('targets', targets);
72-
}
81+
if (t < prevT || !targets || !scales) {
82+
if (!targets) { targets = new Array(count); outer.setData('targets', targets); }
83+
if (!scales) { scales = new Array(count); outer.setData('scales', scales); }
7384
for (let i = 0; i < count; i++) {
7485
targets[i] = clamp01(1 - jitter + rand(0, jitter * 2));
86+
scales[i] = rand(innerMin, innerMax);
7587
}
7688
}
77-
path.setData('_prevT', t);
89+
outer.setData('_prevT', t);
7890

7991
let k;
80-
if (t < 0.5) {
81-
const u = t * 2;
82-
k = 1 - Math.pow(1 - u, 3);
83-
} else {
84-
const u = (t - 0.5) * 2;
85-
k = 1 - u * u * u;
86-
}
92+
if (t < 0.5) { const u = t * 2; k = 1 - Math.pow(1 - u, 3); }
93+
else { const u = (t - 0.5) * 2; k = 1 - u * u * u; }
94+
95+
let fx = 0, fy = 0, gfx = 0, gfy = 0;
8796

88-
let firstX = 0, firstY = 0;
8997
for (let i = 0; i < count; i++) {
90-
const deg = i * step;
98+
const deg = i * (360 / count);
9199
const rad = deg * (Math.PI / 180);
92-
const rNow = rBase + rAmp * k * targets[i];
93-
const x = cx + rNow * Math.cos(rad);
94-
const y = cy + rNow * Math.sin(rad);
100+
101+
const rOuter = rBase + rAmp * k * targets[i];
102+
const rInner = rOuter * scales[i];
103+
104+
const xo = cx + rOuter * Math.cos(rad);
105+
const yo = cy + rOuter * Math.sin(rad);
106+
const xi = cx + rInner * Math.cos(rad);
107+
const yi = cy + rInner * Math.sin(rad);
95108

96109
if (i === 0) {
97-
path.startAt(x, y);
98-
firstX = x; firstY = y;
110+
outer.startAt(xo, yo); inner.startAt(xi, yi);
111+
fx = xo; fy = yo; gfx = xi; gfy = yi;
99112
} else {
100-
path.lineTo(x, y);
113+
outer.lineTo(xo, yo); inner.lineTo(xi, yi);
101114
}
102115
}
103-
path.lineTo(firstX, firstY).close();
104116

105-
path.fillStyle(this.color, 1);
106-
if (stroke) {
107-
path.lineStyle(strokeWidth, this.color, 1);
117+
outer.lineTo(fx, fy).close();
118+
inner.lineTo(gfx, gfy).close();
119+
120+
outer.fillStyle(this.color, 1);
121+
inner.fillStyle(innerColor, 1);
122+
123+
if (strokeWidth > 0) {
124+
outer.lineStyle(strokeWidth, this.color, 1);
125+
inner.lineStyle(strokeWidth, innerColor, 1);
108126
} else {
109-
path.lineStyle();
127+
outer.lineStyle(); inner.lineStyle();
110128
}
111129
}
112130
});

examples/spinner/custom-snake.bat

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
set main=./examples/spinner/custom-snake.js
2+
cd ..
3+
cd ..
4+
npm run dev

0 commit comments

Comments
 (0)