towers can shoooot
This commit is contained in:
parent
6fd91b6e73
commit
87e5a7a71a
@ -1,11 +1,12 @@
|
||||
[
|
||||
{
|
||||
"name": "Basic Tower",
|
||||
"behaviour": "BasicTowerBehaviour",
|
||||
"sprite": "basic_tower",
|
||||
"description": "The building block of society, nothing more basic exists.",
|
||||
"stats": {
|
||||
"damage": 2,
|
||||
"cooldown": 2,
|
||||
"cooldown": 120,
|
||||
"gemSlotsAmount": 2,
|
||||
"cost": 100,
|
||||
"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',
|
||||
});
|
||||
|
||||
GameAssets.BasicProjectileTexture = await PIXI.Assets.load({
|
||||
src: '/assets/projectiles/basic_tower.png',
|
||||
});
|
||||
|
||||
await this.LoadMissions();
|
||||
await this.LoadTowers();
|
||||
await this.LoadCreepStats();
|
||||
@ -106,6 +110,8 @@ export default class GameAssets {
|
||||
|
||||
public static BasicTowerTexture: PIXI.Texture;
|
||||
|
||||
public static BasicProjectileTexture: PIXI.Texture;
|
||||
|
||||
public static Frame01Texture: PIXI.Texture;
|
||||
public static Frame02Texture: PIXI.Texture;
|
||||
public static FrameBackground: PIXI.Texture;
|
||||
|
@ -45,6 +45,7 @@ export type CreepResistancesDefinition = {
|
||||
|
||||
export type TowerDefinition = {
|
||||
name: string;
|
||||
behaviour: string;
|
||||
sprite: string;
|
||||
description: string;
|
||||
stats: TowerStatsDefinition;
|
||||
|
@ -22,7 +22,7 @@ export default class Creep extends GameObject {
|
||||
public maxHealth: number;
|
||||
public escaped: 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;
|
||||
constructor(creepType: CreepType, path: PathDefinition) {
|
||||
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 { TowerDefinition } from '../Definitions';
|
||||
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) {
|
||||
return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
|
||||
@ -30,15 +34,16 @@ export enum TowerEvents {
|
||||
export class Tower extends GameObject {
|
||||
public row: number;
|
||||
public column: number;
|
||||
private projectiles: Projectile[] = [];
|
||||
private behaviour: string;
|
||||
private definition: TowerDefinition;
|
||||
private sprite: PIXI.Sprite;
|
||||
private antiLag = 0;
|
||||
private debugGraphics: PIXI.Graphics = new PIXI.Graphics();
|
||||
private dbgtxt: any;
|
||||
constructor(row, column, texture, definition) {
|
||||
private graphics: PIXI.Graphics = new PIXI.Graphics();
|
||||
constructor(row, column, texture, definition, behaviour) {
|
||||
super();
|
||||
this.row = row;
|
||||
this.column = column;
|
||||
this.behaviour = behaviour;
|
||||
this.definition = definition;
|
||||
let parent: Cell = Globals.Grid.getCellByRowAndCol(row, column);
|
||||
this.sprite = new PIXI.Sprite({
|
||||
@ -47,25 +52,16 @@ export class Tower extends GameObject {
|
||||
width: 64,
|
||||
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.dbgtxt);
|
||||
parent.container.addChild(this.container);
|
||||
parent.clickDetector.onmouseenter = (e) => {
|
||||
this.debugGraphics.circle(this.column * 64 + 32, this.row * 64 + 32, this.definition.stats.range * 64);
|
||||
this.debugGraphics.fill({ color: 0xff0000, alpha: 0.5 });
|
||||
this.graphics.circle(this.column * 64 + 32, this.row * 64 + 32, this.definition.stats.range * 64);
|
||||
this.graphics.fill({ color: 0xff0000, alpha: 0.5 });
|
||||
};
|
||||
parent.clickDetector.onmouseleave = (e) => {
|
||||
this.debugGraphics.clear();
|
||||
this.graphics.clear();
|
||||
};
|
||||
Globals.app.stage.addChild(this.debugGraphics);
|
||||
Globals.app.stage.addChild(this.graphics);
|
||||
}
|
||||
public GetCreepsInRange() {
|
||||
let creeps = Globals.Grid.creeps;
|
||||
@ -79,12 +75,22 @@ export class Tower extends GameObject {
|
||||
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 {
|
||||
if (this.antiLag >= 10) {
|
||||
this.antiLag = 0;
|
||||
let inrange = this.GetCreepsInRange().length;
|
||||
this.dbgtxt.text = inrange;
|
||||
}
|
||||
this.antiLag++;
|
||||
this.projectiles.forEach((proj) => {
|
||||
proj.update(elapsedMS);
|
||||
});
|
||||
if (this.behaviour == TowerBehaviours.BasicTowerBehaviour) {
|
||||
let creepsInRange = this.GetCreepsInRange();
|
||||
if (creepsInRange.length > 0) {
|
||||
let focus = creepsInRange[0];
|
||||
this.Shoot(focus);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,14 @@
|
||||
import * as PIXI from 'pixi.js';
|
||||
import { Globals } from '../Bastion';
|
||||
import { TowerDefinition } from '../Definitions';
|
||||
import { TerrainType, TowerDefinition } from '../Definitions';
|
||||
import GameAssets from '../Assets';
|
||||
import GameObject from '../GameObject';
|
||||
import { Tower, TowerEvents } from './Tower';
|
||||
|
||||
export enum TowerBehaviours {
|
||||
BasicTowerBehaviour = 'BasicTowerBehaviour',
|
||||
}
|
||||
|
||||
export default class TowerManager {
|
||||
public isPlacingTower: boolean = false;
|
||||
public canPlaceTowers: boolean = true;
|
||||
@ -32,7 +36,7 @@ export default class TowerManager {
|
||||
if (this.isPlacingTower) {
|
||||
if (!this.selectedTower)
|
||||
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) {
|
||||
@ -44,7 +48,7 @@ export default class TowerManager {
|
||||
});
|
||||
return returnTower;
|
||||
}
|
||||
public PlaceTower(definition: TowerDefinition, row, column, ignoreCost?) {
|
||||
public PlaceTower(definition: TowerDefinition, row, column, behaviour: string, ignoreCost?) {
|
||||
let idx = 0;
|
||||
GameAssets.Towers.forEach((item, index) => {
|
||||
if (item.sprite == definition.sprite) idx = index;
|
||||
@ -52,9 +56,13 @@ export default class TowerManager {
|
||||
const sprite = GameAssets.TowerSprites[idx];
|
||||
if (!Globals.GameScene.MissionStats.hasEnoughGold(definition.stats.cost) && !ignoreCost)
|
||||
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);
|
||||
let tower = new Tower(row, column, sprite, definition);
|
||||
let tower = new Tower(row, column, sprite, definition, behaviour);
|
||||
this.towers.push(tower);
|
||||
this.ToggleChoosingTowerLocation('RESET');
|
||||
console.log('SHOULDVE PLACED TOWER');
|
||||
|
Loading…
x
Reference in New Issue
Block a user