Collision With Tanks and shots, destroying tanks

This commit is contained in:
Nikita Iryupin 2021-06-02 23:40:51 +02:00
parent 09bbb7fcd5
commit c4eb0bd705
7 changed files with 143 additions and 26 deletions

View File

@ -1,31 +1,40 @@
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}
* @type {Map} _map
*/
_map;
constructor() {
/**
*
* @param {Tank} tank
* @param {AITankManager} aiManager
*/
constructor(tank, aiManager) {
this._mainTank = tank;
this._aiManager = aiManager;
}
attachMap(map) {
this._map = map;
}
checkCollisionForTank(xMin, xMax, yMin, yMax) {
checkCollisionForTank(xMin, xMax, yMin, yMax, tank) {
if (!this._map)
return false;
return (this._checkTankCollision(xMin, xMax, yMin, yMax) != null) ||
return (this._checkTankCollision(xMin, xMax, yMin, yMax, tank) != null) ||
(this._checkBoundaries(xMin, xMax, yMin, yMax) != null) ||
(this._checkBlockCollision(xMin, xMax, yMin, yMax, false) != null);
}
checkCollisionForShots(xMin, xMax, yMin, yMax, direction) {
checkCollisionForShots(xMin, xMax, yMin, yMax, direction, tank) {
if (!this._map)
return false;
@ -38,12 +47,34 @@ export class CollisionManager {
return true;
}
return this._checkBoundaries(xMin, xMax, yMin, yMax) != null;
if (this._checkBoundaries(xMin, xMax, yMin, yMax) != null)
return true;
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);
}
return true;
}
else {
return false;
}
}
_checkTankCollision(xMin, xMax, yMin, yMax) {
//TODO with AI tanks
_checkTankCollision(xMin, xMax, yMin, yMax, tank) {
let tanks = [this._mainTank].concat(this._aiManager._activeTanks).filter(t => tank.x != t.x && tank.y != t.y);
for (let tankToCheck of tanks) {
let box = tankToCheck.getCollisionBox();
if (this.intersect(xMin, xMax, yMin, yMax, box.minX, box.maxX, box.minY, box.maxY)) return tankToCheck;
}
return null;
}

View File

@ -13,11 +13,15 @@ export class GameField {
this.width = width;
this.ctx = ctx;
this.canvas = canvas;
this.collisionManager = new CollisionManager();
this.tank = new Tank(Constants.PLAYER_TANK_ID_IMAGE.getValue(), 0, 0, this.collisionManager);
this.aiTanks = new AITankManager(this.collisionManager)
this.tileset = null;
this.map = null;
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;
}
//add all tiles here!
@ -46,6 +50,12 @@ export class GameField {
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());
await this.tileset.loadAll();
}
@ -55,10 +65,11 @@ export class GameField {
}
if (!this.map) {
this.map = await new MapParser().getMap(4, this.tileset);
this.map = await new MapParser().getMap(1, this.tileset);
this.canvas.height = this.height;
this.canvas.width = this.width;
this.collisionManager.attachMap(this.map);
this.aiTanks.setCount(this.map._enemiesCount);
}
let lateDraw = [];
@ -67,7 +78,8 @@ export class GameField {
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());
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){
@ -81,10 +93,14 @@ export class GameField {
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());
}
if (this.aiTanks.isAllTanksDied()) return;
requestAnimationFrame(() => this.drawField());
}

30
src/Tanks/aiTank.js Normal file
View File

@ -0,0 +1,30 @@
import { DirectionEnum } from "./directionEnum";
import { Tank } from "./tank";
export class AITank extends Tank {
constructor(id, x, y, collision, aiManager) {
super(id, x, y, collision);
this._ai = aiManager;
this.moveCount = 0;
this.shotChance = 15;
}
move(direction) {
if (this.moveCount == 0)
this.setNewMoveDirectionAndCount();
super.move(this.direction);
this.moveCount--;
}
shot() {
if (Math.floor(Math.random() * 100) + 1 <= this.shotChance)
super.shot();
}
setNewMoveDirectionAndCount(){
this.moveCount = Math.floor(Math.random() * 100) + 5;
this.direction = DirectionEnum.array[Math.floor(Math.random() * DirectionEnum.array.length)];
}
}

