[WIP] Explosion, tank spawning

This commit is contained in:
Nikita Iryupin 2021-06-03 20:59:29 +02:00
parent c4eb0bd705
commit cd1b791987
10 changed files with 101 additions and 35 deletions

View File

@ -7,6 +7,6 @@
<script src='bundle.js'></script>
</head>
<body>
<canvas id="canvas"></canvas>
<main><canvas id="canvas"></canvas></main>
</body>
</html>

View File

@ -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];
}

View File

@ -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();

View File

@ -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());
}

View File

@ -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];
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}
}
}
}

View File

@ -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) {
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);
}

View File

@ -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);