star-sdk-cli 0.1.21 → 0.1.23
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/dist/cli.mjs +45 -135
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -685,39 +685,34 @@ if (state === 'menu' || state === 'gameover') canvas.style.cursor = 'auto'; //
|
|
|
685
685
|
|
|
686
686
|
**Decision:** Does player click on game objects? \u2192 \`'pointer'\` | Aim precisely? \u2192 \`'crosshair'\` | WASD/touch only? \u2192 \`'none'\` during play, \`'auto'\` for menus
|
|
687
687
|
|
|
688
|
-
###
|
|
688
|
+
### Drag and Drop (Polling Pattern)
|
|
689
689
|
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
- **USE THIS** for all canvas pointer input.
|
|
693
|
-
|
|
694
|
-
### \`createDrag()\`
|
|
695
|
-
|
|
696
|
-
Creates a drag state helper that handles coordinate conversion and offset tracking automatically.
|
|
690
|
+
Use \`g.tap\`, \`g.pointer\`, and \`g.released\` for drag-and-drop \u2014 coordinates are automatic.
|
|
697
691
|
|
|
698
692
|
\`\`\`ts
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
canvas.addEventListener('pointerdown', (e) => {
|
|
702
|
-
canvas.setPointerCapture(e.pointerId); // IMPORTANT: Capture for reliable drags
|
|
703
|
-
const { x, y } = drag.point(e); // Convert coordinates
|
|
704
|
-
const hit = pieces.find(p => /* hit test */);
|
|
705
|
-
if (hit) drag.grab(e, hit); // Start drag with offset
|
|
706
|
-
});
|
|
693
|
+
let dragging = null;
|
|
694
|
+
let offsetX = 0, offsetY = 0;
|
|
707
695
|
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
696
|
+
g.loop((dt) => {
|
|
697
|
+
if (g.tap) {
|
|
698
|
+
const hit = pieces.find(p => inRect(g.tap, p));
|
|
699
|
+
if (hit) {
|
|
700
|
+
dragging = hit;
|
|
701
|
+
offsetX = hit.x - g.tap.x; // Offset so piece doesn't jump to cursor
|
|
702
|
+
offsetY = hit.y - g.tap.y;
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
if (dragging && g.pointer.down) {
|
|
706
|
+
dragging.x = g.pointer.x + offsetX;
|
|
707
|
+
dragging.y = g.pointer.y + offsetY;
|
|
708
|
+
}
|
|
709
|
+
if (g.released && dragging) {
|
|
710
|
+
handleDrop(dragging);
|
|
711
|
+
dragging = null;
|
|
712
|
+
}
|
|
711
713
|
});
|
|
712
714
|
\`\`\`
|
|
713
715
|
|
|
714
|
-
**API:**
|
|
715
|
-
- \`point(e)\` - Pure coordinate conversion, no side effects
|
|
716
|
-
- \`grab(e, obj)\` - Start dragging an object, computing offset from cursor
|
|
717
|
-
- \`move(e)\` - Update dragged object's position
|
|
718
|
-
- \`release()\` - End drag, returns dropped object or null
|
|
719
|
-
- \`dragging\` - The currently dragged object (or null)
|
|
720
|
-
|
|
721
716
|
### \`GameOptions\` (optional)
|
|
722
717
|
|
|
723
718
|
Pass an options object as the second argument to \`game()\`:
|
|
@@ -991,15 +986,15 @@ game(({ ctx, scoped, loop }) => {
|
|
|
991
986
|
|
|
992
987
|
**Why use \`scoped()\`:** Prevents transform stack corruption from early returns, exceptions, or forgetting \`ctx.restore()\`. The context is always restored, even if the function exits early.
|
|
993
988
|
|
|
994
|
-
### Recipe 7: Drag and Drop
|
|
989
|
+
### Recipe 7: Drag and Drop
|
|
995
990
|
|
|
996
|
-
Use
|
|
991
|
+
Use \`g.tap\`, \`g.pointer\`, and \`g.released\` for drag-and-drop. Coordinates are canvas-space automatically.
|
|
997
992
|
|
|
998
993
|
\`\`\`ts
|
|
999
994
|
import { game } from 'star-canvas';
|
|
1000
995
|
|
|
1001
|
-
game((
|
|
1002
|
-
|
|
996
|
+
game((g) => {
|
|
997
|
+
const { ctx, width, height } = g;
|
|
1003
998
|
const pieceSize = height * 0.15;
|
|
1004
999
|
|
|
1005
1000
|
const pieces = [
|
|
@@ -1008,77 +1003,8 @@ game(({ ctx, width, height, loop, canvas, createDrag }) => {
|
|
|
1008
1003
|
{ x: width * 0.6, y: height * 0.3, color: '#3b82f6' },
|
|
1009
1004
|
];
|
|
1010
1005
|
|
|
1011
|
-
// Create drag helper - handles coordinate conversion automatically
|
|
1012
|
-
const drag = createDrag();
|
|
1013
|
-
|
|
1014
|
-
function hitTest(x, y) {
|
|
1015
|
-
for (let i = pieces.length - 1; i >= 0; i--) {
|
|
1016
|
-
const p = pieces[i];
|
|
1017
|
-
if (x >= p.x && x < p.x + pieceSize && y >= p.y && y < p.y + pieceSize) {
|
|
1018
|
-
return p;
|
|
1019
|
-
}
|
|
1020
|
-
}
|
|
1021
|
-
return null;
|
|
1022
|
-
}
|
|
1023
|
-
|
|
1024
|
-
canvas.addEventListener('pointerdown', (e) => {
|
|
1025
|
-
canvas.setPointerCapture(e.pointerId); // IMPORTANT: Ensures drag works outside canvas
|
|
1026
|
-
const { x, y } = drag.point(e); // Convert coordinates
|
|
1027
|
-
const hit = hitTest(x, y);
|
|
1028
|
-
if (hit) {
|
|
1029
|
-
drag.grab(e, hit); // Start drag with offset from cursor
|
|
1030
|
-
canvas.style.cursor = 'grabbing';
|
|
1031
|
-
}
|
|
1032
|
-
});
|
|
1033
|
-
|
|
1034
|
-
canvas.addEventListener('pointermove', (e) => {
|
|
1035
|
-
drag.move(e); // Updates grabbed object position
|
|
1036
|
-
if (!drag.dragging) {
|
|
1037
|
-
const { x, y } = drag.point(e);
|
|
1038
|
-
canvas.style.cursor = hitTest(x, y) ? 'grab' : 'default';
|
|
1039
|
-
}
|
|
1040
|
-
});
|
|
1041
|
-
|
|
1042
|
-
canvas.addEventListener('pointerup', () => {
|
|
1043
|
-
const dropped = drag.release(); // Returns dropped object (or null)
|
|
1044
|
-
if (dropped) {
|
|
1045
|
-
console.log('Dropped:', dropped);
|
|
1046
|
-
}
|
|
1047
|
-
canvas.style.cursor = 'default';
|
|
1048
|
-
});
|
|
1049
|
-
|
|
1050
|
-
loop(() => {
|
|
1051
|
-
ctx.fillStyle = '#1f2937';
|
|
1052
|
-
ctx.fillRect(0, 0, width, height);
|
|
1053
|
-
|
|
1054
|
-
for (const p of pieces) {
|
|
1055
|
-
ctx.fillStyle = drag.dragging === p ? '#f59e0b' : p.color;
|
|
1056
|
-
ctx.fillRect(p.x, p.y, pieceSize, pieceSize);
|
|
1057
|
-
}
|
|
1058
|
-
});
|
|
1059
|
-
});
|
|
1060
|
-
\`\`\`
|
|
1061
|
-
|
|
1062
|
-
**CRITICAL: Always use \`setPointerCapture()\`** - This ensures drags work even when the pointer moves outside the canvas. Without it, fast drags can leave objects stuck mid-drag.
|
|
1063
|
-
|
|
1064
|
-
### Recipe 8: Drag and Drop (Manual Pattern)
|
|
1065
|
-
|
|
1066
|
-
If you need more control, here's the manual approach with \`toStagePoint()\`.
|
|
1067
|
-
|
|
1068
|
-
\`\`\`ts
|
|
1069
|
-
import { game } from 'star-canvas';
|
|
1070
|
-
|
|
1071
|
-
game(({ ctx, width, height, loop, canvas, toStagePoint }) => {
|
|
1072
|
-
const pieceSize = height * 0.15;
|
|
1073
|
-
const pieces = [
|
|
1074
|
-
{ x: width * 0.2, y: height * 0.3, color: '#ef4444' },
|
|
1075
|
-
{ x: width * 0.4, y: height * 0.4, color: '#10b981' },
|
|
1076
|
-
];
|
|
1077
|
-
|
|
1078
|
-
// Manual drag state
|
|
1079
1006
|
let dragging = null;
|
|
1080
|
-
let
|
|
1081
|
-
let dragOffsetY = 0;
|
|
1007
|
+
let offsetX = 0, offsetY = 0;
|
|
1082
1008
|
|
|
1083
1009
|
function hitTest(px, py) {
|
|
1084
1010
|
for (let i = pieces.length - 1; i >= 0; i--) {
|
|
@@ -1090,34 +1016,28 @@ game(({ ctx, width, height, loop, canvas, toStagePoint }) => {
|
|
|
1090
1016
|
return null;
|
|
1091
1017
|
}
|
|
1092
1018
|
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1019
|
+
g.loop(() => {
|
|
1020
|
+
// Grab
|
|
1021
|
+
if (g.tap) {
|
|
1022
|
+
const hit = hitTest(g.tap.x, g.tap.y);
|
|
1023
|
+
if (hit) {
|
|
1024
|
+
dragging = hit;
|
|
1025
|
+
offsetX = hit.x - g.tap.x; // Offset so piece doesn't jump to cursor
|
|
1026
|
+
offsetY = hit.y - g.tap.y;
|
|
1027
|
+
}
|
|
1102
1028
|
}
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1029
|
+
// Move
|
|
1030
|
+
if (dragging && g.pointer.down) {
|
|
1031
|
+
dragging.x = g.pointer.x + offsetX;
|
|
1032
|
+
dragging.y = g.pointer.y + offsetY;
|
|
1033
|
+
}
|
|
1034
|
+
// Drop
|
|
1035
|
+
if (g.released && dragging) {
|
|
1036
|
+
console.log('Dropped:', dragging);
|
|
1037
|
+
dragging = null;
|
|
1112
1038
|
}
|
|
1113
|
-
});
|
|
1114
|
-
|
|
1115
|
-
canvas.addEventListener('pointerup', () => {
|
|
1116
|
-
dragging = null;
|
|
1117
|
-
canvas.style.cursor = 'default';
|
|
1118
|
-
});
|
|
1119
1039
|
|
|
1120
|
-
|
|
1040
|
+
// Draw
|
|
1121
1041
|
ctx.fillStyle = '#1f2937';
|
|
1122
1042
|
ctx.fillRect(0, 0, width, height);
|
|
1123
1043
|
|
|
@@ -1129,16 +1049,6 @@ game(({ ctx, width, height, loop, canvas, toStagePoint }) => {
|
|
|
1129
1049
|
});
|
|
1130
1050
|
\`\`\`
|
|
1131
1051
|
|
|
1132
|
-
**Common Drag-Drop Mistakes:**
|
|
1133
|
-
|
|
1134
|
-
1. \u274C Forgetting \`toStagePoint()\` in pointermove \u2192 \`createDrag()\` fixes this
|
|
1135
|
-
2. \u274C No drag offset (piece "jumps" to cursor) \u2192 \`createDrag()\` fixes this
|
|
1136
|
-
3. \u274C Using \`e.clientX/clientY\` directly \u2192 \`createDrag()\` fixes this
|
|
1137
|
-
4. \u274C Not clearing state on pointerup \u2192 \`createDrag()\` fixes this
|
|
1138
|
-
5. \u274C Missing \`setPointerCapture()\` (drags break outside canvas) \u2192 **You must add this!**
|
|
1139
|
-
|
|
1140
|
-
**Recommendation:** Use \`createDrag()\` + \`setPointerCapture()\` for bulletproof drag-and-drop.
|
|
1141
|
-
|
|
1142
1052
|
### Recipe 9: Image Backgrounds
|
|
1143
1053
|
|
|
1144
1054
|
Two patterns for backgrounds: **full-canvas** (unique scenes) or **tileable patterns** (repeating textures).
|