diff --git a/assets/images/starcontrol/sc-ship-androsynth.png b/assets/images/starcontrol/sc-ship-androsynth.png index 8688716..147012a 100644 Binary files a/assets/images/starcontrol/sc-ship-androsynth.png and b/assets/images/starcontrol/sc-ship-androsynth.png differ diff --git a/assets/images/starcontrol/sc-ship-arilou.png b/assets/images/starcontrol/sc-ship-arilou.png index 1792924..7ce2550 100644 Binary files a/assets/images/starcontrol/sc-ship-arilou.png and b/assets/images/starcontrol/sc-ship-arilou.png differ diff --git a/assets/images/starcontrol/sc-ship-chenjesu.png b/assets/images/starcontrol/sc-ship-chenjesu.png index 4a143d0..771c984 100644 Binary files a/assets/images/starcontrol/sc-ship-chenjesu.png and b/assets/images/starcontrol/sc-ship-chenjesu.png differ diff --git a/assets/images/starcontrol/sc-ship-chmmr.png b/assets/images/starcontrol/sc-ship-chmmr.png index 09b9e95..809f625 100644 Binary files a/assets/images/starcontrol/sc-ship-chmmr.png and b/assets/images/starcontrol/sc-ship-chmmr.png differ diff --git a/assets/images/starcontrol/sc-ship-druuge.png b/assets/images/starcontrol/sc-ship-druuge.png index 4b8a429..c4460b3 100644 Binary files a/assets/images/starcontrol/sc-ship-druuge.png and b/assets/images/starcontrol/sc-ship-druuge.png differ diff --git a/assets/images/starcontrol/sc-ship-earthling.png b/assets/images/starcontrol/sc-ship-earthling.png index 89ae26b..880cb90 100644 Binary files a/assets/images/starcontrol/sc-ship-earthling.png and b/assets/images/starcontrol/sc-ship-earthling.png differ diff --git a/assets/images/starcontrol/sc-ship-ilwrath.png b/assets/images/starcontrol/sc-ship-ilwrath.png index 236fa02..37224e5 100644 Binary files a/assets/images/starcontrol/sc-ship-ilwrath.png and b/assets/images/starcontrol/sc-ship-ilwrath.png differ diff --git a/assets/images/starcontrol/sc-ship-kohrah.png b/assets/images/starcontrol/sc-ship-kohrah.png index e5f2efb..ff5de44 100644 Binary files a/assets/images/starcontrol/sc-ship-kohrah.png and b/assets/images/starcontrol/sc-ship-kohrah.png differ diff --git a/assets/images/starcontrol/sc-ship-melnorme.png b/assets/images/starcontrol/sc-ship-melnorme.png index 6fad9e4..8b4ec26 100644 Binary files a/assets/images/starcontrol/sc-ship-melnorme.png and b/assets/images/starcontrol/sc-ship-melnorme.png differ diff --git a/assets/images/starcontrol/sc-ship-mmrnmhrm-y.png b/assets/images/starcontrol/sc-ship-mmrnmhrm-y.png index 75eb325..d6c90ca 100644 Binary files a/assets/images/starcontrol/sc-ship-mmrnmhrm-y.png and b/assets/images/starcontrol/sc-ship-mmrnmhrm-y.png differ diff --git a/assets/images/starcontrol/sc-ship-mmrnmhrm.png b/assets/images/starcontrol/sc-ship-mmrnmhrm.png index 5968e79..9dc4a64 100644 Binary files a/assets/images/starcontrol/sc-ship-mmrnmhrm.png and b/assets/images/starcontrol/sc-ship-mmrnmhrm.png differ diff --git a/assets/images/starcontrol/sc-ship-mycon.png b/assets/images/starcontrol/sc-ship-mycon.png index 6f8e827..d1022e4 100644 Binary files a/assets/images/starcontrol/sc-ship-mycon.png and b/assets/images/starcontrol/sc-ship-mycon.png differ diff --git a/assets/images/starcontrol/sc-ship-orz.png b/assets/images/starcontrol/sc-ship-orz.png index b0ed1b2..bc68de2 100644 Binary files a/assets/images/starcontrol/sc-ship-orz.png and b/assets/images/starcontrol/sc-ship-orz.png differ diff --git a/assets/images/starcontrol/sc-ship-pkunk.png b/assets/images/starcontrol/sc-ship-pkunk.png index 6c51e47..b59d8f7 100644 Binary files a/assets/images/starcontrol/sc-ship-pkunk.png and b/assets/images/starcontrol/sc-ship-pkunk.png differ diff --git a/assets/images/starcontrol/sc-ship-shofixti.png b/assets/images/starcontrol/sc-ship-shofixti.png index 609727a..e36d9e2 100644 Binary files a/assets/images/starcontrol/sc-ship-shofixti.png and b/assets/images/starcontrol/sc-ship-shofixti.png differ diff --git a/assets/images/starcontrol/sc-ship-slylandro.png b/assets/images/starcontrol/sc-ship-slylandro.png index 320e59c..6ead2dd 100644 Binary files a/assets/images/starcontrol/sc-ship-slylandro.png and b/assets/images/starcontrol/sc-ship-slylandro.png differ diff --git a/assets/images/starcontrol/sc-ship-spathi.png b/assets/images/starcontrol/sc-ship-spathi.png index bd13f00..8da0e71 100644 Binary files a/assets/images/starcontrol/sc-ship-spathi.png and b/assets/images/starcontrol/sc-ship-spathi.png differ diff --git a/assets/images/starcontrol/sc-ship-supox.png b/assets/images/starcontrol/sc-ship-supox.png index 0da9ad1..c91475b 100644 Binary files a/assets/images/starcontrol/sc-ship-supox.png and b/assets/images/starcontrol/sc-ship-supox.png differ diff --git a/assets/images/starcontrol/sc-ship-syreen.png b/assets/images/starcontrol/sc-ship-syreen.png index 1c743af..964c51c 100644 Binary files a/assets/images/starcontrol/sc-ship-syreen.png and b/assets/images/starcontrol/sc-ship-syreen.png differ diff --git a/assets/images/starcontrol/sc-ship-thraddash.png b/assets/images/starcontrol/sc-ship-thraddash.png index 28b5870..fd8d519 100644 Binary files a/assets/images/starcontrol/sc-ship-thraddash.png and b/assets/images/starcontrol/sc-ship-thraddash.png differ diff --git a/assets/images/starcontrol/sc-ship-umgah.png b/assets/images/starcontrol/sc-ship-umgah.png index 13b7967..9ef42a3 100644 Binary files a/assets/images/starcontrol/sc-ship-umgah.png and b/assets/images/starcontrol/sc-ship-umgah.png differ diff --git a/assets/images/starcontrol/sc-ship-urquan.png b/assets/images/starcontrol/sc-ship-urquan.png index 2c6acc0..05dd04e 100644 Binary files a/assets/images/starcontrol/sc-ship-urquan.png and b/assets/images/starcontrol/sc-ship-urquan.png differ diff --git a/assets/images/starcontrol/sc-ship-utwig.png b/assets/images/starcontrol/sc-ship-utwig.png index d852d30..aeaa8a9 100644 Binary files a/assets/images/starcontrol/sc-ship-utwig.png and b/assets/images/starcontrol/sc-ship-utwig.png differ diff --git a/assets/images/starcontrol/sc-ship-vux.png b/assets/images/starcontrol/sc-ship-vux.png index 723a677..bf658bd 100644 Binary files a/assets/images/starcontrol/sc-ship-vux.png and b/assets/images/starcontrol/sc-ship-vux.png differ diff --git a/assets/images/starcontrol/sc-ship-yehat.png b/assets/images/starcontrol/sc-ship-yehat.png index ae6a578..79d7cb7 100644 Binary files a/assets/images/starcontrol/sc-ship-yehat.png and b/assets/images/starcontrol/sc-ship-yehat.png differ diff --git a/assets/images/starcontrol/sc-ship-zoqfot.png b/assets/images/starcontrol/sc-ship-zoqfot.png index d949ff9..8beee78 100644 Binary files a/assets/images/starcontrol/sc-ship-zoqfot.png and b/assets/images/starcontrol/sc-ship-zoqfot.png differ diff --git a/data/star-control-ships.json b/data/star-control-ships.json index 82d6ce4..79de537 100644 --- a/data/star-control-ships.json +++ b/data/star-control-ships.json @@ -55,8 +55,8 @@ "sprite": { "sheet": "sc-ship-androsynth", "frames": 16, - "frameWidth": 16, - "frameHeight": 21 + "frameWidth": 34, + "frameHeight": 30 } }, "arilou": { @@ -105,8 +105,8 @@ "sprite": { "sheet": "sc-ship-arilou", "frames": 16, - "frameWidth": 17, - "frameHeight": 14 + "frameWidth": 22, + "frameHeight": 16 } }, "chenjesu": { @@ -169,8 +169,8 @@ "sprite": { "sheet": "sc-ship-chenjesu", "frames": 16, - "frameWidth": 34, - "frameHeight": 34 + "frameWidth": 46, + "frameHeight": 42 } }, "chmmr": { @@ -229,8 +229,8 @@ "sprite": { "sheet": "sc-ship-chmmr", "frames": 16, - "frameWidth": 37, - "frameHeight": 38 + "frameWidth": 44, + "frameHeight": 42 } }, "druuge": { @@ -281,8 +281,8 @@ "sprite": { "sheet": "sc-ship-druuge", "frames": 16, - "frameWidth": 15, - "frameHeight": 34 + "frameWidth": 52, + "frameHeight": 48 } }, "earthling": { @@ -337,8 +337,8 @@ "sprite": { "sheet": "sc-ship-earthling", "frames": 16, - "frameWidth": 13, - "frameHeight": 35 + "frameWidth": 46, + "frameHeight": 38 } }, "ilwrath": { @@ -390,8 +390,8 @@ "sprite": { "sheet": "sc-ship-ilwrath", "frames": 16, - "frameWidth": 38, - "frameHeight": 31 + "frameWidth": 50, + "frameHeight": 46 } }, "kohrah": { @@ -447,8 +447,8 @@ "sprite": { "sheet": "sc-ship-kohrah", "frames": 16, - "frameWidth": 22, - "frameHeight": 38 + "frameWidth": 42, + "frameHeight": 42 } }, "melnorme": { @@ -505,8 +505,8 @@ "sprite": { "sheet": "sc-ship-melnorme", "frames": 16, - "frameWidth": 31, - "frameHeight": 31 + "frameWidth": 36, + "frameHeight": 36 } }, "mmrnmhrm": { @@ -578,8 +578,8 @@ "sprite": { "sheet": "sc-ship-mmrnmhrm-y", "frames": 16, - "frameWidth": 17, - "frameHeight": 24 + "frameWidth": 28, + "frameHeight": 26 } } ], @@ -594,8 +594,8 @@ "sprite": { "sheet": "sc-ship-mmrnmhrm", "frames": 16, - "frameWidth": 26, - "frameHeight": 18 + "frameWidth": 30, + "frameHeight": 28 } }, "mycon": { @@ -650,8 +650,8 @@ "sprite": { "sheet": "sc-ship-mycon", "frames": 16, - "frameWidth": 26, - "frameHeight": 25 + "frameWidth": 32, + "frameHeight": 28 } }, "orz": { @@ -708,8 +708,8 @@ "sprite": { "sheet": "sc-ship-orz", "frames": 16, - "frameWidth": 29, - "frameHeight": 23 + "frameWidth": 40, + "frameHeight": 38 } }, "pkunk": { @@ -768,8 +768,8 @@ "sprite": { "sheet": "sc-ship-pkunk", "frames": 16, - "frameWidth": 27, - "frameHeight": 20 + "frameWidth": 30, + "frameHeight": 30 } }, "shofixti": { @@ -822,8 +822,8 @@ "sprite": { "sheet": "sc-ship-shofixti", "frames": 16, - "frameWidth": 9, - "frameHeight": 15 + "frameWidth": 20, + "frameHeight": 20 } }, "slylandro": { @@ -876,8 +876,8 @@ "sprite": { "sheet": "sc-ship-slylandro", "frames": 16, - "frameWidth": 28, - "frameHeight": 45 + "frameWidth": 50, + "frameHeight": 46 } }, "spathi": { @@ -934,8 +934,8 @@ "sprite": { "sheet": "sc-ship-spathi", "frames": 16, - "frameWidth": 28, - "frameHeight": 22 + "frameWidth": 38, + "frameHeight": 32 } }, "supox": { @@ -984,8 +984,8 @@ "sprite": { "sheet": "sc-ship-supox", "frames": 16, - "frameWidth": 13, - "frameHeight": 30 + "frameWidth": 34, + "frameHeight": 34 } }, "syreen": { @@ -1039,8 +1039,8 @@ "sprite": { "sheet": "sc-ship-syreen", "frames": 16, - "frameWidth": 17, - "frameHeight": 30 + "frameWidth": 46, + "frameHeight": 38 } }, "thraddash": { @@ -1098,8 +1098,8 @@ "sprite": { "sheet": "sc-ship-thraddash", "frames": 16, - "frameWidth": 22, - "frameHeight": 22 + "frameWidth": 28, + "frameHeight": 28 } }, "umgah": { @@ -1151,8 +1151,8 @@ "sprite": { "sheet": "sc-ship-umgah", "frames": 16, - "frameWidth": 12, - "frameHeight": 14 + "frameWidth": 18, + "frameHeight": 16 } }, "urquan": { @@ -1211,8 +1211,8 @@ "sprite": { "sheet": "sc-ship-urquan", "frames": 16, - "frameWidth": 29, - "frameHeight": 33 + "frameWidth": 46, + "frameHeight": 44 } }, "utwig": { @@ -1298,8 +1298,8 @@ "sprite": { "sheet": "sc-ship-utwig", "frames": 16, - "frameWidth": 33, - "frameHeight": 31 + "frameWidth": 36, + "frameHeight": 36 } }, "vux": { @@ -1352,8 +1352,8 @@ "sprite": { "sheet": "sc-ship-vux", "frames": 16, - "frameWidth": 15, - "frameHeight": 18 + "frameWidth": 28, + "frameHeight": 24 } }, "yehat": { @@ -1415,8 +1415,8 @@ "sprite": { "sheet": "sc-ship-yehat", "frames": 16, - "frameWidth": 19, - "frameHeight": 13 + "frameWidth": 26, + "frameHeight": 24 } }, "zoqfot": { @@ -1470,8 +1470,8 @@ "sprite": { "sheet": "sc-ship-zoqfot", "frames": 16, - "frameWidth": 23, - "frameHeight": 24 + "frameWidth": 30, + "frameHeight": 30 } } } diff --git a/src/games/starcontrol/StarControlGame.js b/src/games/starcontrol/StarControlGame.js index 412f625..5cab716 100644 --- a/src/games/starcontrol/StarControlGame.js +++ b/src/games/starcontrol/StarControlGame.js @@ -4,10 +4,9 @@ import { Button } from '../../ui/Button.js'; import { MusicPlayer } from '../../ui/MusicPlayer.js'; import { playSound, SFX } from '../../ui/Sounds.js'; import { api } from '../../services/api.js'; -import { applyArcadeCRTOverlay } from '../../ui/ArcadeCRTOverlay.js'; import { ARENA_W, ARENA_H, ZOOM, TUNE, STEP_MS, - mulberry32, wrap, tdelta, tdist, tmid, targetZoom, smoothTowards, + mulberry32, wrap, tdelta, tmid, targetZoom, smoothTowards, compileShips, createBattle, setInput, stepMatch, quantizeFacing, facingToRad, } from './StarControlLogic.js'; import { createAI, updateAI } from './StarControlAI.js'; @@ -87,18 +86,16 @@ export default class StarControlGame extends Phaser.Scene { ); this.escHandler = () => this.onEscape(); this.input.keyboard.on('keydown-ESC', this.escHandler); + this.pickKeyHandlers = []; - this.crt = applyArcadeCRTOverlay(this, { - accentTint: 0x74f5a1, scanlineTint: 0x2e8f57, - }); try { const music = this.cache.json.get('music'); if (music?.tracks) this.music = new MusicPlayer(this, music.tracks); } catch (_) { /* optional */ } this.events.once('shutdown', () => { - this.crt.destroy(); this.input.keyboard.off('keydown-ESC', this.escHandler); + this.teardownPickKeys(); }); // Match configuration defaults (setup view edits these). @@ -365,6 +362,7 @@ export default class StarControlGame extends Phaser.Scene { showShipPick() { this.view = 'shipPick'; this.clearView(); + this.teardownPickKeys(); // AI sides pick instantly. [0, 1].forEach((side) => { @@ -397,23 +395,68 @@ export default class StarControlGame extends Phaser.Scene { const perRow = Math.min(remaining.length, 7); const cardW = 240; const cardH = 290; - remaining.forEach((entry, n) => { + const cards = remaining.map((entry, n) => { const row = Math.floor(n / perRow); const inRow = Math.min(remaining.length - row * perRow, perRow); const x = cx + (n % perRow - (inRow - 1) / 2) * (cardW + 20); const y = 420 + row * (cardH + 24); - root.add(this.shipCard(x, y, cardW, cardH, entry, humanSide, () => { - this.current[humanSide] = entry.i; - this.needPick[humanSide] = false; - playSound(this, SFX.EIGHTBIT_CARD); - this.showShipPick(); // next picker (hotseat) or battle - })); + const card = this.shipCard(x, y, cardW, cardH, entry, humanSide, + () => this.confirmShipPick(humanSide, entry)); + root.add(card); + return card; }); root.add(this.mkText(cx, GAME_HEIGHT - 40, `FLEET VALUE REMAINING — YOU ${fleetPoints(this.SHIPS, remaining.map((e) => e.key))} PTS / ` + `ENEMY ${fleetPoints(this.SHIPS, this.aliveFleet(1 - humanSide).map((e) => e.key))} PTS`, 22, '#89a6a0')); + + this.setupPickKeys(humanSide, remaining, cards); + } + + confirmShipPick(side, entry) { + this.current[side] = entry.i; + this.needPick[side] = false; + playSound(this, SFX.EIGHTBIT_CARD); + this.showShipPick(); // next picker (hotseat) or battle + } + + // Lets the currently-picking player browse ship cards with the same keys + // they fly with in battle. In hotseat, each side is locked to its own + // cluster (A/D+Z/X for side 0, arrows+comma/period for side 1) so one + // player's keys don't steal the other's turn. Outside hotseat the human + // is always side 0, but readKeys() lets them fly with either cluster — + // so both must work here too. + setupPickKeys(side, remaining, cards) { + if (!cards.length) return; + let idx = 0; + cards[idx].focusRing.setVisible(true); + const move = (delta) => { + cards[idx].focusRing.setVisible(false); + idx = (idx + delta + cards.length) % cards.length; + cards[idx].focusRing.setVisible(true); + playSound(this, SFX.EIGHTBIT_ACTION); + }; + const confirm = () => this.confirmShipPick(side, remaining[idx]); + const clusters = this.mode === 'hotseat' + ? [side === 0 ? ['A', 'D', 'Z', 'X'] : ['LEFT', 'RIGHT', 'COMMA', 'PERIOD']] + : [['A', 'D', 'Z', 'X'], ['LEFT', 'RIGHT', 'COMMA', 'PERIOD']]; + for (const [leftKey, rightKey, fireKey, specialKey] of clusters) { + this.registerPickKey(`keydown-${leftKey}`, () => move(-1)); + this.registerPickKey(`keydown-${rightKey}`, () => move(1)); + this.registerPickKey(`keydown-${fireKey}`, confirm); + this.registerPickKey(`keydown-${specialKey}`, confirm); + } + } + + registerPickKey(evt, fn) { + this.input.keyboard.on(evt, fn); + this.pickKeyHandlers.push({ evt, fn }); + } + + teardownPickKeys() { + (this.pickKeyHandlers ?? []).forEach(({ evt, fn }) => this.input.keyboard.off(evt, fn)); + this.pickKeyHandlers = []; } shipCard(x, y, w, h, entry, side, onPick) { @@ -423,16 +466,30 @@ export default class StarControlGame extends Phaser.Scene { g.fillStyle(0x0c1a14, 0.94).fillRoundedRect(-w / 2, -h / 2, w, h, 10); g.lineStyle(2, SIDE_COLORS[side].hull, 0.7).strokeRoundedRect(-w / 2, -h / 2, w, h, 10); c.add(g); - const icon = this.add.graphics(); - this.drawChevron(icon, 0, -62, 34, -Math.PI / 2, SIDE_COLORS[side].hull, false); - c.add(icon); + const spDef = def.sprite; + if (spDef?.sheet && this.textures.exists(spDef.sheet)) { + // Frame 0 of every UQM rotation sheet faces up. + this.textures.get(spDef.sheet).setFilter(Phaser.Textures.FilterMode.NEAREST); + const iconScale = Math.min(100 / spDef.frameWidth, 100 / spDef.frameHeight); + c.add(this.add.sprite(0, -62, spDef.sheet, 0).setScale(iconScale)); + } else { + const icon = this.add.graphics(); + this.drawChevron(icon, 0, -62, 34, -Math.PI / 2, SIDE_COLORS[side].hull, false); + c.add(icon); + } c.add(this.mkText(0, 8, def.name.replace(' ', '\n'), 24).setAlign('center')); const crew = entry.crew ?? def.stats.maxCrew; c.add(this.mkText(0, 74, `CREW ${crew}/${def.stats.maxCrew}`, 18, crew < def.stats.maxCrew ? '#f4a26c' : '#9adbb2')); c.add(this.mkText(0, 102, `${def.pointValue} PTS`, 18, '#e7d27b')); + const focusRing = this.add.graphics(); + focusRing.lineStyle(3, 0xffffff, 1).strokeRoundedRect(-w / 2, -h / 2, w, h, 10); + focusRing.setVisible(false); + c.add(focusRing); + c.focusRing = focusRing; c.setSize(w, h); c.setInteractive({ useHandCursor: true }); - c.on('pointerover', () => g.lineStyle(3, 0xffffff, 1).strokeRoundedRect(-w / 2, -h / 2, w, h, 10)); + c.on('pointerover', () => focusRing.setVisible(true)); + c.on('pointerout', () => focusRing.setVisible(false)); c.on('pointerdown', onPick); return c; } @@ -498,7 +555,9 @@ export default class StarControlGame extends Phaser.Scene { if (this.match.over && this.deathHoldMs > 0) { this.deathHoldMs -= delta; - if (this.deathHoldMs <= 0) this.resolveBattleEnd(); + // resolveBattleEnd leaves the battle view (destroying HUD/world + // objects), so this frame must not touch them afterwards. + if (this.deathHoldMs <= 0) { this.resolveBattleEnd(); return; } } this.updateCamera(delta); @@ -537,7 +596,7 @@ export default class StarControlGame extends Phaser.Scene { case 'shipHit': this.fxList.push({ type: 'burst', x: e.x, y: e.y, r: 40 + e.dmg * 14, ttl: 300, age: 0 }); this.throttledSfx(SFX.EIGHTBIT_EXPLODE, 120); - this.crt.pulse?.(0.4, 120); + this.cameras.main.shake(120, 0.0016); break; case 'shotHit': this.fxList.push({ type: 'burst', x: e.x, y: e.y, r: 26, ttl: 200, age: 0 }); @@ -556,7 +615,7 @@ export default class StarControlGame extends Phaser.Scene { case 'glory': this.fxList.push({ type: 'ring', x: e.x, y: e.y, r: e.range, ttl: 600, age: 0 }); playSound(this, SFX.SCIFI_EXPLODE); - this.crt.pulse?.(1, 400); + this.cameras.main.shake(400, 0.004); break; case 'cloak': this.throttledSfx(SFX.SCIFI_RISER, 300); @@ -570,7 +629,7 @@ export default class StarControlGame extends Phaser.Scene { case 'death': this.fxList.push({ type: 'boom', x: e.x, y: e.y, r: 260, ttl: 1100, age: 0 }); playSound(this, SFX.SCIFI_EXPLODE); - this.crt.pulse?.(1, 500); + this.cameras.main.shake(500, 0.004); this.deathFocus = { x: e.x, y: e.y }; break; case 'battleOver': @@ -651,7 +710,17 @@ export default class StarControlGame extends Phaser.Scene { const ra = this.renderPos(A); const rb = this.renderPos(B); mid = tmid(ra.x, ra.y, rb.x, rb.y); - tz = targetZoom(tdist(ra.x, ra.y, rb.x, rb.y)); + const dx = tdelta(ra.x, rb.x, ARENA_W); + const dy = tdelta(ra.y, rb.y, ARENA_H); + tz = targetZoom(Math.hypot(dx, dy)); + // The distance bands above assume a roughly square view, but the + // canvas is 16:9, so a mostly-vertical separation can still push a + // ship past the (much closer) top/bottom edge. Clamp per-axis against + // the actual on-screen half-extents so both ships always fit. + const SHIP_MARGIN = 140; + const maxZoomX = (GAME_WIDTH / 2 - SHIP_MARGIN) / Math.max(Math.abs(dx) / 2, 1); + const maxZoomY = (GAME_HEIGHT / 2 - SHIP_MARGIN) / Math.max(Math.abs(dy) / 2, 1); + tz = Math.min(tz, maxZoomX, maxZoomY); } const k = 1 - Math.exp(-delta / ZOOM.SMOOTH_MS); this.cam.zoom = smoothTowards(this.cam.zoom, tz, delta); @@ -763,8 +832,8 @@ export default class StarControlGame extends Phaser.Scene { } } - // Ships. UQM sheets: frame 0 faces up, rotating counterclockwise, so the - // frame for quantized facing q (0 = east, clockwise) is (12 - q) & 15. + // Ships. UQM sheets: frame 0 faces up, rotating clockwise, so the + // frame for quantized facing q (0 = east, clockwise) is (q + 4) & 15. for (const ship of this.match.ships) { const spr = this.shipSprites?.[ship.side]; if (!ship.alive || ship.fx.cloaked) { spr?.setVisible(false); continue; } @@ -780,7 +849,7 @@ export default class StarControlGame extends Phaser.Scene { spr.setVisible(true) .setPosition(s.x, s.y) .setScale(z * 4) - .setFrame((12 - q + 16) & 15); + .setFrame((q + 4) & 15); spr.setTint(ship.fx.blazer ? 0xff8866 : 0xffffff); if (thrusting) { const f = ship.facing; diff --git a/tools/fetchStarControlAssets.js b/tools/fetchStarControlAssets.js index 41f8b8c..35f6841 100644 --- a/tools/fetchStarControlAssets.js +++ b/tools/fetchStarControlAssets.js @@ -10,8 +10,11 @@ // // --ships: for each ship, the GitHub contents API lists // sc2/content/base/ships/