feat: integrate brighter A3 soft ribbon hints with cached target glow
This commit is contained in:
@@ -35,27 +35,27 @@ test('hint draws skip player edges and mask visited cells on their own layer; co
|
||||
const ctx=new Proxy({globalCompositeOperation:'source-over',save(){stack.push(this.globalCompositeOperation);},restore(){this.globalCompositeOperation=stack.pop();},beginPath(){from=to=null;},moveTo:(...p)=>{from=p;},lineTo:(...p)=>{to=p;},stroke(){if(from&&to)strokes.push([from,to]);},arc:(...p)=>arcs.push(p),fill(){events.push({kind:'fill',mode:this.globalCompositeOperation});}},{get:(o,k)=>o[k]??(()=>{}),set:(o,k,v)=>(o[k]=v,true)});
|
||||
const poly=[[0,0],[100,0],[100,100],[0,100]];
|
||||
drawHint(ctx,{route:['a','b','c'],visitedPolygons:[poly]},{a:[0,0],b:[100,0],c:[200,0]},50,300,['a','b']);
|
||||
assert.deepEqual(strokes,[[[100,0],[200,0]],[[100,0],[200,0]]],'only unwalked edge receives hint strokes');
|
||||
assert.equal(strokes.length,4);assert.ok(strokes.every(s=>JSON.stringify(s)===JSON.stringify([[100,0],[200,0]])),'only unwalked edge receives hint strokes');
|
||||
assert.ok(events.some(e=>e.kind==='fill'&&e.mode==='destination-out'));
|
||||
assert.equal(ctx.globalCompositeOperation,'source-over');
|
||||
assert.equal(arcs.length,1,'no moving light or rings over already walked edge');
|
||||
assert.equal(arcs.length,0,'A3 has no light beads or endpoint rings');
|
||||
});
|
||||
test('parity is a segment anchor; colour is not; flow moves continuously across cells',()=>{
|
||||
const l={cells:solution.map(id=>({id,...(id==='d'?{parity:'odd'}:{category:'circle'})}))};
|
||||
assert.deepEqual(hintSegment(l,solution,[]).route,['a','b','c','d']);
|
||||
const arcs=[],ctx=new Proxy({arc:(...p)=>arcs.push(p)},{get:(o,k)=>o[k]??(()=>{}),set:(o,k,v)=>(o[k]=v,true)});
|
||||
drawHint(ctx,{route:['a','b','c']},{a:[0,0],b:[100,0],c:[100,100]},50,300);
|
||||
assert.deepEqual(arcs.at(-3).slice(0,2),[50,0]);
|
||||
assert.equal(arcs.length,0,'static fallback has no moving beads');
|
||||
});
|
||||
|
||||
test('coral teaching ribbon preserves visited masks and offers direction in reduced motion',()=>{
|
||||
test('soft teaching ribbon preserves visited masks without arrows in reduced motion',()=>{
|
||||
for(const reducedMotion of [false,true]){
|
||||
const strokes=[],fills=[],stack=[];
|
||||
const ctx=new Proxy({globalCompositeOperation:'source-over',save(){stack.push(this.globalCompositeOperation);},restore(){this.globalCompositeOperation=stack.pop();},stroke(){strokes.push({color:this.strokeStyle,mode:this.globalCompositeOperation});},fill(){fills.push(this.globalCompositeOperation);}},{get:(o,k)=>o[k]??(()=>{}),set:(o,k,v)=>(o[k]=v,true)});
|
||||
const path=['a'];
|
||||
drawHint(ctx,{route:['a','b'],guides:[{a:'a',b:'b',points:[[0,0],[100,0]]}],visitedShapes:[{rings:[[[0,0],[20,0],[20,20],[0,20]]],radius:3,depth:3,maskPad:4}],keepouts:[{x:40,y:0,w:12,h:15}],reducedMotion},{},50,300,path);
|
||||
assert.ok(strokes.some(s=>s.color==='#F49B75'));
|
||||
assert.ok(strokes.filter(s=>s.color==='#C96E48'&&s.mode==='source-over').length>=1,'directional chevron');
|
||||
assert.ok(strokes.some(s=>s.color==='rgba(255,185,126,0.72)'));
|
||||
assert.equal(strokes.filter(s=>s.color==='#C96E48').length,0,'no chevrons');
|
||||
assert.ok(fills.includes('destination-out'));
|
||||
assert.equal(ctx.globalCompositeOperation,'source-over');
|
||||
assert.deepEqual(path,['a']);
|
||||
|
||||
Reference in New Issue
Block a user