3.9: Оновлення головного файлу
Що ми будемо робити?
У цьому підрозділі ми оновимо файл main.js
для інтеграції всіх нових компонентів уроку 3: системи керування, стрільби, руху та колізій.
Оновлення файлу main.js
Оновіть файл main.js
:
javascript
/**
* 🎮 Головний файл гри - Танчики
*
* Урок 3: Рух та стрільба
*
* Відповідає за:
* - Ініціалізацію всіх компонентів гри
* - Запуск ігрового циклу
* - Управління станом гри
*/
// Отримуємо Canvas та контекст
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
// Конфігурація гри
export const GAME_CONFIG = {
// Розміри Canvas
CANVAS_WIDTH: 800,
CANVAS_HEIGHT: 600,
// Розмір тайла
TILE_SIZE: 32,
// Налаштування гри
GAME_SPEED: 60, // FPS
DEBUG_MODE: false
};
// Імпортуємо всі необхідні класи
import { Game } from './Game.js';
import { GameLogger } from './GameLogger.js';
import { InputManager } from './InputManager.js';
// Глобальні змінні
let game;
let logger;
let inputManager;
/**
* Ініціалізація гри
*/
function initGame() {
console.log('🎮 Ініціалізація гри...');
// Створюємо логер
logger = new GameLogger('logContent');
// Створюємо систему керування
inputManager = new InputManager();
// Створюємо гру
game = new Game();
// Підключаємо систему керування до гравця
game.player.setInputManager(inputManager);
// Встановлюємо межі руху
game.player.setBounds({
maxX: GAME_CONFIG.CANVAS_WIDTH,
maxY: GAME_CONFIG.CANVAS_HEIGHT
});
game.enemy.setBounds({
maxX: GAME_CONFIG.CANVAS_WIDTH,
maxY: GAME_CONFIG.CANVAS_HEIGHT
});
// Встановлюємо ціль для ворога
game.enemy.setTarget(game.player);
// Налаштовуємо стрільбу
game.player.setShootCooldown(500); // 500мс між пострілами
game.enemy.setShootCooldown(2000); // 2 секунди між пострілами
game.enemy.setShootingAccuracy(0.8); // 80% точність
// Налаштовуємо пошкодження
game.player.setDamageResistance(0.1); // 10% стійкості
game.enemy.setDamageResistance(0.05); // 5% стійкості
// Прослуховуємо події гри
setupGameEvents();
// Запускаємо гру
game.start();
logger.info('🎮 Гра успішно ініціалізована!');
logger.info('⌨️ Керування: WASD для руху, Пробіл для стрільби, P для паузи');
}
/**
* Налаштування подій гри
*/
function setupGameEvents() {
// Подія паузи
document.addEventListener('gamePause', (event) => {
if (event.detail.isPaused) {
game.pause();
logger.warning('⏸️ Гра призупинена');
} else {
game.resume();
logger.info('▶️ Гра відновлена');
}
});
// Подія перезапуску
document.addEventListener('gameRestart', () => {
restartGame();
});
// Подія налагодження
document.addEventListener('gameDebug', () => {
toggleDebugMode();
});
// Подія завершення гри
document.addEventListener('gameOver', (event) => {
handleGameOver(event.detail);
});
}
/**
* Перезапуск гри
*/
function restartGame() {
logger.info('🔄 Перезапуск гри...');
// Зупиняємо поточну гру
if (game) {
game.stop();
}
// Очищаємо лог
logger.clear();
// Перезапускаємо гру
setTimeout(() => {
initGame();
}, 100);
}
/**
* Перемикання режиму налагодження
*/
function toggleDebugMode() {
GAME_CONFIG.DEBUG_MODE = !GAME_CONFIG.DEBUG_MODE;
if (GAME_CONFIG.DEBUG_MODE) {
logger.warning('🐛 Режим налагодження увімкнено');
showDebugInfo();
} else {
logger.info('🐛 Режим налагодження вимкнено');
hideDebugInfo();
}
}
/**
* Показ інформації для налагодження
*/
function showDebugInfo() {
// Створюємо панель налагодження
let debugPanel = document.getElementById('debugPanel');
if (!debugPanel) {
debugPanel = document.createElement('div');
debugPanel.id = 'debugPanel';
debugPanel.style.cssText = `
position: fixed;
top: 10px;
left: 10px;
background: rgba(0, 0, 0, 0.8);
color: white;
padding: 10px;
border-radius: 5px;
font-family: monospace;
font-size: 12px;
z-index: 1000;
`;
document.body.appendChild(debugPanel);
}
// Оновлюємо інформацію кожен кадр
function updateDebugInfo() {
if (!GAME_CONFIG.DEBUG_MODE || !game) return;
const player = game.player;
const enemy = game.enemy;
const collisionStats = game.getCollisionStats();
debugPanel.innerHTML = `
<div><strong>🐛 DEBUG INFO</strong></div>
<div>FPS: ${Math.round(1000 / game.getDeltaTime())}</div>
<div>Гравець: (${Math.round(player.x)}, ${Math.round(player.y)})</div>
<div>Здоров'я: ${player.getHealth()}/${player.getMaxHealth()}</div>
<div>Кулі: ${player.getBullets().length}</div>
<div>Ворог: (${Math.round(enemy.x)}, ${Math.round(enemy.y)})</div>
<div>Здоров'я: ${enemy.getHealth()}/${enemy.getMaxHealth()}</div>
<div>Стан AI: ${enemy.getAIState().state}</div>
<div>Кулі: ${enemy.getBullets().length}</div>
<div>Колізії: ${collisionStats.totalCollisions}</div>
`;
requestAnimationFrame(updateDebugInfo);
}
updateDebugInfo();
}
/**
* Приховування інформації для налагодження
*/
function hideDebugInfo() {
const debugPanel = document.getElementById('debugPanel');
if (debugPanel) {
debugPanel.remove();
}
}
/**
* Обробка завершення гри
* @param {Object} gameOverData - Дані про завершення гри
*/
function handleGameOver(gameOverData) {
const { winner, reason } = gameOverData;
logger.warning(`🏁 Гра завершена! ${reason}`);
if (winner === 'player') {
logger.success('🎉 Гравець переміг!');
} else if (winner === 'enemy') {
logger.error('💀 Ворог переміг!');
}
// Показуємо кнопку перезапуску
showRestartButton();
}
/**
* Показ кнопки перезапуску
*/
function showRestartButton() {
let restartBtn = document.getElementById('restartButton');
if (!restartBtn) {
restartBtn = document.createElement('button');
restartBtn.id = 'restartButton';
restartBtn.textContent = '🔄 Перезапустити гру';
restartBtn.style.cssText = `
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
padding: 15px 30px;
font-size: 18px;
background: #e74c3c;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
z-index: 1000;
`;
restartBtn.addEventListener('click', restartGame);
document.body.appendChild(restartBtn);
}
restartBtn.style.display = 'block';
}
/**
* Функція очищення логу
*/
function clearLog() {
if (logger) {
logger.clear();
}
}
/**
* Отримання статистики гри
* @returns {Object} - Статистика
*/
function getGameStats() {
if (!game) return null;
return {
player: {
health: game.player.getHealth(),
maxHealth: game.player.getMaxHealth(),
bullets: game.player.getBullets().length,
position: { x: game.player.x, y: game.player.y }
},
enemy: {
health: game.enemy.getHealth(),
maxHealth: game.enemy.getMaxHealth(),
bullets: game.enemy.getBullets().length,
position: { x: game.enemy.x, y: game.enemy.y },
aiState: game.enemy.getAIState()
},
collisions: game.getCollisionStats(),
gameTime: game.getGameTime()
};
}
// Експортуємо глобальні змінні для використання в інших модулях
export { canvas, ctx, GAME_CONFIG, logger };
// Функція очищення логу (глобальна)
window.clearLog = clearLog;
// Функція отримання статистики (глобальна)
window.getGameStats = getGameStats;
// Запускаємо гру після завантаження DOM
document.addEventListener('DOMContentLoaded', () => {
console.log('🚀 Запуск гри Танчики - Урок 3');
initGame();
});
// Обробка помилок
window.addEventListener('error', (event) => {
console.error('❌ Помилка гри:', event.error);
if (logger) {
logger.error(`Помилка: ${event.error.message}`);
}
});
// Обробка завершення роботи сторінки
window.addEventListener('beforeunload', () => {
if (game) {
game.stop();
}
console.log('👋 Гра завершена');
});
Що оновлено в main.js?
Нові імпорти:
InputManager
- система керування- Оновлені класи з новою функціональністю
Нові функції:
setupGameEvents()
- налаштування подій гриrestartGame()
- перезапуск гриtoggleDebugMode()
- перемикання режиму налагодженняshowDebugInfo()
- показ інформації для налагодженняhandleGameOver()
- обробка завершення гриgetGameStats()
- отримання статистики
Нові налаштування:
- Система керування підключена до гравця
- Межі руху для обох танків
- Налаштування стрільби (затримки, точність)
- Система пошкоджень (стійкість)
- Ціль для ворога (гравець)
Система подій
Підтримувані події:
gamePause
- пауза/продовженняgameRestart
- перезапуск гриgameDebug
- режим налагодженняgameOver
- завершення гри
Обробка подій:
- Автоматичне логування всіх подій
- Візуальні індикатори стану
- Кнопка перезапуску при завершенні
Режим налагодження
Показувана інформація:
- FPS - частота кадрів
- Позиції гравця та ворога
- Здоров'я та кількість куль
- Стан AI ворога
- Статистика колізій
Керування:
- F12 - перемикання режиму
- Автоматичне оновлення кожен кадр
- Позиціонування в лівому верхньому куті
Глобальні функції
Доступні через window
:
clearLog()
- очищення логуgetGameStats()
- отримання статистики
Використання в консолі:
javascript
// Очистити лог
clearLog();
// Отримати статистику
const stats = getGameStats();
console.log(stats);
// Перезапустити гру
restartGame();
Результат
Після оновлення цього файлу у вас буде:
- ✅ Повноцінна гра з рухом та стрільбою
- ✅ Система керування клавішами
- ✅ Штучний інтелект ворога
- ✅ Система колізій та пошкоджень
- ✅ Режим налагодження
- ✅ Статистика та логування
Фінальна структура файлів
📁 battle_city_js_course
├── 📄 index.html # HTML сторінка з оновленим інтерфейсом
├── 📄 main.js # Головний файл (оновлений)
├── 📄 InputManager.js # Система керування (новий)
├── 📄 Bullet.js # Клас кулі (новий)
├── 📄 Player.js # Клас гравця (оновлений)
├── 📄 Enemy.js # Клас ворога (оновлений)
├── 📄 Tank.js # Базовий клас танка (оновлений)
├── 📄 GameField.js # Ігрове поле (оновлений)
├── 📄 GameLogger.js # Система логування (оновлений)
├── 📄 Game.js # Мотор гри (оновлений)
└── 📄 CollisionManager.js # Система колізій (новий)
Що далі?
🎉 Вітаємо! Ви успішно завершили Урок 3: Рух та стрільба!
У наступному уроці ми додамо:
- ✅ Вибухи та анімації
- ✅ Звукові ефекти
- ✅ Покращену графіку
- ✅ Додаткові можливості