@looop-games/cli 0.1.8 → 0.1.9

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.
@@ -1,21 +0,0 @@
1
- // Boot smoke — the game's first regression test, shipped with the scaffold.
2
- // Proves the dev stack serves the game page AND the engine alias (a plain
3
- // static server would 404 every /shared/... import and the game would
4
- // silently never boot). Runs under `npx looop test`, which boots a real dev
5
- // stack and exports its URL. Grow your own checks as `<aspect>.smoke.mjs`
6
- // files next to this one.
7
- const url = process.env.LOOOP_TEST_GAME_URL || process.env.URL;
8
- if (!url) {
9
- console.error('boot smoke: no game URL — run this via `npx looop test`.');
10
- process.exit(1);
11
- }
12
-
13
- const page = await fetch(url);
14
- if (!page.ok) throw new Error(`game page: ${page.status} for ${url}`);
15
- if (!(await page.text()).includes('<canvas')) throw new Error('game page served, but no canvas in it');
16
-
17
- const engineModule = new URL('/shared/ui/room/client.js', url);
18
- const engine = await fetch(engineModule);
19
- if (!engine.ok) throw new Error(`engine alias broken: ${engineModule.pathname} → ${engine.status}`);
20
-
21
- console.log('boot smoke: game page + engine alias OK');
package/template/game.js DELETED
@@ -1,53 +0,0 @@
1
- // A tiny multiplayer plaza — walk around, see everyone else.
2
- // This is a REAL Looop game: it already syncs across browsers and works
3
- // published. Reshape it into your game; the room + identity plumbing stays.
4
- import { createRoom, getIdentity } from '/shared/ui/room/client.js';
5
-
6
- const me = getIdentity(); // injected by the platform (fails closed if absent)
7
- const canvas = document.getElementById('game');
8
- const ctx = canvas.getContext('2d');
9
- const size = () => { canvas.width = innerWidth; canvas.height = innerHeight; };
10
- addEventListener('resize', size); size();
11
-
12
- const self = { name: me.name, color: me.color, x: Math.random() * 400 - 200, y: Math.random() * 400 - 200 };
13
- // One room per game: the slug (injected by the serve path) is the room id.
14
- const room = createRoom({ room: window.GAME_SLUG ?? 'dev', self });
15
-
16
- let others = new Map();
17
- room.onPlayers = (players) => { others = new Map(players); };
18
- // Handy for smokes: how many players does this client see (self included)?
19
- window.__looopPlayers = () => others.size + 1;
20
-
21
- const keys = new Set();
22
- addEventListener('keydown', (e) => keys.add(e.key.toLowerCase()));
23
- addEventListener('keyup', (e) => keys.delete(e.key.toLowerCase()));
24
-
25
- const SPEED = 220; // px/s — tune the feel!
26
- let last = performance.now();
27
- function tick(now) {
28
- const dt = Math.min((now - last) / 1000, 0.05); last = now;
29
- const dx = (keys.has('d') || keys.has('arrowright')) - (keys.has('a') || keys.has('arrowleft'));
30
- const dy = (keys.has('s') || keys.has('arrowdown')) - (keys.has('w') || keys.has('arrowup'));
31
- if (dx || dy) {
32
- const n = Math.hypot(dx, dy);
33
- self.x += (dx / n) * SPEED * dt;
34
- self.y += (dy / n) * SPEED * dt;
35
- room.update({ x: self.x, y: self.y });
36
- }
37
-
38
- ctx.fillStyle = '#0f1220';
39
- ctx.fillRect(0, 0, canvas.width, canvas.height);
40
- const cx = canvas.width / 2, cy = canvas.height / 2;
41
- const drawAvatar = (p) => {
42
- ctx.fillStyle = p.color ?? '#888';
43
- ctx.fillRect(cx + (p.x ?? 0) - self.x - 14, cy + (p.y ?? 0) - self.y - 14, 28, 28);
44
- ctx.fillStyle = '#e7e9f4';
45
- ctx.font = '12px system-ui';
46
- ctx.textAlign = 'center';
47
- ctx.fillText(p.name ?? '?', cx + (p.x ?? 0) - self.x, cy + (p.y ?? 0) - self.y - 22);
48
- };
49
- for (const p of others.values()) drawAvatar(p);
50
- drawAvatar(self);
51
- requestAnimationFrame(tick);
52
- }
53
- requestAnimationFrame(tick);
@@ -1,2 +0,0 @@
1
- node_modules/
2
- .looop/
@@ -1,8 +0,0 @@
1
- # Design — the pillars
2
-
3
- The rules that follow from the vision: the principles new ideas get checked
4
- against. Written as
5
- they emerge from real decisions (via `/handbook`), not invented up
6
- front — an empty file is honest; a speculative pillar is a trap.
7
-
8
- _No pillars yet._
@@ -1,8 +0,0 @@
1
- # Feel — locked values
2
-
3
- Feel calls the creator has blessed: the value, where it lives, and why it's
4
- right — so no future session "improves" them away. General feel craft lives in
5
- the engine's `shared/practices/feel.md`; this file is only what THIS game has
6
- locked. `/handbook` adds entries.
7
-
8
- _Nothing locked yet._
@@ -1,9 +0,0 @@
1
- # QA — this game's own checks
2
-
3
- Checks THIS game has earned, on top of the engine's master list
4
- (`node_modules/@looop-games/engine/shared/practices/qa.md`) and the executable
5
- tests `npx looop test` discovers. `/qa` runs all three sources; `/handbook`
6
- adds entries here when a playtest catches something no automated check saw —
7
- but prefer writing a `*.smoke.mjs` when the check can be executed.
8
-
9
- _No game-specific checks yet. The first playtest catch starts this list._
@@ -1,26 +0,0 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8">
5
- <!-- Mobile baseline (engine practices, architecture.md): locked viewport,
6
- no double-tap/pinch zoom, no text selection on game UI. Required on
7
- every Looop game — keep all four pieces when reshaping this file. -->
8
- <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
9
- <title>{{name}}</title>
10
- <style>
11
- html, body { margin: 0; height: 100%; background: #0f1220; overflow: hidden; touch-action: manipulation; }
12
- * { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; -webkit-tap-highlight-color: transparent; }
13
- input, textarea, [contenteditable] { -webkit-user-select: text; user-select: text; }
14
- canvas { display: block; width: 100vw; height: 100vh; }
15
- </style>
16
- <script>
17
- // Safari ignores user-scalable=no — block iOS gesture-zoom too.
18
- for (const ev of ['gesturestart', 'gesturechange', 'gestureend'])
19
- document.addEventListener(ev, (e) => e.preventDefault());
20
- </script>
21
- </head>
22
- <body>
23
- <canvas id="game"></canvas>
24
- <script type="module" src="game.js"></script>
25
- </body>
26
- </html>