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.
Files changed (2) hide show
  1. package/dist/cli.mjs +45 -135
  2. 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
- ### \`toStagePoint(event)\`
688
+ ### Drag and Drop (Polling Pattern)
689
689
 
690
- Converts \`MouseEvent\` or \`PointerEvent\` client coordinates to the stage's logical coordinates.
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
- const drag = createDrag();
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
- canvas.addEventListener('pointermove', (e) => drag.move(e)); // Updates position
709
- canvas.addEventListener('pointerup', () => {
710
- const dropped = drag.release(); // Returns dropped object (or null)
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 with createDrag() (RECOMMENDED)
989
+ ### Recipe 7: Drag and Drop
995
990
 
996
- Use the \`createDrag()\` helper - it handles coordinate conversion and offset tracking automatically.
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(({ ctx, width, height, loop, canvas, createDrag }) => {
1002
- // Size relative to height for consistency
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 dragOffsetX = 0;
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
- canvas.addEventListener('pointerdown', (e) => {
1094
- canvas.setPointerCapture(e.pointerId); // Ensures drag works outside canvas
1095
- const { x, y } = toStagePoint(e); // CRITICAL: Convert coordinates!
1096
- const hit = hitTest(x, y);
1097
- if (hit) {
1098
- dragging = hit;
1099
- dragOffsetX = x - hit.x; // Store offset
1100
- dragOffsetY = y - hit.y;
1101
- canvas.style.cursor = 'grabbing';
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
- canvas.addEventListener('pointermove', (e) => {
1106
- const { x, y } = toStagePoint(e); // CRITICAL: Convert here too!
1107
- if (dragging) {
1108
- dragging.x = x - dragOffsetX;
1109
- dragging.y = y - dragOffsetY;
1110
- } else {
1111
- canvas.style.cursor = hitTest(x, y) ? 'grab' : 'default';
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
- loop(() => {
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).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "star-sdk-cli",
3
- "version": "0.1.21",
3
+ "version": "0.1.23",
4
4
  "description": "CLI for Star SDK — register games, install AI docs, and deploy to Star hosting",
5
5
  "type": "module",
6
6
  "bin": {