2024-11-19 23:54:25 +01:00

118 lines
4.0 KiB
TypeScript

import Assets from '../base/Assets';
import { CreepStatsDefinition, CreepType, PathDefinition } from '../base/Definitions';
import GameObject from '../base/GameObject';
import * as PIXI from 'pixi.js';
import GameScene from '../scenes/GameScene';
export enum CreepEvents {
Died = 'died',
TakenDamage = 'takenDamage',
Escaped = 'escaped',
Moved = 'moved',
}
export default class Creep extends GameObject {
public creepType: CreepType;
private path: PathDefinition;
private stats: CreepStatsDefinition;
private pathIndex: number = 0;
private speed: number;
private gameScene: GameScene;
public health: number;
public escaped: boolean = false;
public died: boolean = false;
public x: number; // X and Y are local to the grid, not canvas
public y: number;
constructor(creepType: CreepType, path: PathDefinition, gameScene: GameScene, bounds?: PIXI.Rectangle) {
super(bounds);
this.gameScene = gameScene;
this.creepType = creepType;
this.stats = Assets.CreepStats[this.creepType];
this.speed = this.stats.speed;
this.health = this.stats.health;
this.path = path;
this.x = path[0][1] + 0.5; // centered
this.y = path[0][0] + 0.5;
this.gameScene.grid.container.addChild(this.container);
}
private gridUnitsToPixels(gridUnits) {
return this.gameScene.grid.gridUnitsToPixels(gridUnits);
}
public update(elapsedMS: number) {
if (this.pathIndex + 1 == this.path.length) {
if (this.escaped) return;
this.events.emit(CreepEvents.Escaped, this);
this.escaped = true;
return;
}
const currentCell = this.path[this.pathIndex];
const targetCell = this.path[this.pathIndex + 1];
const targetX = targetCell[1] + 0.5;
const targetY = targetCell[0] + 0.5;
const directionX = targetCell[1] - currentCell[1];
const directionY = targetCell[0] - currentCell[0];
let deltaX = this.speed * elapsedMS * directionX;
let deltaY = this.speed * elapsedMS * directionY;
let increaseIndex = false;
if (deltaX > 0 && this.x + deltaX > targetX) {
// limit to center of target cell
deltaX = targetX - this.x;
increaseIndex = true;
}
if (deltaX < 0 && this.x + deltaX < targetX) {
// limit to center of target cell
deltaX = targetX - this.x;
increaseIndex = true;
}
if (deltaY > 0 && this.y + deltaY > targetY) {
// limit to center of target cell
deltaY = targetY - this.y;
increaseIndex = true;
}
if (deltaY < 0 && this.y + deltaY < targetY) {
// limit to center of target cell
deltaY = targetY - this.y;
increaseIndex = true;
}
this.x += deltaX;
this.y += deltaY;
if (increaseIndex) this.pathIndex++;
this.setBounds(
new PIXI.Rectangle(
this.gridUnitsToPixels(this.x),
this.gridUnitsToPixels(this.y),
this.gridUnitsToPixels(0.5),
this.gridUnitsToPixels(0.6)
)
);
}
public takeDamage(amount: number) {
this.health -= amount;
if (this.health < 0 && !this.died) {
this.died = true;
this.events.emit(CreepEvents.Died, this);
}
}
public override destroy() {
super.destroy();
this.draw = null;
this.container.removeChildren();
}
protected draw() {
this.container.removeChildren();
const sprite = new PIXI.Sprite(Assets.BasicCreepTexture);
sprite.x = 0;
sprite.y = 0;
sprite.anchor.set(0.5, 0.5);
sprite.width = this.bounds.width;
sprite.height = this.bounds.height;
this.container.addChild(sprite);
this.container.x = this.bounds.x;
this.container.y = this.bounds.y;
}
}