«Танчики» на HTML5
Состояния игры и графика
Изначально этим этапом должны были быть только состояния (начало пауза, геймовер), но так как два из трёх состояний я сделал ещё в прошлом этапе, то тут я добавил паузу, заготовку для главного меню и решил, что этого мало и перешёл сразу к следующему этапу, а именно замена временных квадратов на спрайты. Я решил не использовать то, что выдаёт там интернет, но постарался сам нарисовать близко по стилистике
По спецификациям спрайтов: сделал по два кадра на все танки, чтоб сделать анимацию гусениц. три кадра на воду. остальные по одному кадру
Вообще вот столько спрайтшитов отрисовал:
Результат сейчас выглядит вот так
Для водички отдельная функция появилась:
export function updateWaterAnimation() {
waterAnimationFrame = (waterAnimationFrame + 1) % WATER_SPRITE.frameCount;
}
//Ну и в рисовании фона вода теперь принимает непосредственное участие в отрисовки фона
renderBackground(gameMap, getWaterAnimationFrame());
//И внутри рендера ещё добавлен фолбек, чтобы в случае чего рисовать квадратики, как раньше.
//Чтоб не получилось что и-за какой-то ошибки на экране будет пустой квадрат
// Попробуем отрисовать спрайт
const spriteDrawn = renderTileSprite(
ctx, tileId, x, y, px, py, size,
gameMap, wallsSprite, waterSprite, forestIceSprite, waterFrame
);
// Если спрайт не нарисован - fallback на цветной квадрат
if (!spriteDrawn) {
renderTileFallback(ctx, tileDef, x, y, px, py, size, gameMap);
}
Конфигурация эффектов так же содержит фолбэк
/**
* Конфигурация эффектов
*/
const EFFECT_CONFIG = {
[EffectType.EXPLOSION_SMALL]: {
maxFrames: EXPLOSION_SMALL_SPRITE.frameCount, // 3 кадра
frameTime: 3, // 3 игровых кадра на кадр анимации (100ms при 30 FPS)
size: TANK_SIZE, // 16x16
colors: ['#FFFF00', '#FFA500', '#FF4500'] // Fallback: Жёлтый → оранжевый → красный
},
[EffectType.EXPLOSION_BIG]: {
maxFrames: EXPLOSION_BIG_SPRITE.frameCount, // 4 кадра
frameTime: 3,
size: TANK_SIZE, // 16x16
colors: ['#FFFFFF', '#FFFF00', '#FFA500', '#FF4500'] // Fallback
},
[EffectType.SPAWN]: {
maxFrames: SPAWN_SPRITE.frameCount, // 5 кадров
frameTime: 4,
size: TANK_SIZE, // 16x16
colors: ['#FFFFFF', '#AAAAAA', '#FFFFFF', '#AAAAAA', '#FFFFFF'] // Fallback: Мигание
}
};
Размер тут, правда, как будто излишен, так как все спрайты 16 на 16 и не пока не вижу необходимости делать другие, но посмотрю, может появился необходимость делать что-то больше чем 1 клетка размером, если нет, удалю.
Дальше по состояниям. В main.js появился метод и много его вызовов:
if (uiActions.pause) {
setState(GameState.PAUSED);
}
export function setState(newState) {
if (currentState === newState) return;
const oldState = currentState;
console.log(`State: ${oldState} -> ${newState}`);
currentState = newState;
stateTimer = 0;
// Вызываем callback если установлен
if (onStateChangeCallback) {
onStateChangeCallback(newState, oldState);
}
}
export function setOnStateChange(callback) {
onStateChangeCallback = callback;
}
// Последний метод вызывается один раз при инициализации:
setOnStateChange(handleStateChange);
function handleStateChange(newState, oldState) {
// При переходе из STAGE_COMPLETE в STAGE_INTRO (по таймеру) — инициализируем уровень
if (oldState === GameState.STAGE_COMPLETE && newState === GameState.STAGE_INTRO) {
initializeLevel(getCurrentStage());
}
}
// это нам пригодится в будущем
План действий
Да!!!!!!!
А если мышь дать, всё равно сточат )
Правильнее вырезаны))
Вырезал мелкими резцами по дереву