From 1823a39e58d1b492bcd0b0cb33567e903e05549f Mon Sep 17 00:00:00 2001 From: "prompt.ac/@jeffrey" Date: Fri, 25 Sep 2026 17:03:23 -0700 Subject: [PATCH] oskiewar: plain high-contrast start, held-only legend, fps behind debug START is the word alone in high-contrast ink with its shadow; the yellow plate is gone. The top-left legend shows a control only while it is held, named by the action it triggers. The frame rate shows only with the debug overlay lit. The console keeps daylight under the photographic theme (the website still pairs the photographs with night). Co-Authored-By: Claude Opus 5.5 --- xbox/live/oskiewar.js | 38 +++++++++++++++---------------- xbox/live/tests/oskiewar.test.mjs | 9 +++++--- 2 files changed, 25 insertions(+), 22 deletions(-) diff --git a/xbox/live/oskiewar.js b/xbox/live/oskiewar.js index 50325c8903..1afa157d19 100644 --- a/xbox/live/oskiewar.js +++ b/xbox/live/oskiewar.js @@ -1460,9 +1460,13 @@ function losAngelesSun() { return { light: light * light * (3 - 2 * light), sunset }; } -function consoleFrameDrop() { +function consoleHost() { const caps = typeof capabilities === "function" ? capabilities() : {}; - return caps.platform === "xbox-uwp" || caps.platform === "xbox" ? .1 : 0; + return caps.platform === "xbox-uwp" || caps.platform === "xbox"; +} + +function consoleFrameDrop() { + return consoleHost() ? .1 : 0; } function displayTheme() { @@ -12552,6 +12556,10 @@ function drawControlLegend(ink) { // page — the drawn controller carries its d-pad, so no rows remain. const m30 = !keyboard && !survivalActive() && m30Seated(); if (m30) controls.length = 0; + const pressed = controls.filter(([, button, action]) => + (button.startsWith("Arrow") ? directionActive(button) : held.includes(button)) || + action === "DASH >>"); + controls.splice(0, controls.length, ...pressed); const keyboardCap = { LEFT: "A", RIGHT: "D", STICK_UP: "W", DOWN: "S", A: "SPACE", B: "ENTER", X: "SHIFT", Y: "ALT" }; const step = Math.round(size * 1.82); @@ -15338,21 +15346,12 @@ function drawTitleScreen(t, ink, transitionAge = -1) { if (!socialPreview) { const x = button.x - (hovered ? 2 : 0); const y = button.y - (hovered ? 3 : 0); - const rounded = (left, top, width, height, radius, color) => { - hudBox(left + radius, top, width - radius * 2, height, ...color); - hudBox(left, top + radius, width, height - radius * 2, ...color); - for (const cx of [left + radius, left + width - radius]) - for (const cy of [top + radius, top + height - radius]) - filledDisc(cx, cy, radius, color); - }; - rounded(x + (hovered ? 7 : 4), y + (hovered ? 9 : 6), - button.width, button.height, 14, shadowInk); - rounded(x, y, button.width, button.height, 14, [178, 139, 32]); - rounded(x + 3, y + 3, button.width - 6, button.height - 6, 11, - hovered ? [255, 240, 139] : [255, 221, 74]); - typeWrite(prompt, x + (button.width - button.textWidth) / 2, - y + (button.height - button.textSize) / 2 - 2, - button.textSize, ...promptInk); + const startInk = transitionInk || ink; + const startX = x + (button.width - button.textWidth) / 2; + const startY = y + (button.height - button.textSize) / 2 - 2; + typeWrite(prompt, startX + 3, startY + 4, button.textSize, + ...contrastShadow(startInk)); + typeWrite(prompt, startX, startY, button.textSize, ...startInk); // The pace dial. Quiet unless the clock is off its default — or was just // touched, so stepping back to one still answers the keypress — and it // lives large in the bottom-right corner, a dashboard readout rather @@ -15613,7 +15612,7 @@ function drawDebugPerformance(ink) { // playing lets still show fps in hud". One short word, so the read-out // costs the frame it measures almost nothing. const bare = !debugHitboxes; - if (bare && !bareFrameRateShown()) return; + if (bare) return; const metaSize = debugReadoutMetaSize(); const run = runtime(); // Every line waits for a real measurement. The read-out used to answer with @@ -16029,7 +16028,8 @@ function gamePaint() { if (!player.remote) player.handleColors = fighterProfile(player.name).colors; refreshPhotoTheme(); globalThis.__oskiewarGraphicsThemeStatus = photoThemeActive ? "photorealistic" : "flat"; - visualTheme = photoThemeActive ? { light: 0, sunset: 0 } : displayTheme(); + visualTheme = photoThemeActive && !consoleHost() + ? { light: 0, sunset: 0 } : displayTheme(); const replayOven = typeof capabilities === "function" && capabilities().replayOven === true; const reelHud = typeof capabilities === "function" && diff --git a/xbox/live/tests/oskiewar.test.mjs b/xbox/live/tests/oskiewar.test.mjs index baa0221020..c7fed7e4c4 100644 --- a/xbox/live/tests/oskiewar.test.mjs +++ b/xbox/live/tests/oskiewar.test.mjs @@ -770,7 +770,9 @@ test("web uses the realistic theme with shared sun colors as fallback", () => { /caps\.platform === "web" \|\| caps\.platform === "macos"/); assert.match(source, /return \{ \.\.\.sun, light: caps\.colorScheme === "light" \? 1 : 0 \}/); - assert.match(source, /visualTheme = photoThemeActive \? \{ light: 0, sunset: 0 \} : displayTheme\(\)/); + // The website pairs photographs with night; the console keeps daylight. + assert.match(source, + /visualTheme = photoThemeActive && !consoleHost\(\)\s*\? \{ light: 0, sunset: 0 \} : displayTheme\(\)/); }); test("tab title animates playful phoneme spacing", () => { @@ -2589,8 +2591,9 @@ test("start button flashes yellow green lime before lifting off the fight", () = assert.equal(fight.selectionState().selecting, false); assert.match(source, /const prompt = "start"/); assert.match(source, /const button = titleButtonRect\(\)/); - // Start retains its yellow identity in the larger button. - assert.match(source, /\[255, 221, 74\]/); + // Start is the word alone in high-contrast ink: no plate behind it. + assert.match(source, /typeWrite\(prompt, startX, startY, button\.textSize, \.\.\.startInk\)/); + assert.doesNotMatch(source, /rounded\(x, y, button\.width, button\.height/); pads[0].down = ["Y"]; tick(); assert.equal(fight.shellState().mode, "MENU"); -- 2.51.2