import type { Vec2 } from '../geometry/Vec2'; import type { BearColor } from './BearCrush'; export type OddJellyVariant = 'normal' | 'ears' | 'horn' | 'tail' | 'body' | 'face'; export interface OddJellyBody { id: number; variant: OddJellyVariant; strength: number; position: Vec2; rotation: number; color: BearColor; } export interface OddJellyDefinition { difficulty: 'Easy' | 'Normal' | 'Hard' | 'Very hard'; bodies: readonly OddJellyBody[]; } export const ODD_JELLY = { limit: 30, down: 0.10, hold: 0.05, up: 0.15, cycle: 0.30, halfW: 5.4, halfH: 7.6, } as const; // 스테이지별 고정 시드를 사용해 재시작과 앱 재실행 뒤에도 같은 개체·자세를 유지한다. function scatteredPositions(stage:number):Vec2[] { let seed=4709+stage*7919; const random=()=>((seed=(Math.imul(seed,1664525)+1013904223)>>>0)/4294967296); const positions:Vec2[]=[]; // 고정 시드의 후보 중 기존 개체에서 가장 먼 곳을 골라 격자 없이 간격을 확보한다. for(let id=0;id<32;id++) { let best:Vec2={x:0,y:0},distance=-1; for(let candidate=0;candidate<256;candidate++) { const p={x:(random()*2-1)*4.45,y:(random()*2-1)*6.4}; const nearest=positions.reduce((min,q)=>Math.min(min,Math.hypot(p.x-q.x,p.y-q.y)),20); if(nearest>distance){best=p;distance=nearest;} } positions.push(best); } return positions; } const colors:readonly BearColor[]=['red','green','blue','yellow','white']; const targets = [[5,18,27],[2,9,14,23,30],[1,6,10,15,21,26,29],[0,4,8,12,16,20,24,28,31]]; const variants: readonly OddJellyVariant[][] = [ ['horn','tail','ears'], ['tail','ears','horn','body','ears'], ['ears','horn','body','tail','ears','body','horn'], ['ears','body','face','horn','body','ears','tail','face','horn'], ]; export const ODD_JELLY_LEVELS: readonly OddJellyDefinition[] = (['Easy','Normal','Hard','Very hard'] as const).map((difficulty,stage) => ({ difficulty, bodies: scatteredPositions(stage).map((position,id) => { const target=targets[stage].indexOf(id); return { id,variant:target<0?'normal':variants[stage][target],strength:target<0?0:[1,0.75,0.5,0.35][stage], position, rotation:(((id*13+stage*7)%31)-15)*Math.PI/40, color:colors[(id*3+stage)%colors.length], }; }), }));