towers can now know when someone is nearby

This commit is contained in:
koneko 2025-01-04 19:54:11 +01:00
parent 483667c64b
commit 6fd91b6e73
7 changed files with 121 additions and 50 deletions

View File

@ -8,7 +8,7 @@
"cooldown": 2, "cooldown": 2,
"gemSlotsAmount": 2, "gemSlotsAmount": 2,
"cost": 100, "cost": 100,
"range": 7 "range": 3
} }
} }
] ]

View File

@ -11,7 +11,7 @@ export class Cell extends GameObject {
public column: number; public column: number;
public isPath: boolean = false; public isPath: boolean = false;
private g: PIXI.Graphics; private g: PIXI.Graphics;
private clickDetector: PIXI.Graphics; public clickDetector: PIXI.Graphics;
constructor(type: TerrainType, row: number, column: number, isPath: boolean) { constructor(type: TerrainType, row: number, column: number, isPath: boolean) {
super(); super();

View File

@ -13,6 +13,10 @@ export default class MissionStats extends GameObject {
return this.hp; return this.hp;
} }
public hasEnoughGold(amount) {
return amount <= this.gold;
}
public setHP(hp: number) { public setHP(hp: number) {
this.hp = hp; this.hp = hp;
this.healthText.text = this.hp; this.healthText.text = this.hp;
@ -28,6 +32,16 @@ export default class MissionStats extends GameObject {
this.goldText.text = this.gold; this.goldText.text = this.gold;
} }
public earnGold(gold: number) {
this.gold += gold;
this.goldText.text = this.gold;
}
public spendGold(amount: number) {
this.gold -= amount;
this.goldText.text = this.gold;
}
constructor(initialHP: number, initialGold: number) { constructor(initialHP: number, initialGold: number) {
super(); super();
this.hp = initialHP; this.hp = initialHP;

90
src/classes/game/Tower.ts Normal file
View File

@ -0,0 +1,90 @@
import { Globals } from '../Bastion';
import * as PIXI from 'pixi.js';
import GameObject from '../GameObject';
import { TowerDefinition } from '../Definitions';
import { Cell } from './Grid';
function distance(x1, y1, x2, y2) {
return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
}
export type TowerInstance = {
row: number;
column: number;
sprite: PIXI.Sprite;
projectiles: Array<any>;
baseDamage: number;
damage: number;
cooldown: number;
ticksToFireAt: number;
slottedGems: Array<any>;
cost: number;
baseRange: number;
range: number;
};
export enum TowerEvents {
TowerPlacedEvent = 'towerPlacedEvent',
}
export class Tower extends GameObject {
public row: number;
public column: number;
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) {
super();
this.row = row;
this.column = column;
this.definition = definition;
let parent: Cell = Globals.Grid.getCellByRowAndCol(row, column);
this.sprite = new PIXI.Sprite({
texture: texture,
height: 64,
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 });
};
parent.clickDetector.onmouseleave = (e) => {
this.debugGraphics.clear();
};
Globals.app.stage.addChild(this.debugGraphics);
}
public GetCreepsInRange() {
let creeps = Globals.Grid.creeps;
return creeps.filter((creep) => {
const x = creep.x;
const y = creep.y;
const towerX = this.column * 64 + 32;
const towerY = this.row * 64 + 32;
const radius = this.definition.stats.range * 64;
const d = distance(towerX, towerY, x, y);
return d < radius;
});
}
public update(elapsedMS: any): void {
if (this.antiLag >= 10) {
this.antiLag = 0;
let inrange = this.GetCreepsInRange().length;
this.dbgtxt.text = inrange;
}
this.antiLag++;
}
}

View File

@ -3,50 +3,7 @@ import { Globals } from '../Bastion';
import { TowerDefinition } from '../Definitions'; import { TowerDefinition } from '../Definitions';
import GameAssets from '../Assets'; import GameAssets from '../Assets';
import GameObject from '../GameObject'; import GameObject from '../GameObject';
import { Tower, TowerEvents } from './Tower';
export type TowerInstance = {
row: number;
column: number;
sprite: PIXI.Sprite;
projectiles: Array<any>;
baseDamage: number;
damage: number;
cooldown: number;
ticksToFireAt: number;
slottedGems: Array<any>;
cost: number;
baseRange: number;
range: number;
};
export enum TowerEvents {
TowerPlacedEvent = 'towerPlacedEvent',
}
enum TowerSprite {
basic_tower = 'GameAssets.BasicTowerTexture',
}
class Tower extends GameObject {
public row: number;
public column: number;
private sprite: PIXI.Sprite;
constructor(row, column, texture, definition) {
super();
this.row = row;
this.column = column;
let parent = Globals.Grid.getCellByRowAndCol(row, column);
this.sprite = new PIXI.Sprite({
texture: texture,
height: 64,
width: 64,
zIndex: 10,
});
this.container.addChild(this.sprite);
parent.container.addChild(this.container);
}
public update(elapsedMS: any): void {}
}
export default class TowerManager { export default class TowerManager {
public isPlacingTower: boolean = false; public isPlacingTower: boolean = false;
@ -73,7 +30,8 @@ export default class TowerManager {
public PlayerClickOnGrid(row, column) { public PlayerClickOnGrid(row, column) {
if (!this.canPlaceTowers) return; if (!this.canPlaceTowers) return;
if (this.isPlacingTower) { if (this.isPlacingTower) {
if (!this.selectedTower) throw console.warn('TowerManager.selectedTower is null.'); 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);
} }
} }
@ -86,13 +44,16 @@ export default class TowerManager {
}); });
return returnTower; return returnTower;
} }
public PlaceTower(definition: TowerDefinition, row, column) { public PlaceTower(definition: TowerDefinition, row, column, 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;
}); });
const sprite = GameAssets.TowerSprites[idx]; 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).isPath) {
Globals.GameScene.MissionStats.spendGold(definition.stats.cost);
let tower = new Tower(row, column, sprite, definition); let tower = new Tower(row, column, sprite, definition);
this.towers.push(tower); this.towers.push(tower);
this.ToggleChoosingTowerLocation('RESET'); this.ToggleChoosingTowerLocation('RESET');
@ -104,4 +65,9 @@ export default class TowerManager {
console.warn('Can not place tower on occupied spot or path. Try again.'); console.warn('Can not place tower on occupied spot or path. Try again.');
} }
} }
public update(elapsedMS) {
this.towers.forEach((twr) => {
twr.update(elapsedMS);
});
}
} }

