- 玩法一 数字一笔:规则库、求解器、26 关、竖屏触摸 Web 原型、测试 - 玩法二 连连气球:连消畅玩版核心、Web 原型、Cocos 球槽组件与导出脚本 - 玩法三 六边一笔:规则库、求解器、10 关 + 转墙实验包、Web 原型、测试 - 产品文档、UI 设计规范、各玩法 GDD / HANDOFF - 文档移除全部外部参考作引用;删除玩法二 v0 旧稿
46 lines
3.5 KiB
JavaScript
46 lines
3.5 KiB
JavaScript
// 本次任务已有空间为 4;新验收任务需改成已创建的空间 ID。
|
|
// 只读调试快照作为触摸定位依据,不改游戏状态。
|
|
import assert from 'node:assert/strict';
|
|
import { writeFile } from 'node:fs/promises';
|
|
const task = await taskSpace(4);
|
|
const page = task.page('p1');
|
|
const dir = process.env.BALLOON_QA_DIR || '/Users/wukaibing/Grok/number-swipe/modes/02-connect-1234/docs/qa-v2';
|
|
await page.reload();
|
|
await page.evaluate(() => {window.qaErrors=[];addEventListener('error',e=>window.qaErrors.push(e.message));addEventListener('unhandledrejection',e=>window.qaErrors.push(String(e.reason)));});
|
|
const snapshot = () => page.evaluate(() => window.__balloons.snapshot());
|
|
const targets = () => page.evaluate(() => {const api=window.__balloons, s=api.snapshot(), t=api.transform(), r=document.querySelector('#board').getBoundingClientRect();return api.hint().map(id=>{const b=s.balls.find(b=>b.id===id);return {x:r.left+t.x+b.x*t.scale,y:r.top+t.y+b.y*t.scale,id:0,radiusX:5,radiusY:5,force:1};});});
|
|
const touch = (type, points=[]) => page.cdp('Input.dispatchTouchEvent',{type,touchPoints:points});
|
|
const swipe = async(points,cancel=false) => {
|
|
for(let i=0;i<points.length;i++) await touch(i?'touchMove':'touchStart',[points[i]]);
|
|
await touch(cancel?'touchCancel':'touchEnd');
|
|
};
|
|
const opening=await snapshot(), points=await targets();
|
|
await swipe(points.slice(0,2)); assert.deepEqual(await snapshot(),opening);
|
|
await swipe(points,true); assert.deepEqual(await snapshot(),opening);
|
|
await swipe([points[0],points[1],points[2],points[1]]); assert.deepEqual(await snapshot(),opening);
|
|
const moves=[];
|
|
for(let i=0;i<24;i++){
|
|
const before=await snapshot(); await swipe(await targets());
|
|
await page.waitForFunction(()=>!window.__balloons.animating(),undefined,{timeout:7000});
|
|
const after=await snapshot(); assert.equal(after.stats.turns,before.stats.turns+1); assert(after.stats.score>before.stats.score);
|
|
assert(await page.evaluate(()=>document.querySelector('#modal').hidden));
|
|
moves.push({turn:after.stats.turns,score:after.stats.score,combo:after.stats.lastCombo,peak:after.stats.maxNumber,flown:after.stats.flown,feverLeft:after.feverLeft});
|
|
if(i===0){
|
|
await page.screenshot({path:dir+'/first-merge.png'});
|
|
await page.click('#undo'); assert.deepEqual(await snapshot(),before);
|
|
await swipe(await targets()); await page.waitForFunction(()=>!window.__balloons.animating(),undefined,{timeout:7000});
|
|
assert.deepEqual(await snapshot(),after);
|
|
}
|
|
if(after.feverLeft===5 && !moves.slice(0,-1).some(m=>m.feverLeft===5)) await page.screenshot({path:dir+'/rainbow.png'});
|
|
if(after.stats.flown===1 && !moves.slice(0,-1).some(m=>m.flown>0)) await page.screenshot({path:dir+'/flight.png'});
|
|
}
|
|
const beforeBreeze=await snapshot(); await page.click('#shuffle');
|
|
await page.waitForFunction(()=>!window.__balloons.animating(),undefined,{timeout:7000});
|
|
assert.deepEqual((await snapshot()).stats,beforeBreeze.stats);
|
|
await page.click('#undo'); assert.deepEqual(await snapshot(),beforeBreeze);
|
|
const errors=await page.evaluate(()=>window.qaErrors); assert.deepEqual(errors,[]);
|
|
assert(moves.some(m=>m.combo>=3)); assert(moves.some(m=>m.flown>0)); assert(moves.some(m=>m.feverLeft>0));
|
|
await writeFile(dir+'/browser.json',JSON.stringify({viewport:[390,844],input:'CDP touch events',invalidCancelBacktrack:true,undoDeterministic:true,breezeUndo:true,moves,errors},null,2)+'\n');
|
|
console.log(JSON.stringify({gestures:moves.length,final:moves.at(-1),errors}));
|
|
console.log(await page.snapshot());
|