feat: version campaigns and document original puzzle design
Restore v0.1 and v0.2 archives with separate progress, publish the curved v0.3 campaign, and document the original 24-level design with reproducible evidence. Refine board presentation and movement, and keep video lab tooling within its own directory.
This commit is contained in:
+6
-7
@@ -1,4 +1,4 @@
|
||||
import { exitTiming, smoothMotion } from './exit-animation.js';
|
||||
import { exitTiming, smoothMotion, travelProgress } from './exit-animation.js';
|
||||
import { THEME, PIGMENTS, pigmentIndex } from './design-tokens.js';
|
||||
import { DIRS, key } from './core.js';
|
||||
import { tileSample, roundedHex } from './tile-shape.js';
|
||||
@@ -77,8 +77,7 @@ export function drawScene(p,level,tiles,view,state={}) {
|
||||
if(tile.id===state.shake) dx=Math.sin(state.shakeTime*38)*5*(1-state.shakeTime);
|
||||
let dy=0;
|
||||
if(tile.id===blocker?.id){
|
||||
dx+=Math.cos(impactAngle)*phase.kick*size*.1;dy+=Math.sin(impactAngle)*phase.kick*size*.1;
|
||||
if(phase.impact>0){const ring=hexPoints(c.x+dx,c.y+dy,size*1.04);p.line([...ring,ring[0]],THEME.warning,2.5);}
|
||||
dx+=Math.cos(impactAngle)*phase.kick*size*.32;dy+=Math.sin(impactAngle)*phase.kick*size*.32;
|
||||
}
|
||||
drawTile(p,c.x+dx,c.y+dy,size,visualTile(tile));
|
||||
}
|
||||
@@ -89,11 +88,11 @@ export function drawScene(p,level,tiles,view,state={}) {
|
||||
drawExit(p,route,view,progress,visualTile(route.tile),state.reduced);
|
||||
}else{
|
||||
const loc=pointAlong(movingPath,phase?phase.distance:Math.sin(progress*Math.PI));
|
||||
drawTile(p,loc.x,loc.y,size,visualTile(route.tile),loc.angle,phase?1-phase.impact*.045:1);
|
||||
drawTile(p,loc.x,loc.y,size,visualTile(route.tile),loc.angle,phase&&!state.reduced?1-phase.impact*.12:1);
|
||||
}
|
||||
if(target&&phase.impact>0){
|
||||
const x=(contact.x+target.x)/2,y=(contact.y+target.y)/2;
|
||||
for(const sign of [-1,1]){const a=impactAngle+sign*Math.PI/2,d=size*(.13+phase.impact*.12);p.line([{x:x+Math.cos(a)*d,y:y+Math.sin(a)*d},{x:x+Math.cos(a)*(d+size*.15),y:y+Math.sin(a)*(d+size*.15)}],THEME.warning,2.5);}
|
||||
for(const offset of [-1.95,-1.2,1.2,1.95]){const a=impactAngle+offset,d=size*(.12+phase.impact*.16),length=size*.26*phase.impact;p.line([{x:x+Math.cos(a)*d,y:y+Math.sin(a)*d},{x:x+Math.cos(a)*(d+length),y:y+Math.sin(a)*(d+length)}],THEME.track,Math.max(1.5,size*.055));}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -121,9 +120,9 @@ export function exitGeometry(route,view){
|
||||
export function drawExit(p,route,view,progress,tile,reduced=false){
|
||||
const {points,edge,angle}=exitGeometry(route,view),size=view.size;
|
||||
if(reduced){if(progress<.8){const at=pointAlong(points,progress/.8);drawTile(p,at.x,at.y,size,tile,at.angle);}return;}
|
||||
const travel=exitTiming(route).travelFraction;
|
||||
const timing=exitTiming(route),travel=timing.travelFraction;
|
||||
if(progress<travel){
|
||||
const at=pointAlong(points,smoothMotion(progress/travel));
|
||||
const at=pointAlong(points,travelProgress(progress/travel,timing.travelMs));
|
||||
drawTile(p,at.x,at.y,size,tile,at.angle);return;
|
||||
}
|
||||
const t=Math.min(1,(progress-travel)/(1-travel)),ease=smoothMotion(t);
|
||||
|
||||
Reference in New Issue
Block a user