Zones 20 and 40 now push everything rightward for the first 20 seconds of their chase, forcing the player to tap left to stay on screen. Added a main menu (new game / continue / skins), an in-game pause menu, and a skins system that unlocks permanent stat bonuses (speed, damage, HP, crystal/dark-matter/droid multipliers) as the player's max zone reached increases. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D5SuZW1XGCkahPX7cHMoRP
178 lines
3.2 KiB
TypeScript
178 lines
3.2 KiB
TypeScript
export type UpgradeKey = 'crystal' | 'speed' | 'damage' | 'droid' | 'vitality';
|
|
|
|
export type BossType = 'melee' | 'missile' | 'bomb' | 'laser';
|
|
|
|
export interface CrystalEntity {
|
|
id: number;
|
|
x: number;
|
|
y: number;
|
|
value: number;
|
|
radius: number;
|
|
rotation: number;
|
|
spin: number;
|
|
jitter: number[];
|
|
}
|
|
|
|
export interface EnemyEntity {
|
|
id: number;
|
|
x: number;
|
|
y: number;
|
|
hp: number;
|
|
maxHp: number;
|
|
speed: number;
|
|
radius: number;
|
|
isBoss: boolean;
|
|
state: 'chase' | 'fight';
|
|
wanderAngle: number;
|
|
jitter: number[];
|
|
hitFlash: number;
|
|
}
|
|
|
|
export interface DroidEntity {
|
|
id: number;
|
|
angleOffset: number;
|
|
cooldown: number;
|
|
laserTimer: number;
|
|
}
|
|
|
|
export interface AsteroidEntity {
|
|
id: number;
|
|
x: number;
|
|
y: number;
|
|
vx: number;
|
|
speed: number;
|
|
radius: number;
|
|
rotation: number;
|
|
spin: number;
|
|
jitter: number[];
|
|
}
|
|
|
|
export interface GoldenAsteroidEntity {
|
|
id: number;
|
|
x: number;
|
|
y: number;
|
|
vx: number;
|
|
vy: number;
|
|
radius: number;
|
|
rotation: number;
|
|
jitter: number[];
|
|
}
|
|
|
|
export interface BossProjectile {
|
|
id: number;
|
|
x: number;
|
|
y: number;
|
|
vx: number;
|
|
vy: number;
|
|
radius: number;
|
|
}
|
|
|
|
export interface BossBomb {
|
|
x: number;
|
|
y: number;
|
|
radius: number;
|
|
state: 'telegraph' | 'boom';
|
|
timer: number;
|
|
}
|
|
|
|
export type ChaseKind = 'cruiser' | 'swarm';
|
|
|
|
export interface FuelCellEntity {
|
|
id: number;
|
|
x: number;
|
|
y: number;
|
|
radius: number;
|
|
rotation: number;
|
|
spin: number;
|
|
jitter: number[];
|
|
}
|
|
|
|
export interface ChaseProjectile {
|
|
id: number;
|
|
kind: 'laser' | 'plasma';
|
|
x: number;
|
|
y: number;
|
|
vx: number;
|
|
vy: number;
|
|
radius: number;
|
|
}
|
|
|
|
export interface Particle {
|
|
x: number;
|
|
y: number;
|
|
vx: number;
|
|
vy: number;
|
|
life: number;
|
|
maxLife: number;
|
|
size: number;
|
|
color: string;
|
|
}
|
|
|
|
export interface FloatingText {
|
|
x: number;
|
|
y: number;
|
|
vy: number;
|
|
life: number;
|
|
maxLife: number;
|
|
text: string;
|
|
color: string;
|
|
}
|
|
|
|
export interface LoreEntry {
|
|
zone: number;
|
|
title: string;
|
|
text: string;
|
|
}
|
|
|
|
export type SkinBonusType = 'speed' | 'damage' | 'hp' | 'crystalMult' | 'darkMatterMult' | 'droidDamageMult';
|
|
|
|
export interface SkinDef {
|
|
id: string;
|
|
name: string;
|
|
unlockZone: number;
|
|
bonusType: SkinBonusType;
|
|
bonusValue: number;
|
|
primary: string;
|
|
secondary: string;
|
|
accent: string;
|
|
}
|
|
|
|
export interface GameSnapshot {
|
|
score: number;
|
|
zone: number;
|
|
crystalsInZone: number;
|
|
crystalsRequired: number;
|
|
darkMatter: number;
|
|
bossActive: boolean;
|
|
bossHp: number;
|
|
bossMaxHp: number;
|
|
pirateActive: boolean;
|
|
pirateHp: number;
|
|
pirateMaxHp: number;
|
|
levels: Record<UpgradeKey, number>;
|
|
costs: Record<UpgradeKey, number>;
|
|
canAfford: Record<UpgradeKey, boolean>;
|
|
droidCount: number;
|
|
canPrestige: boolean;
|
|
prestigeGain: number;
|
|
cutsceneActive: boolean;
|
|
loreActive: boolean;
|
|
loreEntry: LoreEntry | null;
|
|
knightHp: number;
|
|
knightMaxHp: number;
|
|
musicMuted: boolean;
|
|
chaseActive: boolean;
|
|
chaseKind: ChaseKind | null;
|
|
chaseFuelCells: number;
|
|
chaseFuelRequired: number;
|
|
chaseTimeRemaining: number;
|
|
chaseEngulfed: boolean;
|
|
chaseEscapeMeter: number;
|
|
chaseDriftActive: boolean;
|
|
chaseDriftRemaining: number;
|
|
paused: boolean;
|
|
maxZoneReached: number;
|
|
equippedSkin: string;
|
|
hasSave: boolean;
|
|
}
|