View File

@ -2,7 +2,7 @@ import * as PIXI from 'pixi.js';
import GuiObject from '../GuiObject'; import GuiObject from '../GuiObject';
import GameAssets from '../Assets'; import GameAssets from '../Assets';
import { Globals } from '../Bastion'; import { Globals } from '../Bastion';
import { TowerEvents } from '../game/TowerManager'; import { TowerEvents } from '../game/Tower';
class TowerButton extends GuiObject { class TowerButton extends GuiObject {
private frameSprite: PIXI.NineSliceSprite; private frameSprite: PIXI.NineSliceSprite;

View File

@ -9,7 +9,7 @@ import Button, { ButtonTexture } from '../classes/gui/Button';
import Scene from './Scene'; import Scene from './Scene';
import * as PIXI from 'pixi.js'; import * as PIXI from 'pixi.js';
import MissionStats from '../classes/game/MissionStats'; import MissionStats from '../classes/game/MissionStats';
import TowerManager, { TowerEvents } from '../classes/game/TowerManager'; import TowerManager from '../classes/game/TowerManager';
enum RoundMode { enum RoundMode {
Purchase = 0, Purchase = 0,
@ -74,6 +74,7 @@ export class GameScene extends Scene {
public update(elapsedMS) { public update(elapsedMS) {
Globals.WaveManager.update(elapsedMS); Globals.WaveManager.update(elapsedMS);
Globals.Grid.update(elapsedMS); Globals.Grid.update(elapsedMS);
Globals.TowerManager.update(elapsedMS);
} }
public onCreepEscaped(creep: Creep) { public onCreepEscaped(creep: Creep) {