Collision With Tanks and shots, destroying tanks
This commit is contained in:
parent
09bbb7fcd5
commit
c4eb0bd705
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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
30
src/Tanks/aiTank.js
Normal 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)];
|
||||
}
|
||||
}
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user