173 lines
11 KiB
TypeScript
173 lines
11 KiB
TypeScript
/**
|
|
* config.ts — ВСЕ настройки игры в одном месте.
|
|
*
|
|
* Здесь сосредоточены: размеры мира, геометрия комнат/дверей и баланс
|
|
* (скорости, здоровье, перезарядки). Меняй числа тут, чтобы «крутить»
|
|
* игру — больше ничего трогать не нужно.
|
|
*
|
|
* ВАЖНО: единица времени — один «шаг» симуляции (= 1/60 секунды), а НЕ
|
|
* кадр браузера. Цикл игры (см. engine/GameLoop.ts) гарантирует ровно
|
|
* 60 шагов в секунду на любом мониторе, поэтому скорости заданы «пикселей
|
|
* за шаг», а перезарядки — «в шагах».
|
|
*/
|
|
|
|
// ─────────────────────────────────────────────────────────────
|
|
// Холст и сетка
|
|
// ─────────────────────────────────────────────────────────────
|
|
export const CW = 880; // ширина области отрисовки (px)
|
|
export const CH = 660; // высота области отрисовки (px)
|
|
export const TILE = 44; // размер одного тайла (px)
|
|
export const COLS = 15; // тайлов по горизонтали в комнате
|
|
export const ROWS = 11; // тайлов по вертикали в комнате
|
|
export const RW = COLS * TILE; // ширина комнаты в пикселях
|
|
export const RH = ROWS * TILE; // высота комнаты в пикселях
|
|
export const OX = (CW - RW) / 2; // отступ комнаты слева
|
|
export const OY = 80; // отступ комнаты сверху (место под HUD)
|
|
|
|
// Частота симуляции. Логика всегда обновляется с этим шагом.
|
|
export const FIXED_FPS = 60;
|
|
export const FIXED_DT = 1 / FIXED_FPS; // секунд на шаг
|
|
|
|
export const GAME_LOOP = {
|
|
maxFrameTimeSec: 0.25, // не «отыгрывать» долгие паузы (фон/таб)
|
|
maxStepsPerFrame: 5, // защита от «спирали смерти» при лагах
|
|
};
|
|
|
|
// ─────────────────────────────────────────────────────────────
|
|
// Типы тайлов
|
|
// ─────────────────────────────────────────────────────────────
|
|
export const T_WALL = 0;
|
|
export const T_FLOOR = 1;
|
|
export const T_DOOR = 2;
|
|
|
|
// ─────────────────────────────────────────────────────────────
|
|
// Режимы боя
|
|
// ─────────────────────────────────────────────────────────────
|
|
export const MODE_RANGED = 0;
|
|
export const MODE_MELEE = 1;
|
|
|
|
// ─────────────────────────────────────────────────────────────
|
|
// Направления
|
|
// ─────────────────────────────────────────────────────────────
|
|
import type { Dir } from './core/types';
|
|
|
|
/** Единичный вектор смещения для каждого направления (x вправо, y вниз). */
|
|
export const DIR: Record<Dir, readonly [number, number]> = {
|
|
up: [0, -1],
|
|
down: [0, 1],
|
|
left: [-1, 0],
|
|
right: [1, 0],
|
|
};
|
|
|
|
/** Противоположное направление. Используется при простановке дверей соседей. */
|
|
export const OPP: Record<Dir, Dir> = {
|
|
up: 'down',
|
|
down: 'up',
|
|
left: 'right',
|
|
right: 'left',
|
|
};
|
|
|
|
/**
|
|
* Геометрия дверей: проём шириной в 3 тайла по центру каждой стороны.
|
|
* cx/cy — координата тайла-центра двери (для спавна игрока и расчётов).
|
|
*/
|
|
export const DOOR = {
|
|
up: { cols: [6, 7, 8] as number[], row: 0, cx: 7, cy: 0 },
|
|
down: { cols: [6, 7, 8] as number[], row: ROWS - 1, cx: 7, cy: ROWS - 1 },
|
|
left: { col: 0, rows: [4, 5, 6] as number[], cx: 0, cy: 5 },
|
|
right: { col: COLS - 1, rows: [4, 5, 6] as number[], cx: COLS - 1, cy: 5 },
|
|
};
|
|
|
|
// ─────────────────────────────────────────────────────────────
|
|
// Генерация карты (случайное блуждание)
|
|
// ─────────────────────────────────────────────────────────────
|
|
export const MAP_RADIUS = 3; // карта вмещается в сетку (2*R+1)²
|
|
export const MIN_ROOMS = 8; // минимум комнат
|
|
export const EXTRA_ROOMS = 4; // + случайно до этого числа
|
|
|
|
// ─────────────────────────────────────────────────────────────
|
|
// Баланс: игрок
|
|
// ─────────────────────────────────────────────────────────────
|
|
export const PLAYER = {
|
|
size: 26,
|
|
speed: 3.2, // px за шаг
|
|
maxHp: 6,
|
|
invFrames: 60, // неуязвимость после удара, в шагах
|
|
entryInvFrames: 20, // короткая неуязвимость при входе в комнату, в шагах
|
|
rangedCooldown: 10, // перезарядка выстрела, в шагах
|
|
meleeCooldown: 22, // перезарядка удара ближнего боя, в шагах
|
|
transitionLock: 15, // блок повторного перехода между комнатами, в шагах
|
|
};
|
|
|
|
// ─────────────────────────────────────────────────────────────
|
|
// Баланс: снаряд (слеза) и ближний бой
|
|
// ─────────────────────────────────────────────────────────────
|
|
export const PROJECTILE = {
|
|
radius: 5,
|
|
speed: 7, // px за шаг
|
|
damage: 1,
|
|
life: 80, // время жизни в шагах
|
|
};
|
|
|
|
export const MELEE = {
|
|
reach: 22, // отступ хитбокса от центра игрока
|
|
size: 50, // сторона квадратного хитбокса
|
|
life: 10, // длительность взмаха в шагах
|
|
damage: 2,
|
|
knockback: 10,
|
|
};
|
|
|
|
// ─────────────────────────────────────────────────────────────
|
|
// Баланс: враги (таблица характеристик по типу)
|
|
// ─────────────────────────────────────────────────────────────
|
|
export const ENEMY_STATS = {
|
|
normal: { size: 32, hp: 3, speed: 1.15, damage: 1 },
|
|
fast: { size: 26, hp: 2, speed: 1.9, damage: 1 },
|
|
boss: { size: 46, hp: 10, speed: 0.9, damage: 2 },
|
|
charger: { size: 32, hp: 5, speed: 1.6, damage: 1 },
|
|
tank: { size: 44, hp: 10, speed: 0.6, damage: 2 },
|
|
shooter: { size: 28, hp: 3, speed: 1.0, damage: 1 },
|
|
} as const;
|
|
|
|
export const ENEMY = {
|
|
aggroRange: 500, // дистанция, с которой враг начинает преследование
|
|
attackCooldown: 30, // пауза между контактными ударами, в шагах
|
|
hitFlash: 8, // длительность «мигания» при попадании, в шагах
|
|
knockbackDecay: 0.85,
|
|
fastChance: 0.3, // доля быстрых врагов в обычной комнате
|
|
};
|
|
|
|
// ─────────────────────────────────────────────────────────────
|
|
// Спавн врагов
|
|
// ─────────────────────────────────────────────────────────────
|
|
export const SPAWN = {
|
|
normalMin: 2, // минимум врагов в обычной комнате
|
|
normalExtra: 2, // + случайно до этого числа
|
|
minDistFromDoor: 180, // не спавнить ближе к двери входа
|
|
minDistFromPlayer: 150,
|
|
minDistBetween: 60,
|
|
maxPlacementTries: 100,
|
|
treasureChance: 0.12, // шанс комнаты-сокровищницы
|
|
bossChance: 0.2, // шанс назначить комнату боссом
|
|
};
|
|
|
|
// ─────────────────────────────────────────────────────────────
|
|
// Сундук (сокровищница)
|
|
// ─────────────────────────────────────────────────────────────
|
|
export const CHEST = {
|
|
size: 40,
|
|
hp: 5,
|
|
};
|
|
|
|
// ─────────────────────────────────────────────────────────────
|
|
// Масштабирование этажей (New Game+)
|
|
// ─────────────────────────────────────────────────────────────
|
|
export const FLOOR_SCALING = {
|
|
roomsPerFloor: 2, // + комнат на этаж
|
|
hpMulPerFloor: 0.15, // + множитель HP врагов на этаж
|
|
speedMulPerFloor: 0.05, // + множитель скорости на этаж
|
|
densityMulPerFloor: 0.1, // + множитель плотности на этаж
|
|
bossHpMulPerFloor: 0.2, // + множитель HP босса на этаж
|
|
fastChancePerFloor: 0.03, // + доля быстрых врагов на этаж
|
|
};
|