import { Tileset } from "../Graphics/Tileset/tileset" import { Tank } from "../Tanks/tank"; import { Constants } from "../constants" import { BlockTypeEnum } from "../Blocks/blockTypeEnum" import { MapParser } from "../Graphics/Map/mapParser"; import { CollisionManager } from "./collisionManager"; import { AITankManager } from "./../Tanks/aiTankManager"; import { DirectionEnum } from "../Tanks/directionEnum"; import { SoundEnum, SoundManager } from "./soundManager"; import $ from 'jquery'; import { isThursday } from "date-fns"; export class GameField { /** * * @param {number} width * @param {number} height * @param {CanvasRenderingContext2D} ctx * @param {HTMLCanvasElement} canvas */ constructor(width = 512, height = 512, ctx, canvas) { this.height = height; this.width = width + 100; this.ctx = ctx; this.canvas = canvas; this.tileset = null; this.map = null; this.soundManager = new SoundManager(); this.collisionManager = new CollisionManager(this.soundManager); this.tank = new Tank(Constants.PLAYER_TANK_ID_IMAGE.getValue(), 0, 18 * 16, this.collisionManager); this.aiTanks = new AITankManager(this.collisionManager); this.collisionManager.setMainTank(this.tank); this.lastRequest = null; } //add all tiles here! async setupTileset() { this.tileset = new Tileset("nesBattle.png"); //Bricks this.tileset.addTile(512, 0, 32, 32, BlockTypeEnum.Brick); //Metal this.tileset.addTile(512, 32, 32, 32, BlockTypeEnum.Iron); //Eagle this.tileset.addTile(608, 64, 32, 32, BlockTypeEnum.Eagle); this.tileset.addTile(640, 64, 32, 32, BlockTypeEnum.DestroyedEagle); //River this.tileset.addTile(512, 64, 32, 32, BlockTypeEnum.River); //Forest this.tileset.addTile(544, 64, 32, 32, BlockTypeEnum.Forest); //Tank this.tileset.addTile(0, 2, 28, 30, Constants.PLAYER_TANK_ID_IMAGE.getValue() + DirectionEnum.Up.getValue()); this.tileset.addTile(64, 0, 28, 28, Constants.PLAYER_TANK_ID_IMAGE.getValue() + DirectionEnum.Left.getValue()); this.tileset.addTile(128, 0, 28, 28, Constants.PLAYER_TANK_ID_IMAGE.getValue() + DirectionEnum.Down.getValue()); this.tileset.addTile(192, 0, 28, 28, Constants.PLAYER_TANK_ID_IMAGE.getValue() + DirectionEnum.Right.getValue()); //Enemy tank this.tileset.addTile(256, 2, 28, 30, 200 + DirectionEnum.Up.getValue()); this.tileset.addTile(320, 0, 28, 28, 200 + DirectionEnum.Left.getValue()); this.tileset.addTile(386, 0, 28, 28, 200 + DirectionEnum.Down.getValue()); this.tileset.addTile(452, 0, 28, 28, 200 + DirectionEnum.Right.getValue()); this.tileset.addTile(512, 8 * 32, 32, 32, BlockTypeEnum.Explosion1); this.tileset.addTile(544, 8 * 32, 32, 32, BlockTypeEnum.Explosion2); this.tileset.addTile(576, 8 * 32, 32, 32, BlockTypeEnum.Explosion3); await this.tileset.loadAll(); } async prepareGame(level) { if (!this.tileset) { await this.setupTileset(); } this.map = await new MapParser().getMap(level, this.tileset); this.canvas.height = this.height; this.canvas.width = this.width; this.collisionManager.attachMap(this.map); this.aiTanks.setCount(this.map._enemiesCount); } async play(level, firstTime) { this.ctx.clearRect(0, 0, this.width, this.height); this.tank.deathCount = 20; this.tank.isDestroyed = false; this.tank.x = Constants.TANK_DEFAULT_SPAWN_X.getValue(); this.tank.y = Constants.TANK_DEFAULT_SPAWN_Y.getValue(); this.aiTanks._activeTanks = []; this.collisionManager._aiTanks = []; $(".loading").show(); $(".text-loading").show(); $(".start-level-button").hide(); await this.prepareGame(level); if (this.map == null) { this.prepareGame(1); } $(".text-loading").hide(); $(".start-level-button").show(); if (firstTime) { $(".start-level-button").on("click", () => { $(".loading").hide(); this.soundManager.playSound(SoundEnum.GameStart); requestAnimationFrame(() => this.gameLoop()); }) } else { $(".loading").hide(); requestAnimationFrame(() => this.gameLoop()); } } lose() { this.soundManager.playSound(SoundEnum.GameOver); requestAnimationFrame(() => this.drawFieldRecursive()) setTimeout(() => { cancelAnimationFrame(this.lastRequest); this.lastRequest = undefined; this.play(1, false); }, 2000); } win() { cancelAnimationFrame(this.lastRequest); this.lastRequest = undefined; setTimeout(() => { this.play(this.map.mapLevel + 1, false); }, 2000); } async gameLoop() { if (this.map.getEagle().isDestroyed()) { this.lose(); return; } if (this.aiTanks.isAllTanksDied()) { this.win(); return; } if (this.tank.canBeErased()) { this.lose(); return; } this.drawField(); this.lastRequest = requestAnimationFrame(() => this.gameLoop()); } drawFieldRecursive() { this.drawField(); this.lastRequest = requestAnimationFrame(() => this.drawFieldRecursive()); } drawField() { let lateDraw = []; for (let x = 0; x < this.map.width; x += 1) { for (let y = 0; y < this.map.height; y += 1) { this.ctx.fillStyle = "black"; this.ctx.fillRect(x * Constants.TILE_SIZE.getValue(), y * Constants.TILE_SIZE.getValue(), Constants.TILE_SIZE.getValue(), Constants.TILE_SIZE.getValue()); let element = this.map.getElement(x, y); if (element.getType() == BlockTypeEnum.Forest) { lateDraw.push({ element, x, y }); } else { element.draw(this.ctx, x * Constants.TILE_SIZE.getValue(), y * Constants.TILE_SIZE.getValue()); } } } this.tank.draw(this.tileset, this.ctx); this.aiTanks.drawAllTanks(this.tileset, this.ctx); for (let el of lateDraw) { el.element.draw(this.ctx, el.x * Constants.TILE_SIZE.getValue(), el.y * Constants.TILE_SIZE.getValue()); } this.drawPanel(); } drawPanel() { this.ctx.fillStyle = "black"; this.ctx.fillRect(this.width - 90, 0, 90, 100); this.ctx.font = "20px VT323, sans-serif"; this.ctx.fillStyle = "white"; this.ctx.fillText("Level: " + this.map.mapLevel, this.width - 90, 20); this.ctx.fillText("Tanks: " + this.aiTanks._count, this.width - 90, 50); } }