diff --git a/public/index.html b/public/index.html index dc135a1..8a321eb 100644 --- a/public/index.html +++ b/public/index.html @@ -7,6 +7,6 @@ - +
\ No newline at end of file diff --git a/src/Blocks/blockTypeEnum.js b/src/Blocks/blockTypeEnum.js index f4b07df..2178574 100644 --- a/src/Blocks/blockTypeEnum.js +++ b/src/Blocks/blockTypeEnum.js @@ -6,4 +6,10 @@ export class BlockTypeEnum { static Eagle = new BlockTypeEnum(); static DestroyedEagle = new BlockTypeEnum(); + + static Explosion1 = new BlockTypeEnum(); + static Explosion2 = new BlockTypeEnum(); + static Explosion3 = new BlockTypeEnum(); + + static ExplosionArray = [this.Explosion1, this.Explosion2, this.Explosion3]; } \ No newline at end of file diff --git a/src/GameLogic/collisionManager.js b/src/GameLogic/collisionManager.js index 8566e14..a57da27 100644 --- a/src/GameLogic/collisionManager.js +++ b/src/GameLogic/collisionManager.js @@ -1,29 +1,42 @@ import { BlockTypeEnum } from "../Blocks/blockTypeEnum"; import { Constants } from "../constants"; import { Map } from "../Graphics/Map/map"; -import { AITankManager } from "../Tanks/aiTankManager"; import { Tank } from "../Tanks/tank"; export class CollisionManager { /** - * @type {Map} _map + * @type {Map} */ _map; /** - * - * @param {Tank} tank - * @param {AITankManager} aiManager + * @type {Tank} */ - constructor(tank, aiManager) { - this._mainTank = tank; - this._aiManager = aiManager; - } + _mainTank; + + /** + * @type {Tank[]} + */ + _aiTanks = []; + attachMap(map) { this._map = map; } + setMainTank(tank) { + this._mainTank = tank; + } + + addNewAITank(tank) { + if (tank) + this._aiTanks.push(tank); + } + + deleteFromAITank() { + this._aiTanks = this._aiTanks.filter((e) => !e.canBeErased()); + } + checkCollisionForTank(xMin, xMax, yMin, yMax, tank) { if (!this._map) return false; @@ -53,12 +66,7 @@ export class CollisionManager { let collTank = this._checkTankCollision(xMin, xMax, yMin, yMax, tank); if (collTank) { - if (collTank.id == Constants.PLAYER_TANK_ID_IMAGE.getValue()) - this._mainTank.isDestroyed = true; - else { - this._aiManager.destroy(collTank); - } - + collTank.isDestroyed = true; return true; } else { @@ -68,7 +76,7 @@ export class CollisionManager { } _checkTankCollision(xMin, xMax, yMin, yMax, tank) { - let tanks = [this._mainTank].concat(this._aiManager._activeTanks).filter(t => tank.x != t.x && tank.y != t.y); + let tanks = [this._mainTank].concat(this._aiTanks).filter(t => t !== tank); for (let tankToCheck of tanks) { let box = tankToCheck.getCollisionBox(); diff --git a/src/GameLogic/gameField.js b/src/GameLogic/gameField.js index ffe86dd..ab473b4 100644 --- a/src/GameLogic/gameField.js +++ b/src/GameLogic/gameField.js @@ -20,8 +20,7 @@ export class GameField { this.collisionManager = new CollisionManager(); this.tank = new Tank(Constants.PLAYER_TANK_ID_IMAGE.getValue(), 0, 18*16, this.collisionManager); this.aiTanks = new AITankManager(this.collisionManager); - this.collisionManager._aiManager = this.aiTanks; - this.collisionManager._mainTank = this.tank; + this.collisionManager.setMainTank(this.tank); } //add all tiles here! @@ -56,6 +55,10 @@ export class GameField { 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(); } @@ -99,7 +102,10 @@ export class GameField { el.element.draw(this.ctx, el.x * Constants.TILE_SIZE.getValue(), el.y * Constants.TILE_SIZE.getValue()); } + if (this.collisionManager.deleteFromAITank()); + if (this.aiTanks.isAllTanksDied()) return; + if (this.tank.canBeErased()) return; requestAnimationFrame(() => this.drawField()); } diff --git a/src/Graphics/Map/map.js b/src/Graphics/Map/map.js index a639d27..d22f172 100644 --- a/src/Graphics/Map/map.js +++ b/src/Graphics/Map/map.js @@ -1,19 +1,15 @@ export class Map { - constructor(width, height) { + constructor(width, height, enemiesCount) { this.width = width; this.height = height; this._map = []; - this._enemiesCount = null; + this._enemiesCount = enemiesCount; } pushElement(element) { this._map.push(element); } - setEnemyCount(count) { - this._enemiesCount = count; - } - getElement(x, y){ return this._map[x + y*this.width]; } diff --git a/src/Graphics/Map/mapParser.js b/src/Graphics/Map/mapParser.js index 60abc0a..33fa6cf 100644 --- a/src/Graphics/Map/mapParser.js +++ b/src/Graphics/Map/mapParser.js @@ -11,7 +11,7 @@ export class MapParser { async getMap(levelNumber, tileset) { let mapObject = await (await fetch(`./stages/stage-${levelNumber}.json`)).json(); - var map = new Map(mapObject.size.width, mapObject.size.height); + var map = new Map(mapObject.size.width, mapObject.size.height, mapObject.bots); for (let i = 0; i < mapObject.map.length; i++) { let row = mapObject.map[i].match(/.{1,3}/g); @@ -70,8 +70,7 @@ export class MapParser { } } } - //TODO bots from map - map.setEnemyCount(mapObject.bots); + return map; } diff --git a/src/Tanks/aiTank.js b/src/Tanks/aiTank.js index 9fe69dc..351c0ea 100644 --- a/src/Tanks/aiTank.js +++ b/src/Tanks/aiTank.js @@ -2,9 +2,8 @@ import { DirectionEnum } from "./directionEnum"; import { Tank } from "./tank"; export class AITank extends Tank { - constructor(id, x, y, collision, aiManager) { + constructor(id, x, y, collision) { super(id, x, y, collision); - this._ai = aiManager; this.moveCount = 0; this.shotChance = 15; diff --git a/src/Tanks/aiTankManager.js b/src/Tanks/aiTankManager.js index 671aa1e..5df058d 100644 --- a/src/Tanks/aiTankManager.js +++ b/src/Tanks/aiTankManager.js @@ -1,14 +1,22 @@ +import { Constants } from "../constants"; +import { CollisionManager } from "../GameLogic/collisionManager"; import { AITank } from "./aiTank" export class AITankManager { + /** + * + * @param {CollisionManager} collisionManager + */ constructor(collisionManager) { - this.MAX_TANKS_ON_FIELD = 1; + this.MAX_TANKS_ON_FIELD = 2; this._count = null; this._collision = collisionManager; this._canSpawn = false; this._activeTanks = []; + + this._lastSpawn = 0; } drawAllTanks(tileset, ctx) { @@ -22,15 +30,21 @@ export class AITankManager { } tick() { + this.destroyKilledTanks(); + if (this.checkIfCanSpawn()){ this._count--; - this._activeTanks.push(new AITank(200, 0, 0, this._collision, this)); + this._collision.addNewAITank(this.spawn()); } if (this._activeTanks.length >= this.MAX_TANKS_ON_FIELD) this._canSpawn = false; } + destroyKilledTanks() { + this._activeTanks.filter((e) => e.canBeErased()).forEach((e) => this.destroy(e)); + } + destroy(tank) { this._activeTanks = this._activeTanks.filter(t => tank.x != t.x && tank.y != t.y); this._canSpawn = true; @@ -53,5 +67,24 @@ export class AITankManager { return this._count; } + getAllActiveTanks() { + return this._activeTanks; + } + + spawn() { + const map = this._collision._map; + const tilesize = Constants.TILE_SIZE.getValue(); + let tank = new AITank(200, 0, 0, this._collision); + + for (let x = tilesize*this._activeTanks.length; x < tilesize*map.width; x+=tilesize) { + tank.x = x; + if (!this._collision.checkCollisionForTank(x, x + tilesize-1, 0, tilesize-1, tank) && this._lastSpawn != x) { + this._activeTanks.push(tank); + this._lastSpawn = x; + return tank; + } + } + } + } \ No newline at end of file diff --git a/src/Tanks/tank.js b/src/Tanks/tank.js index d33b3a7..727ca3b 100644 --- a/src/Tanks/tank.js +++ b/src/Tanks/tank.js @@ -1,3 +1,4 @@ +import { BlockTypeEnum } from "../Blocks/blockTypeEnum"; import { Constants } from "../constants"; import { DirectionEnum } from "./directionEnum"; import { ShotManager } from "./shotElement"; @@ -13,11 +14,14 @@ export class Tank { this.direction = DirectionEnum.Up; this.isDestroyed = false; + this.deathCount = 20; this.shotManager = new ShotManager(collisionManager, this); } move(direction) { + if (this.isDestroyed) return; + const box = this.getCollisionBox(); this.direction = direction; @@ -58,6 +62,7 @@ export class Tank { } shot() { + if (this.isDestroyed) return; let x, y = 0 const tanksize = Constants.TANK_SIZE.getValue(); @@ -83,9 +88,23 @@ export class Tank { this.shotManager.tryShot(this.direction, x, y); } + canBeErased() { + return this.isDestroyed && this.deathCount <= 0; + } + draw(tileset, ctx) { - ctx.drawImage(tileset.getImageOf(this.id + this.direction.getValue()), this.x, this.y, - Constants.TANK_SIZE.getValue(), Constants.TANK_SIZE.getValue()); + if (this.isDestroyed) { + let randExplosion = BlockTypeEnum.ExplosionArray[Math.abs(this.deathCount) % BlockTypeEnum.ExplosionArray.length]; + ctx.drawImage(tileset.getImageOf(randExplosion), this.x, this.y, + Constants.TANK_SIZE.getValue(), Constants.TANK_SIZE.getValue()) + + this.deathCount--; + } + else { + ctx.drawImage(tileset.getImageOf(this.id + this.direction.getValue()), this.x, this.y, + Constants.TANK_SIZE.getValue(), Constants.TANK_SIZE.getValue()); + } + this.shotManager.draw(ctx); } diff --git a/src/constants.js b/src/constants.js index 044e898..d310939 100644 --- a/src/constants.js +++ b/src/constants.js @@ -1,7 +1,7 @@ export class Constants { static TILE_SIZE = new Constants(32); static TANK_SIZE = new Constants(24); - static TANK_COLL_OFFSET = new Constants(0.125); + static TANK_COLL_OFFSET = new Constants(0.05); static SHOT_SPEED = new Constants(2.0); static SHOT_SIZE = new Constants(5);