[object Object]

← back to Games Agentabrams

Fix Flappy Sky ghosting: opaque per-frame sky clear (was translucent → smear trail)

a788194cbd8188d80cb978a0bfc2cd06c37726df · 2026-07-24 18:24:23 -0700 · Steve

Files touched

Diff

commit a788194cbd8188d80cb978a0bfc2cd06c37726df
Author: Steve <steve@designerwallcoverings.com>
Date:   Fri Jul 24 18:24:23 2026 -0700

    Fix Flappy Sky ghosting: opaque per-frame sky clear (was translucent → smear trail)
---
 .gitignore                  |  2 ++
 games/flappy-sky/index.html | 11 ++++++++---
 tests/midplay.mjs           | 18 ++++++++++++++++++
 tests/play-flappy-sky.mjs   | 28 ++++++++++++++++++++++++++++
 4 files changed, 56 insertions(+), 3 deletions(-)

diff --git a/.gitignore b/.gitignore
index 31b0a23..8f85f84 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,3 +7,5 @@ dist/
 build/
 .next/
 tests/screenshot.png
+
+tests/rec/
diff --git a/games/flappy-sky/index.html b/games/flappy-sky/index.html
index b92f2c2..3350124 100644
--- a/games/flappy-sky/index.html
+++ b/games/flappy-sky/index.html
@@ -607,9 +607,14 @@
 
   // ---- rendering ------------------------------------------------------
   function drawBackground() {
-    const grd = ctx.createLinearGradient(0, 0, 0, H);
-    grd.addColorStop(0, "rgba(40,50,90,0.25)");
-    grd.addColorStop(1, "rgba(0,0,0,0.55)");
+    // Opaque full-frame sky. This is also the per-frame CLEAR — the canvas is
+    // created with { alpha: false }, so the CSS background never shows through
+    // and a translucent fill here would let every prior frame ghost through
+    // (the bird/pipes/particles smeared into a trail). Paint the sky solid.
+    const grd = ctx.createRadialGradient(W * 0.2, H * 0.2, 0, W * 0.2, H * 0.2, Math.max(W, H));
+    grd.addColorStop(0, "#586df2");
+    grd.addColorStop(0.4, "#243046");
+    grd.addColorStop(1, "#0e1018");
     ctx.fillStyle = grd;
     ctx.fillRect(0, 0, W, H);
 
diff --git a/tests/midplay.mjs b/tests/midplay.mjs
new file mode 100644
index 0000000..4d118af
--- /dev/null
+++ b/tests/midplay.mjs
@@ -0,0 +1,18 @@
+import { createRequire } from 'module'; import { fileURLToPath } from 'url';
+import path from 'path'; import http from 'http'; import fs from 'fs';
+const require=createRequire(import.meta.url); let chromium; try{({chromium}=require('/Users/macstudio3/.npm-global/lib/node_modules/playwright'));}catch{({chromium}=require('playwright'));}
+const root=path.dirname(path.dirname(fileURLToPath(import.meta.url)));
+const MIME={'.html':'text/html','.json':'application/json','.png':'image/png'};
+const server=http.createServer((req,res)=>{let p=decodeURIComponent(req.url.split('?')[0]);if(p.endsWith('/'))p+='index.html';const f=path.join(root,p);if(!f.startsWith(root)||!fs.existsSync(f)){res.writeHead(404);res.end('nf');return;}res.writeHead(200,{'Content-Type':MIME[path.extname(f)]||'text/plain'});fs.createReadStream(f).pipe(res);});
+await new Promise(r=>server.listen(0,'127.0.0.1',r));
+const base=`http://127.0.0.1:${server.address().port}`;
+const browser=await chromium.launch();
+const page=await browser.newPage({viewport:{width:480,height:720}});
+await page.goto(base+'/games/flappy-sky/',{waitUntil:'networkidle'});
+await page.waitForTimeout(400);
+// start, then hover-flap gently to stay airborne, screenshot mid-play
+for(let i=0;i<7;i++){ await page.mouse.click(240,300); await page.waitForTimeout(300); }
+await page.screenshot({path:'tests/rec/flappy-sky-MIDPLAY.png'});
+const s=await page.evaluate(()=>({score:document.getElementById('scoreVal').textContent,overlayHidden:document.getElementById('overlay').classList.contains('hidden'),resultShown:document.getElementById('result').classList.contains('show')}));
+console.log('MIDPLAY', JSON.stringify(s));
+await browser.close(); server.close();
diff --git a/tests/play-flappy-sky.mjs b/tests/play-flappy-sky.mjs
new file mode 100644
index 0000000..3f4e0b3
--- /dev/null
+++ b/tests/play-flappy-sky.mjs
@@ -0,0 +1,28 @@
+import { createRequire } from 'module';
+import { fileURLToPath } from 'url';
+import path from 'path'; import http from 'http'; import fs from 'fs';
+const require = createRequire(import.meta.url);
+let chromium; try { ({chromium}=require('/Users/macstudio3/.npm-global/lib/node_modules/playwright')); } catch { ({chromium}=require('playwright')); }
+const root = path.dirname(path.dirname(fileURLToPath(import.meta.url)));
+const MIME={'.html':'text/html','.json':'application/json','.png':'image/png','.js':'text/javascript'};
+const server=http.createServer((req,res)=>{let p=decodeURIComponent(req.url.split('?')[0]);if(p.endsWith('/'))p+='index.html';const f=path.join(root,p);if(!f.startsWith(root)||!fs.existsSync(f)||fs.statSync(f).isDirectory()){res.writeHead(404);res.end('nf');return;}res.writeHead(200,{'Content-Type':MIME[path.extname(f)]||'text/plain'});fs.createReadStream(f).pipe(res);});
+await new Promise(r=>server.listen(0,'127.0.0.1',r));
+const base=`http://127.0.0.1:${server.address().port}`;
+const browser=await chromium.launch();
+const ctx=await browser.newContext({viewport:{width:480,height:720},recordVideo:{dir:'tests/rec',size:{width:480,height:720}}});
+const page=await ctx.newPage();
+const errs=[]; page.on('pageerror',e=>errs.push('PAGEERR '+e.message)); page.on('console',m=>{if(m.type()==='error')errs.push('CONSOLE '+m.text());});
+await page.goto(base+'/games/flappy-sky/',{waitUntil:'networkidle'});
+await page.waitForTimeout(500);
+// read game state via a probe: we can't reach closure vars, so infer from DOM + a scripted play
+const snap = async(label)=>{ const s=await page.evaluate(()=>({score:document.getElementById('scoreVal')?.textContent, overlayHidden:document.getElementById('overlay')?.classList.contains('hidden'), resultShown:document.getElementById('result')?.classList.contains('show'), prompt:document.getElementById('prompt')?.textContent, best:document.getElementById('bestVal')?.textContent})); console.log(label, JSON.stringify(s)); return s;};
+await snap('READY');
+// start + flap steadily like a real player for ~8s
+await page.mouse.move(240,360);
+for(let i=0;i<20;i++){ await page.mouse.click(240,360); await page.waitForTimeout(340); if(i%15===0) await snap('t'+i); }
+await snap('AFTER-PLAY');
+await page.screenshot({path:'tests/rec/flappy-sky-FIXED.png'});
+await page.waitForTimeout(300);
+await ctx.close(); // finalizes video
+await browser.close(); server.close();
+console.log('ERRORS:', errs.length? errs.join('\n') : 'none');

← c24ee2b Add 3 new-genre arcade games: Abrams Snake, Abrams Break, Ab  ·  back to Games Agentabrams  ·  Add 4 arcade games: Pong 2P, Emoji Memory, Spirograph, Const aeeb0bf →