This commit is contained in:
125
src/data/encounterTransition.ts
Normal file
125
src/data/encounterTransition.ts
Normal file
@@ -0,0 +1,125 @@
|
||||
import { GameState } from '../types';
|
||||
import { getFacingTowardPlayer, getMonsterGroupAnchorX, PLAYER_BASE_X_METERS } from './hostileNpcs';
|
||||
|
||||
function roundMeters(value: number) {
|
||||
return Number(value.toFixed(2));
|
||||
}
|
||||
|
||||
function lerp(start: number, end: number, progress: number) {
|
||||
return roundMeters(start + ((end - start) * progress));
|
||||
}
|
||||
|
||||
export function hasEncounterEntity(state: Pick<GameState, 'sceneHostileNpcs' | 'currentEncounter'>) {
|
||||
return state.sceneHostileNpcs.length > 0 || Boolean(state.currentEncounter);
|
||||
}
|
||||
|
||||
export function buildEncounterEntryState(
|
||||
finalState: GameState,
|
||||
entryX: number,
|
||||
): GameState {
|
||||
if (finalState.sceneHostileNpcs.length > 0) {
|
||||
const anchorX = getMonsterGroupAnchorX(finalState.sceneHostileNpcs);
|
||||
return {
|
||||
...finalState,
|
||||
sceneHostileNpcs: finalState.sceneHostileNpcs.map(monster => {
|
||||
const offset = monster.xMeters - anchorX;
|
||||
const xMeters = roundMeters(entryX + offset);
|
||||
return {
|
||||
...monster,
|
||||
xMeters,
|
||||
animation: 'move' as const,
|
||||
facing: getFacingTowardPlayer(xMeters, PLAYER_BASE_X_METERS),
|
||||
};
|
||||
}),
|
||||
currentEncounter: null,
|
||||
};
|
||||
}
|
||||
|
||||
if (finalState.currentEncounter) {
|
||||
return {
|
||||
...finalState,
|
||||
currentEncounter: {
|
||||
...finalState.currentEncounter,
|
||||
xMeters: entryX,
|
||||
},
|
||||
sceneHostileNpcs: [],
|
||||
};
|
||||
}
|
||||
|
||||
return finalState;
|
||||
}
|
||||
|
||||
export function buildEncounterTransitionState(
|
||||
finalState: GameState,
|
||||
sourceState: Pick<GameState, 'sceneHostileNpcs' | 'currentEncounter'>,
|
||||
): GameState {
|
||||
if (finalState.sceneHostileNpcs.length > 0) {
|
||||
const sourceById = new Map(sourceState.sceneHostileNpcs.map(monster => [monster.id, monster]));
|
||||
return {
|
||||
...finalState,
|
||||
sceneHostileNpcs: finalState.sceneHostileNpcs.map(monster => {
|
||||
const sourceMonster = sourceById.get(monster.id);
|
||||
const xMeters = sourceMonster?.xMeters ?? monster.xMeters;
|
||||
return {
|
||||
...monster,
|
||||
xMeters,
|
||||
animation: 'move' as const,
|
||||
facing: getFacingTowardPlayer(xMeters, PLAYER_BASE_X_METERS),
|
||||
};
|
||||
}),
|
||||
currentEncounter: null,
|
||||
};
|
||||
}
|
||||
|
||||
if (finalState.currentEncounter) {
|
||||
return {
|
||||
...finalState,
|
||||
currentEncounter: {
|
||||
...finalState.currentEncounter,
|
||||
xMeters: sourceState.currentEncounter?.xMeters ?? finalState.currentEncounter.xMeters,
|
||||
},
|
||||
sceneHostileNpcs: [],
|
||||
};
|
||||
}
|
||||
|
||||
return finalState;
|
||||
}
|
||||
|
||||
export function interpolateEncounterTransitionState(
|
||||
startState: Pick<GameState, 'sceneHostileNpcs' | 'currentEncounter'>,
|
||||
finalState: GameState,
|
||||
progress: number,
|
||||
): GameState {
|
||||
if (finalState.sceneHostileNpcs.length > 0) {
|
||||
const startById = new Map(startState.sceneHostileNpcs.map(monster => [monster.id, monster]));
|
||||
return {
|
||||
...finalState,
|
||||
sceneHostileNpcs: finalState.sceneHostileNpcs.map(monster => {
|
||||
const startMonster = startById.get(monster.id);
|
||||
const xMeters = lerp(startMonster?.xMeters ?? monster.xMeters, monster.xMeters, progress);
|
||||
return {
|
||||
...monster,
|
||||
xMeters,
|
||||
animation: progress < 1 ? ('move' as const) : monster.animation,
|
||||
facing: getFacingTowardPlayer(xMeters, PLAYER_BASE_X_METERS),
|
||||
};
|
||||
}),
|
||||
currentEncounter: null,
|
||||
};
|
||||
}
|
||||
|
||||
if (finalState.currentEncounter) {
|
||||
const startX = startState.currentEncounter?.xMeters ?? finalState.currentEncounter.xMeters ?? 0;
|
||||
const endX = finalState.currentEncounter.xMeters ?? startX;
|
||||
return {
|
||||
...finalState,
|
||||
currentEncounter: {
|
||||
...finalState.currentEncounter,
|
||||
xMeters: lerp(startX, endX, progress),
|
||||
},
|
||||
sceneHostileNpcs: [],
|
||||
};
|
||||
}
|
||||
|
||||
return finalState;
|
||||
}
|
||||
Reference in New Issue
Block a user