View File

@ -1,9 +1,39 @@
import { AITank } from "./aiTank"
export class AITankManager {
constructor(collisionManager) {
this.MAX_TANKS_ON_FIELD = 1;
this._count = null;
this._collision = collisionManager;
this._canSpawn = false;
this._activeTanks = null;
this._activeTanks = [];
}
drawAllTanks(tileset, ctx) {
for (let tank of this._activeTanks) {
tank.move(null);
tank.shot();
tank.draw(tileset, ctx);
}
this.tick();
}
tick() {
if (this.checkIfCanSpawn()){
this._count--;
this._activeTanks.push(new AITank(200, 0, 0, this._collision, this));
}
if (this._activeTanks.length >= this.MAX_TANKS_ON_FIELD)
this._canSpawn = false;
}
destroy(tank) {
this._activeTanks = this._activeTanks.filter(t => tank.x != t.x && tank.y != t.y);
this._canSpawn = true;
}
setCount(count) {

View File

@ -4,6 +4,8 @@ export class DirectionEnum {
static Down = new DirectionEnum(3);
static Right = new DirectionEnum(4);
static array = [this.Up, this.Left, this.Down, this.Right];
constructor(value){
this._value = value;
}

View File

@ -56,7 +56,7 @@ export class ShotManager {
}
checkCollision(minX, maxX, minY, maxY) {
return this.collisionManager.checkCollisionForShots(minX, maxX, minY, maxY, this.shot.direction);
return this.collisionManager.checkCollisionForShots(minX, maxX, minY, maxY, this.shot.direction, this.tank);
}
destroyShot() {

View File

@ -12,43 +12,51 @@ export class Tank {
this.speed = 3.0;
this.direction = DirectionEnum.Up;
this.isDestroyed = false;
this.shotManager = new ShotManager(collisionManager, this);
}
move(direction) {
const tanksize = Constants.TANK_SIZE.getValue();
const collisionOffset = Constants.TANK_COLL_OFFSET.getValue() * tanksize;
const box = this.getCollisionBox();
this.direction = direction;
const collisionMinX = this.x + collisionOffset;
const collisionMaxX = this.x + tanksize - collisionOffset;
const collisionMinY = this.y + collisionOffset;
const collisionMaxY = this.y + tanksize - collisionOffset;
switch (direction) {
case DirectionEnum.Up:
if (!this.collisionManager.checkCollisionForTank(collisionMinX, collisionMaxX, collisionMinY - this.speed, collisionMaxY - this.speed))
if (!this.collisionManager.checkCollisionForTank(box.minX, box.maxX, box.minY - this.speed, box.maxY - this.speed, this))
this.y -= this.speed;
break;
case DirectionEnum.Left:
if (!this.collisionManager.checkCollisionForTank(collisionMinX - this.speed, collisionMaxX - this.speed, collisionMinY, collisionMaxY))
if (!this.collisionManager.checkCollisionForTank(box.minX - this.speed, box.maxX - this.speed, box.minY, box.maxY, this))
this.x -= this.speed;
break;
case DirectionEnum.Right:
if (!this.collisionManager.checkCollisionForTank(collisionMinX + this.speed, collisionMaxX + this.speed, collisionMinY, collisionMaxY))
if (!this.collisionManager.checkCollisionForTank(box.minX + this.speed, box.maxX + this.speed, box.minY, box.maxY, this))
this.x += this.speed;
break;
case DirectionEnum.Down:
if (!this.collisionManager.checkCollisionForTank(collisionMinX, collisionMaxX, collisionMinY + this.speed, collisionMaxY + this.speed))
if (!this.collisionManager.checkCollisionForTank(box.minX, box.maxX, box.minY + this.speed, box.maxY + this.speed, this))
this.y += this.speed;
break;
}
}
getCollisionBox() {
const tanksize = Constants.TANK_SIZE.getValue();
const collisionOffset = Constants.TANK_COLL_OFFSET.getValue() * tanksize;
return {
minX: this.x + collisionOffset,
maxX: this.x + tanksize - collisionOffset,
minY: this.y + collisionOffset,
maxY: this.y + tanksize - collisionOffset
}
}
shot() {
let x, y = 0
const tanksize = Constants.TANK_SIZE.getValue();