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 { BlockTypeEnum } from "../Blocks/blockTypeEnum";
|
||||||
import { Constants } from "../constants";
|
import { Constants } from "../constants";
|
||||||
import { Map } from "../Graphics/Map/map";
|
import { Map } from "../Graphics/Map/map";
|
||||||
|
import { AITankManager } from "../Tanks/aiTankManager";
|
||||||
|
import { Tank } from "../Tanks/tank";
|
||||||
|
|
||||||
export class CollisionManager {
|
export class CollisionManager {
|
||||||
/**
|
/**
|
||||||
* @type {Map}
|
* @type {Map} _map
|
||||||
*/
|
*/
|
||||||
_map;
|
_map;
|
||||||
|
|
||||||
constructor() {
|
/**
|
||||||
|
*
|
||||||
|
* @param {Tank} tank
|
||||||
|
* @param {AITankManager} aiManager
|
||||||
|
*/
|
||||||
|
constructor(tank, aiManager) {
|
||||||
|
this._mainTank = tank;
|
||||||
|
this._aiManager = aiManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
attachMap(map) {
|
attachMap(map) {
|
||||||
this._map = map;
|
this._map = map;
|
||||||
}
|
}
|
||||||
|
|
||||||
checkCollisionForTank(xMin, xMax, yMin, yMax) {
|
checkCollisionForTank(xMin, xMax, yMin, yMax, tank) {
|
||||||
if (!this._map)
|
if (!this._map)
|
||||||
return false;
|
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._checkBoundaries(xMin, xMax, yMin, yMax) != null) ||
|
||||||
(this._checkBlockCollision(xMin, xMax, yMin, yMax, false) != 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)
|
if (!this._map)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -38,12 +47,34 @@ export class CollisionManager {
|
|||||||
return true;
|
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) {
|
_checkTankCollision(xMin, xMax, yMin, yMax, tank) {
|
||||||
//TODO with AI tanks
|
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;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -13,11 +13,15 @@ export class GameField {
|
|||||||
this.width = width;
|
this.width = width;
|
||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
this.canvas = canvas;
|
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.tileset = null;
|
||||||
this.map = 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!
|
//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(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());
|
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();
|
await this.tileset.loadAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,10 +65,11 @@ export class GameField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!this.map) {
|
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.height = this.height;
|
||||||
this.canvas.width = this.width;
|
this.canvas.width = this.width;
|
||||||
this.collisionManager.attachMap(this.map);
|
this.collisionManager.attachMap(this.map);
|
||||||
|
this.aiTanks.setCount(this.map._enemiesCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
let lateDraw = [];
|
let lateDraw = [];
|
||||||
@ -67,7 +78,8 @@ export class GameField {
|
|||||||
for (let x = 0; x < this.map.width; x += 1) {
|
for (let x = 0; x < this.map.width; x += 1) {
|
||||||
for (let y = 0; y < this.map.height; y += 1) {
|
for (let y = 0; y < this.map.height; y += 1) {
|
||||||
this.ctx.fillStyle = "black";
|
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);
|
let element = this.map.getElement(x, y);
|
||||||
if (element.getType() == BlockTypeEnum.Forest){
|
if (element.getType() == BlockTypeEnum.Forest){
|
||||||
@ -81,10 +93,14 @@ export class GameField {
|
|||||||
|
|
||||||
this.tank.draw(this.tileset, this.ctx);
|
this.tank.draw(this.tileset, this.ctx);
|
||||||
|
|
||||||
|
this.aiTanks.drawAllTanks(this.tileset, this.ctx);
|
||||||
|
|
||||||
for (let el of lateDraw) {
|
for (let el of lateDraw) {
|
||||||
el.element.draw(this.ctx, el.x * Constants.TILE_SIZE.getValue(), el.y * Constants.TILE_SIZE.getValue());
|
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());
|
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 {
|
export class AITankManager {
|
||||||
|
|
||||||
constructor(collisionManager) {
|
constructor(collisionManager) {
|
||||||
|
this.MAX_TANKS_ON_FIELD = 1;
|
||||||
|
|
||||||
this._count = null;
|
this._count = null;
|
||||||
this._collision = collisionManager;
|
this._collision = collisionManager;
|
||||||
this._canSpawn = false;
|
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) {
|
setCount(count) {
|
||||||
|
|||||||
@ -4,6 +4,8 @@ export class DirectionEnum {
|
|||||||
static Down = new DirectionEnum(3);
|
static Down = new DirectionEnum(3);
|
||||||
static Right = new DirectionEnum(4);
|
static Right = new DirectionEnum(4);
|
||||||
|
|
||||||
|
static array = [this.Up, this.Left, this.Down, this.Right];
|
||||||
|
|
||||||
constructor(value){
|
constructor(value){
|
||||||
this._value = value;
|
this._value = value;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -56,7 +56,7 @@ export class ShotManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkCollision(minX, maxX, minY, maxY) {
|
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() {
|
destroyShot() {
|
||||||
|
|||||||
@ -12,43 +12,51 @@ export class Tank {
|
|||||||
this.speed = 3.0;
|
this.speed = 3.0;
|
||||||
this.direction = DirectionEnum.Up;
|
this.direction = DirectionEnum.Up;
|
||||||
|
|
||||||
|
this.isDestroyed = false;
|
||||||
|
|
||||||
this.shotManager = new ShotManager(collisionManager, this);
|
this.shotManager = new ShotManager(collisionManager, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
move(direction) {
|
move(direction) {
|
||||||
const tanksize = Constants.TANK_SIZE.getValue();
|
const box = this.getCollisionBox();
|
||||||
const collisionOffset = Constants.TANK_COLL_OFFSET.getValue() * tanksize;
|
|
||||||
|
|
||||||
this.direction = direction;
|
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) {
|
switch (direction) {
|
||||||
case DirectionEnum.Up:
|
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;
|
this.y -= this.speed;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DirectionEnum.Left:
|
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;
|
this.x -= this.speed;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DirectionEnum.Right:
|
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;
|
this.x += this.speed;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DirectionEnum.Down:
|
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;
|
this.y += this.speed;
|
||||||
break;
|
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() {
|
shot() {
|
||||||
let x, y = 0
|
let x, y = 0
|
||||||
const tanksize = Constants.TANK_SIZE.getValue();
|
const tanksize = Constants.TANK_SIZE.getValue();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user