towers can shoooot
This commit is contained in:
parent
6fd91b6e73
commit
87e5a7a71a
@ -1,11 +1,12 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"name": "Basic Tower",
|
"name": "Basic Tower",
|
||||||
|
"behaviour": "BasicTowerBehaviour",
|
||||||
"sprite": "basic_tower",
|
"sprite": "basic_tower",
|
||||||
"description": "The building block of society, nothing more basic exists.",
|
"description": "The building block of society, nothing more basic exists.",
|
||||||
"stats": {
|
"stats": {
|
||||||
"damage": 2,
|
"damage": 2,
|
||||||
"cooldown": 2,
|
"cooldown": 120,
|
||||||
"gemSlotsAmount": 2,
|
"gemSlotsAmount": 2,
|
||||||
"cost": 100,
|
"cost": 100,
|
||||||
"range": 3
|
"range": 3
|
||||||
|
BIN
public/assets/projectiles/basic_tower.png
Normal file
BIN
public/assets/projectiles/basic_tower.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
@ -58,6 +58,10 @@ export default class GameAssets {
|
|||||||
src: '/assets/towers/basic_tower.png',
|
src: '/assets/towers/basic_tower.png',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
GameAssets.BasicProjectileTexture = await PIXI.Assets.load({
|
||||||
|
src: '/assets/projectiles/basic_tower.png',
|
||||||
|
});
|
||||||
|
|
||||||
await this.LoadMissions();
|
await this.LoadMissions();
|
||||||
await this.LoadTowers();
|
await this.LoadTowers();
|
||||||
await this.LoadCreepStats();
|
await this.LoadCreepStats();
|
||||||
@ -106,6 +110,8 @@ export default class GameAssets {
|
|||||||
|
|
||||||
public static BasicTowerTexture: PIXI.Texture;
|
public static BasicTowerTexture: PIXI.Texture;
|
||||||
|
|
||||||
|
public static BasicProjectileTexture: PIXI.Texture;
|
||||||
|
|
||||||
public static Frame01Texture: PIXI.Texture;
|
public static Frame01Texture: PIXI.Texture;
|
||||||
public static Frame02Texture: PIXI.Texture;
|
public static Frame02Texture: PIXI.Texture;
|
||||||
public static FrameBackground: PIXI.Texture;
|
public static FrameBackground: PIXI.Texture;
|
||||||
|
@ -45,6 +45,7 @@ export type CreepResistancesDefinition = {
|
|||||||
|
|
||||||
export type TowerDefinition = {
|
export type TowerDefinition = {
|
||||||
name: string;
|
name: string;
|
||||||
|
behaviour: string;
|
||||||
sprite: string;
|
sprite: string;
|
||||||
description: string;
|
description: string;
|
||||||
stats: TowerStatsDefinition;
|
stats: TowerStatsDefinition;
|
||||||
|
@ -22,7 +22,7 @@ export default class Creep extends GameObject {
|
|||||||
public maxHealth: number;
|
public maxHealth: number;
|
||||||
public escaped: boolean = false;
|
public escaped: boolean = false;
|
||||||
public died: boolean = false;
|
public died: boolean = false;
|
||||||
public x: number; // X and Y are local to the grid, not canvas
|
public x: number;
|
||||||
public y: number;
|
public y: number;
|
||||||
constructor(creepType: CreepType, path: PathDefinition) {
|
constructor(creepType: CreepType, path: PathDefinition) {
|
||||||
super();
|
super();
|
||||||
|
57
src/classes/game/Projectile.ts
Normal file
57
src/classes/game/Projectile.ts
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import * as PIXI from 'pixi.js';
|
||||||
|
import GameObject from '../GameObject';
|
||||||
|
import { Globals } from '../Bastion';
|
||||||
|
|
||||||
|
export function calculateAngleToPoint(x, y, targetX, targetY) {
|
||||||
|
const dx = targetX - x;
|
||||||
|
const dy = targetY - y;
|
||||||
|
return Math.atan2(dy, dx);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class Projectile extends GameObject {
|
||||||
|
public sprite: PIXI.Sprite;
|
||||||
|
public x: number;
|
||||||
|
public y: number;
|
||||||
|
public angle: number;
|
||||||
|
public speed: number;
|
||||||
|
constructor(x, y, spriteTexture, angle) {
|
||||||
|
super();
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
|
||||||
|
this.sprite = new PIXI.Sprite({ texture: spriteTexture, scale: 0.5, rotation: angle });
|
||||||
|
this.sprite.anchor.set(0.5);
|
||||||
|
this.container.x = this.x;
|
||||||
|
this.container.y = this.y;
|
||||||
|
this.container.addChild(this.sprite);
|
||||||
|
Globals.app.stage.addChild(this.container);
|
||||||
|
|
||||||
|
this.angle = angle;
|
||||||
|
|
||||||
|
this.speed = 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
public update(elapsedMS) {
|
||||||
|
if (this.x > 2000 || this.x < 0 || this.y > 2000 || this.y < 0) return this.destroy();
|
||||||
|
this.x += Math.cos(this.angle) * this.speed * elapsedMS;
|
||||||
|
this.y += Math.sin(this.angle) * this.speed * elapsedMS;
|
||||||
|
|
||||||
|
this.container.x = this.x;
|
||||||
|
this.container.y = this.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public onCollide(otherSprite) {
|
||||||
|
console.log(`Collision detected with`, otherSprite);
|
||||||
|
}
|
||||||
|
|
||||||
|
public checkCollision(otherSprite) {
|
||||||
|
const boundsA = this.sprite.getBounds();
|
||||||
|
const boundsB = otherSprite.getBounds();
|
||||||
|
return (
|
||||||
|
boundsA.x < boundsB.x + boundsB.width &&
|
||||||
|
boundsA.x + boundsA.width > boundsB.x &&
|
||||||
|
boundsA.y < boundsB.y + boundsB.height &&
|
||||||
|
boundsA.y + boundsA.height > boundsB.y
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,10 @@ import * as PIXI from 'pixi.js';
|
|||||||
import GameObject from '../GameObject';
|
import GameObject from '../GameObject';
|
||||||
import { TowerDefinition } from '../Definitions';
|
import { TowerDefinition } from '../Definitions';
|
||||||
import { Cell } from './Grid';
|
import { Cell } from './Grid';
|
||||||
|
import { TowerBehaviours } from './TowerManager';
|
||||||
|
import Projectile, { calculateAngleToPoint } from './Projectile';
|
||||||
|
import GameAssets from '../Assets';
|
||||||
|
import Creep from './Creep';
|
||||||
|
|
||||||
function distance(x1, y1, x2, y2) {
|
function distance(x1, y1, x2, y2) {
|
||||||
return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
|
return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
|
||||||
@ -30,15 +34,16 @@ export enum TowerEvents {
|
|||||||
export class Tower extends GameObject {
|
export class Tower extends GameObject {
|
||||||
public row: number;
|
public row: number;
|
||||||
public column: number;
|
public column: number;
|
||||||
|
private projectiles: Projectile[] = [];
|
||||||
|
private behaviour: string;
|
||||||
private definition: TowerDefinition;
|
private definition: TowerDefinition;
|
||||||
private sprite: PIXI.Sprite;
|
private sprite: PIXI.Sprite;
|
||||||
private antiLag = 0;
|
private graphics: PIXI.Graphics = new PIXI.Graphics();
|
||||||
private debugGraphics: PIXI.Graphics = new PIXI.Graphics();
|
constructor(row, column, texture, definition, behaviour) {
|
||||||
private dbgtxt: any;
|
|
||||||
constructor(row, column, texture, definition) {
|
|
||||||
super();
|
super();
|
||||||
this.row = row;
|
this.row = row;
|
||||||
this.column = column;
|
this.column = column;
|
||||||
|
this.behaviour = behaviour;
|
||||||
this.definition = definition;
|
this.definition = definition;
|
||||||
let parent: Cell = Globals.Grid.getCellByRowAndCol(row, column);
|
let parent: Cell = Globals.Grid.getCellByRowAndCol(row, column);
|
||||||
this.sprite = new PIXI.Sprite({
|
this.sprite = new PIXI.Sprite({
|
||||||
@ -47,25 +52,16 @@ export class Tower extends GameObject {
|
|||||||
width: 64,
|
width: 64,
|
||||||
zIndex: 10,
|
zIndex: 10,
|
||||||
});
|
});
|
||||||
this.dbgtxt = new PIXI.Text({
|
|
||||||
text: 'instantiating',
|
|
||||||
x: 0,
|
|
||||||
y: -20,
|
|
||||||
style: {
|
|
||||||
fill: 0x0ff00f,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
this.container.addChild(this.sprite);
|
this.container.addChild(this.sprite);
|
||||||
this.container.addChild(this.dbgtxt);
|
|
||||||
parent.container.addChild(this.container);
|
parent.container.addChild(this.container);
|
||||||
parent.clickDetector.onmouseenter = (e) => {
|
parent.clickDetector.onmouseenter = (e) => {
|
||||||
this.debugGraphics.circle(this.column * 64 + 32, this.row * 64 + 32, this.definition.stats.range * 64);
|
this.graphics.circle(this.column * 64 + 32, this.row * 64 + 32, this.definition.stats.range * 64);
|
||||||
this.debugGraphics.fill({ color: 0xff0000, alpha: 0.5 });
|
this.graphics.fill({ color: 0xff0000, alpha: 0.5 });
|
||||||
};
|
};
|
||||||
parent.clickDetector.onmouseleave = (e) => {
|
parent.clickDetector.onmouseleave = (e) => {
|
||||||
this.debugGraphics.clear();
|
this.graphics.clear();
|
||||||
};
|
};
|
||||||
Globals.app.stage.addChild(this.debugGraphics);
|
Globals.app.stage.addChild(this.graphics);
|
||||||
}
|
}
|
||||||
public GetCreepsInRange() {
|
public GetCreepsInRange() {
|
||||||
let creeps = Globals.Grid.creeps;
|
let creeps = Globals.Grid.creeps;
|
||||||
@ -79,12 +75,22 @@ export class Tower extends GameObject {
|
|||||||
return d < radius;
|
return d < radius;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
public Shoot(creep: Creep) {
|
||||||
|
let x = this.column * 64 + 32;
|
||||||
|
let y = this.row * 64 + 32;
|
||||||
|
let angle = calculateAngleToPoint(x, y, creep.x, creep.y);
|
||||||
|
this.projectiles.push(new Projectile(x, y, GameAssets.BasicProjectileTexture, angle));
|
||||||
|
}
|
||||||
public update(elapsedMS: any): void {
|
public update(elapsedMS: any): void {
|
||||||
if (this.antiLag >= 10) {
|
this.projectiles.forEach((proj) => {
|
||||||
this.antiLag = 0;
|
proj.update(elapsedMS);
|
||||||
let inrange = this.GetCreepsInRange().length;
|
});
|
||||||
this.dbgtxt.text = inrange;
|
if (this.behaviour == TowerBehaviours.BasicTowerBehaviour) {
|
||||||
}
|
let creepsInRange = this.GetCreepsInRange();
|
||||||
this.antiLag++;
|
if (creepsInRange.length > 0) {
|
||||||
|
let focus = creepsInRange[0];
|
||||||
|
this.Shoot(focus);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,14 @@
|
|||||||
import * as PIXI from 'pixi.js';
|
import * as PIXI from 'pixi.js';
|
||||||
import { Globals } from '../Bastion';
|
import { Globals } from '../Bastion';
|
||||||
import { TowerDefinition } from '../Definitions';
|
import { TerrainType, TowerDefinition } from '../Definitions';
|
||||||
import GameAssets from '../Assets';
|
import GameAssets from '../Assets';
|
||||||
import GameObject from '../GameObject';
|
import GameObject from '../GameObject';
|
||||||
import { Tower, TowerEvents } from './Tower';
|
import { Tower, TowerEvents } from './Tower';
|
||||||
|
|
||||||
|
export enum TowerBehaviours {
|
||||||
|
BasicTowerBehaviour = 'BasicTowerBehaviour',
|
||||||
|
}
|
||||||
|
|
||||||
export default class TowerManager {
|
export default class TowerManager {
|
||||||
public isPlacingTower: boolean = false;
|
public isPlacingTower: boolean = false;
|
||||||
public canPlaceTowers: boolean = true;
|
public canPlaceTowers: boolean = true;
|
||||||
@ -32,7 +36,7 @@ export default class TowerManager {
|
|||||||
if (this.isPlacingTower) {
|
if (this.isPlacingTower) {
|
||||||
if (!this.selectedTower)
|
if (!this.selectedTower)
|
||||||
throw console.warn('TowerManager.selectedTower is null when trying to place tower.');
|
throw console.warn('TowerManager.selectedTower is null when trying to place tower.');
|
||||||
this.PlaceTower(this.selectedTower, row, column);
|
this.PlaceTower(this.selectedTower, row, column, this.selectedTower.behaviour);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public GetTowerByRowAndCol(row, col) {
|
public GetTowerByRowAndCol(row, col) {
|
||||||
@ -44,7 +48,7 @@ export default class TowerManager {
|
|||||||
});
|
});
|
||||||
return returnTower;
|
return returnTower;
|
||||||
}
|
}
|
||||||
public PlaceTower(definition: TowerDefinition, row, column, ignoreCost?) {
|
public PlaceTower(definition: TowerDefinition, row, column, behaviour: string, ignoreCost?) {
|
||||||
let idx = 0;
|
let idx = 0;
|
||||||
GameAssets.Towers.forEach((item, index) => {
|
GameAssets.Towers.forEach((item, index) => {
|
||||||
if (item.sprite == definition.sprite) idx = index;
|
if (item.sprite == definition.sprite) idx = index;
|
||||||
@ -52,9 +56,13 @@ export default class TowerManager {
|
|||||||
const sprite = GameAssets.TowerSprites[idx];
|
const sprite = GameAssets.TowerSprites[idx];
|
||||||
if (!Globals.GameScene.MissionStats.hasEnoughGold(definition.stats.cost) && !ignoreCost)
|
if (!Globals.GameScene.MissionStats.hasEnoughGold(definition.stats.cost) && !ignoreCost)
|
||||||
return console.warn('Does not have enough gold.');
|
return console.warn('Does not have enough gold.');
|
||||||
if (!this.GetTowerByRowAndCol(row, column) && !Globals.Grid.getCellByRowAndCol(row, column).isPath) {
|
if (
|
||||||
|
!this.GetTowerByRowAndCol(row, column) &&
|
||||||
|
Globals.Grid.getCellByRowAndCol(row, column).type != TerrainType.Path &&
|
||||||
|
Globals.Grid.getCellByRowAndCol(row, column).type != TerrainType.Restricted
|
||||||
|
) {
|
||||||
Globals.GameScene.MissionStats.spendGold(definition.stats.cost);
|
Globals.GameScene.MissionStats.spendGold(definition.stats.cost);
|
||||||
let tower = new Tower(row, column, sprite, definition);
|
let tower = new Tower(row, column, sprite, definition, behaviour);
|
||||||
this.towers.push(tower);
|
this.towers.push(tower);
|
||||||
this.ToggleChoosingTowerLocation('RESET');
|
this.ToggleChoosingTowerLocation('RESET');
|
||||||
console.log('SHOULDVE PLACED TOWER');
|
console.log('SHOULDVE PLACED TOWER');
|
||||||
|
Loading…
x
Reference in New Issue
Block a user