72 lines
2.8 KiB
TypeScript
72 lines
2.8 KiB
TypeScript
// ---------------------------------------------------------------------------
|
|
// Shared game constants & helpers (used by both the server sim and the client)
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export const TICK_RATE = 30; // server simulation ticks per second
|
|
export const SNAP_EVERY = 2; // send a snapshot every N ticks (15 Hz)
|
|
|
|
export const ARENA_RADIUS = 4200; // playable circle radius in world px
|
|
|
|
export const BASE_SPEED = 178; // px per second
|
|
export const BOOST_MULT = 1.95; // speed multiplier while boosting
|
|
export const TURN_RATE = 4.4; // radians per second
|
|
export const BOOST_TURN_RATE = 3.8; // slightly stiffer steering while boosting
|
|
|
|
export const START_SCORE = 25;
|
|
export const MIN_BOOST_SCORE = 18; // cannot boost below this score
|
|
export const BOOST_DRAIN = 16; // score per second burned while boosting
|
|
export const BOOST_DROP_INTERVAL = 0.26; // seconds between tail pellets while boosting
|
|
|
|
export const PELLET_COUNT = 950; // ambient pellets kept alive in the arena
|
|
export const BOT_TARGET_TOTAL = 12; // arena is kept filled to this many snakes
|
|
export const RESPAWN_PROTECT_TICKS = TICK_RATE * 2; // ~2s of spawn protection
|
|
|
|
// --- derived snake geometry -------------------------------------------------
|
|
|
|
export function snakeRadius(score: number): number {
|
|
return 5 + Math.sqrt(Math.max(0, score)) * 0.32;
|
|
}
|
|
|
|
export function snakePointCount(score: number): number {
|
|
return Math.min(420, Math.round(14 + Math.sqrt(Math.max(0, score)) * 2.1));
|
|
}
|
|
|
|
export function snakeSpacing(score: number): number {
|
|
return Math.max(5.5, snakeRadius(score) * 0.5);
|
|
}
|
|
|
|
// --- math helpers ------------------------------------------------------------
|
|
|
|
export function clamp(v: number, lo: number, hi: number): number {
|
|
return v < lo ? lo : v > hi ? hi : v;
|
|
}
|
|
|
|
/** Normalize an angle to (-PI, PI]. */
|
|
export function normAngle(a: number): number {
|
|
while (a > Math.PI) a -= Math.PI * 2;
|
|
while (a <= -Math.PI) a += Math.PI * 2;
|
|
return a;
|
|
}
|
|
|
|
export function dist(x1: number, y1: number, x2: number, y2: number): number {
|
|
return Math.hypot(x2 - x1, y2 - y1);
|
|
}
|
|
|
|
// --- palettes ---------------------------------------------------------------
|
|
|
|
export const SNAKE_COLORS = [
|
|
'#ff5b5b', '#ffb84d', '#ffe14d', '#7dff5b', '#4dffd2', '#4dc9ff',
|
|
'#8a7dff', '#c95bff', '#ff5bd0', '#9dff4d', '#5bff9d', '#ffd24d',
|
|
];
|
|
|
|
export const PELLET_COLORS = [
|
|
'#ff6b6b', '#ffd93d', '#6bff8f', '#4dd2ff',
|
|
'#c586ff', '#ff8fe1', '#8ffcff', '#ffe28f',
|
|
];
|
|
|
|
export const BOT_NAMES = [
|
|
'Noodle', 'Viper', 'Slinky', 'Zigzag', 'Cobra', 'Python', 'Nagini',
|
|
'Basilisk', 'Wiggles', 'Turbo', 'Boa', 'Rattles', 'Medusa',
|
|
'Sidewinder', 'Anaconda', 'DangerNoodle', 'Hiss', 'Monty',
|
|
];
|