chore: hopefully made the repo more consistent
This commit is contained in:
parent
2817f689fe
commit
6875a9b0e8
@ -81,6 +81,7 @@ export default class GameAssets {
|
||||
}
|
||||
|
||||
private static async LoadMissions() {
|
||||
// When adding missions, make sure to keep order.
|
||||
GameAssets.Missions = [await this.LoadMission('/assets/missions/mission_01.json')];
|
||||
}
|
||||
|
||||
|
@ -12,9 +12,6 @@ import NotificationManager from './game/NotificationManager';
|
||||
export class Engine {
|
||||
public static app: PIXI.Application;
|
||||
public static GameMaster: GameMaster;
|
||||
public static WindowHeight: number;
|
||||
public static WindowWidth: number;
|
||||
public static AspectRatio: number = 16 / 9;
|
||||
public static Grid: Grid;
|
||||
public static WaveManager: WaveManager;
|
||||
public static TowerManager: TowerManager;
|
||||
@ -22,11 +19,14 @@ export class Engine {
|
||||
public static NotificationManager: NotificationManager;
|
||||
public static GameScene: GameScene;
|
||||
public static latestCommit: string;
|
||||
|
||||
public static GridCellSize: number = 64;
|
||||
public static GridColumns: number = 25;
|
||||
public static GridRows: number = 17;
|
||||
}
|
||||
|
||||
export default class GameMaster {
|
||||
public currentScene: Scene;
|
||||
private gameScene: GameScene;
|
||||
private GameObjects: GameObject[] = [];
|
||||
|
||||
constructor() {
|
||||
@ -35,12 +35,12 @@ export default class GameMaster {
|
||||
|
||||
public _CreateGuiObject(object: GuiObject) {
|
||||
this.currentScene.gui.push(object);
|
||||
Engine.app.stage.addChild(object.container);
|
||||
Engine.GameMaster.currentScene.stage.addChild(object.container);
|
||||
}
|
||||
|
||||
public _RemoveGuiObject(object: GuiObject) {
|
||||
this.currentScene.gui.splice(this.currentScene.gui.indexOf(object), 1);
|
||||
Engine.app.stage.removeChild(object.container);
|
||||
Engine.GameMaster.currentScene.stage.removeChild(object.container);
|
||||
}
|
||||
|
||||
public changeScene(newScene: Scene) {
|
||||
|
@ -44,7 +44,7 @@ export class FadeInOut extends Animateable {
|
||||
} else {
|
||||
this.pixiObject.alpha -= 1 / this.fadeTime;
|
||||
}
|
||||
if (this.ticks >= this.fadeTime || this.pixiObject.alpha <= 0) this.Finish();
|
||||
if (this.ticks >= this.fadeTime) this.Finish();
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,14 +67,11 @@ export class Tween extends Animateable {
|
||||
public update(deltaMS) {
|
||||
super.update(deltaMS);
|
||||
this.ticks += deltaMS;
|
||||
// Calculate the fraction of time elapsed
|
||||
const progress = this.ticks / (this.tweenTime * 16.67); // Assuming 60 FPS, 1 frame = 16.67ms
|
||||
const progress = this.ticks / (this.tweenTime * 16.67);
|
||||
|
||||
// Update the position based on the progress
|
||||
this.pixiObject.x = (this.goalX - this.pixiObject.x) * progress + this.pixiObject.x;
|
||||
this.pixiObject.y = (this.goalY - this.pixiObject.y) * progress + this.pixiObject.y;
|
||||
|
||||
// Finish the animation if the time is up
|
||||
if (this.ticks >= this.tweenTime * 16.67) {
|
||||
this.pixiObject.x = this.goalX;
|
||||
this.pixiObject.y = this.goalY;
|
||||
@ -89,6 +86,9 @@ export class AnimationManager {
|
||||
this.AnimationQueue.push(animatable);
|
||||
}
|
||||
public update(ms) {
|
||||
// Explanation: we go from the back of the array so that we can remove items freely without messing with
|
||||
// foreach. From experience it gets a little screwy if you do this.AnimationQueue.forEach and doesn't properly
|
||||
// remove elements.
|
||||
for (let i = this.AnimationQueue.length - 1; i >= 0; i--) {
|
||||
const anim = this.AnimationQueue[i];
|
||||
if (anim.finished) {
|
||||
|
@ -30,24 +30,26 @@ export default class Creep extends GameObject {
|
||||
constructor(creepType: CreepType, path: PathDefinition, id) {
|
||||
super();
|
||||
this.creepType = creepType;
|
||||
// Structured clone is used just in case, so that 1 creep doesnt alter stats for all creeps.
|
||||
this.stats = structuredClone(Assets.CreepStats[this.creepType]);
|
||||
this.sprite = new PIXI.Sprite({
|
||||
texture: GameAssets.BasicCreepTexture,
|
||||
});
|
||||
this.id = id;
|
||||
// because wave manager spawns all instantly and i dont want
|
||||
// it to look like a shit game (they all spawn in top left corner)
|
||||
// i want to hide minion - mario
|
||||
// Explanation: WaveManager spawns all creeps instantly, and since I don't want
|
||||
// them to show up on the beginning while they are waiting, I put them outside the visible
|
||||
// part of the currentScene.stage map.
|
||||
this.container.x = -70;
|
||||
this.container.y = -50;
|
||||
this.sprite.width = 64;
|
||||
this.sprite.height = 64;
|
||||
this.sprite.width = Engine.GridCellSize;
|
||||
this.sprite.height = Engine.GridCellSize;
|
||||
this.speed = this.stats.speed;
|
||||
this.health = this.stats.health;
|
||||
this.maxHealth = this.stats.health;
|
||||
this.path = path;
|
||||
this.x = path[0][1] * 64 + 32; // centered
|
||||
this.y = path[0][0] * 64 + 32;
|
||||
// Added + 32 to center them.
|
||||
this.x = path[0][1] * Engine.GridCellSize + Engine.GridCellSize / 2;
|
||||
this.y = path[0][0] * Engine.GridCellSize + Engine.GridCellSize / 2;
|
||||
Engine.GameScene.events.on(CreepEvents.TakenDamage, (creepID, damage) => {
|
||||
if (creepID != this.id) return;
|
||||
this.health -= damage;
|
||||
@ -60,6 +62,8 @@ export default class Creep extends GameObject {
|
||||
if (this.health <= 0) {
|
||||
Engine.GameScene.events.emit(CreepEvents.Died, this.maxHealth, this);
|
||||
this.destroy();
|
||||
// The reason for setting this.dead instead of deleting self is because
|
||||
// I need to allow WaveManager/Grid to manage their death and keep array up to date.
|
||||
this.dead = true;
|
||||
return;
|
||||
}
|
||||
@ -72,8 +76,9 @@ export default class Creep extends GameObject {
|
||||
const currentCell = this.path[this.pathIndex];
|
||||
const targetCell = this.path[this.pathIndex + 1];
|
||||
|
||||
const targetX = targetCell[1] * 64 + 32;
|
||||
const targetY = targetCell[0] * 64 + 32;
|
||||
// Added + 32 for centering.
|
||||
const targetX = targetCell[1] * Engine.GridCellSize + Engine.GridCellSize / 2;
|
||||
const targetY = targetCell[0] * Engine.GridCellSize + Engine.GridCellSize / 2;
|
||||
const directionX = targetCell[1] - currentCell[1];
|
||||
const directionY = targetCell[0] - currentCell[0];
|
||||
let deltaX = this.speed * elapsedMS * directionX;
|
||||
@ -114,7 +119,7 @@ export default class Creep extends GameObject {
|
||||
}
|
||||
}
|
||||
|
||||
public override destroy() {
|
||||
public destroy() {
|
||||
super.destroy();
|
||||
this.container.removeChildren();
|
||||
}
|
||||
|
@ -19,10 +19,10 @@ export class Cell extends GameObject {
|
||||
this.row = row;
|
||||
this.column = column;
|
||||
this.isPath = isPath;
|
||||
this.bb.x = this.column * 64;
|
||||
this.bb.y = this.row * 64;
|
||||
this.bb.width = 64;
|
||||
this.bb.height = 64;
|
||||
this.bb.x = this.column * Engine.GridCellSize;
|
||||
this.bb.y = this.row * Engine.GridCellSize;
|
||||
this.bb.width = Engine.GridCellSize;
|
||||
this.bb.height = Engine.GridCellSize;
|
||||
Engine.Grid.container.addChild(this.container);
|
||||
this.container.x = this.bb.x;
|
||||
this.container.y = this.bb.y;
|
||||
@ -35,7 +35,7 @@ export class Cell extends GameObject {
|
||||
this.clickDetector.fill({ color: 0xff0000, alpha: 0 });
|
||||
this.container.addChild(this.clickDetector);
|
||||
this.clickDetector.onpointerdown = (e) => {
|
||||
Engine.Grid._gridCellClicked(row, column);
|
||||
Engine.Grid.onGridCellClicked(row, column);
|
||||
};
|
||||
|
||||
if (!GameAssets.DebuggingEnabled) return;
|
||||
@ -92,9 +92,9 @@ export class Grid extends GameObject {
|
||||
Engine.Grid = this;
|
||||
this.bb.x = 0;
|
||||
this.bb.y = 0;
|
||||
this.bb.width = 64 * 30;
|
||||
this.bb.height = 64 * 17;
|
||||
Engine.app.stage.addChild(this.container);
|
||||
this.bb.width = Engine.GridCellSize * Engine.GridColumns;
|
||||
this.bb.height = Engine.GridCellSize * Engine.GridRows;
|
||||
Engine.GameMaster.currentScene.stage.addChild(this.container);
|
||||
|
||||
let background = new PIXI.Sprite(GameAssets.MissionBackgrounds[missionIndex]);
|
||||
background.x = 0;
|
||||
@ -126,7 +126,6 @@ export class Grid extends GameObject {
|
||||
this.gridShown = !this.gridShown;
|
||||
}
|
||||
public addCreep(creep: Creep) {
|
||||
console.log('ADD CREEP');
|
||||
this.creeps.push(creep);
|
||||
creep.events.on(CreepEvents.Died, (diedCreep) => {
|
||||
this.onCreepDiedOrEscaped(diedCreep);
|
||||
@ -150,9 +149,5 @@ export class Grid extends GameObject {
|
||||
public getCellByRowAndCol(row, column) {
|
||||
return this.cells.filter((item) => item.row == row && item.column == column)[0];
|
||||
}
|
||||
public _gridCellClicked(row, column) {
|
||||
// function will be assigned by GameScene, but must be predefined here.
|
||||
this.onGridCellClicked(row, column);
|
||||
}
|
||||
public onGridCellClicked(row, column) {}
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ export default class MissionStats extends GameObject {
|
||||
this.gold = initialGold;
|
||||
this.container.x = 0;
|
||||
this.container.y = 20;
|
||||
Engine.app.stage.addChild(this.container);
|
||||
Engine.GameMaster.currentScene.stage.addChild(this.container);
|
||||
this.healthText = new PIXI.Text({
|
||||
text: `${this.hp}`,
|
||||
style: new PIXI.TextStyle({
|
||||
|
@ -58,10 +58,8 @@ export default class NotificationManager extends GameObject {
|
||||
}
|
||||
public Notify(text, type: NotificationType) {
|
||||
let x = 0;
|
||||
let y = this.notifications.length * 30;
|
||||
let y = this.notifications.length * 32;
|
||||
this.notifications.push(new Notification(text, type, x, y, this.ticks + 180));
|
||||
console.log('CREATED NOTIFICATION ');
|
||||
console.log(text, type, x, y, this.ticks + 180);
|
||||
}
|
||||
public update(_) {
|
||||
this.ticks++;
|
||||
|
@ -20,7 +20,6 @@ export default class Projectile extends GameObject {
|
||||
public timeToLive: number = 1;
|
||||
constructor(x, y, spriteTexture, angle, damage) {
|
||||
super();
|
||||
console.log('I SHOOTTED!');
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.damage = damage;
|
||||
@ -30,7 +29,7 @@ export default class Projectile extends GameObject {
|
||||
this.container.x = this.x;
|
||||
this.container.y = this.y;
|
||||
this.container.addChild(this.sprite);
|
||||
Engine.app.stage.addChild(this.container);
|
||||
Engine.GameMaster.currentScene.stage.addChild(this.container);
|
||||
|
||||
this.angle = angle;
|
||||
this.speed = 0.9;
|
||||
@ -59,7 +58,6 @@ export default class Projectile extends GameObject {
|
||||
}
|
||||
|
||||
public onCollide(creep) {
|
||||
console.log('COLLIDED WITH' + creep);
|
||||
Engine.GameScene.events.emit(CreepEvents.TakenDamage, creep.id, this.damage);
|
||||
}
|
||||
|
||||
@ -68,12 +66,5 @@ export default class Projectile extends GameObject {
|
||||
let mybb = this.copyContainerToBB();
|
||||
let otherbb = creep.copyContainerToBB();
|
||||
return mybb.getBounds().intersects(otherbb.getBounds());
|
||||
// console.log(boundsA, boundsB);
|
||||
// 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
|
||||
// );
|
||||
}
|
||||
}
|
||||
|
@ -50,36 +50,40 @@ export class Tower extends GameObject {
|
||||
let parent: Cell = Engine.Grid.getCellByRowAndCol(row, column);
|
||||
this.sprite = new PIXI.Sprite({
|
||||
texture: texture,
|
||||
height: 64,
|
||||
width: 64,
|
||||
height: Engine.GridCellSize,
|
||||
width: Engine.GridCellSize,
|
||||
zIndex: 10,
|
||||
});
|
||||
this.container.addChild(this.sprite);
|
||||
parent.container.addChild(this.container);
|
||||
parent.clickDetector.onmouseenter = (e) => {
|
||||
this.graphics.circle(this.column * 64 + 32, this.row * 64 + 32, this.definition.stats.range * 64);
|
||||
this.graphics.circle(
|
||||
this.column * Engine.GridCellSize + Engine.GridCellSize / 2,
|
||||
this.row * Engine.GridCellSize + Engine.GridCellSize / 2,
|
||||
this.definition.stats.range * Engine.GridCellSize
|
||||
);
|
||||
this.graphics.fill({ color: 0xff0000, alpha: 0.5 });
|
||||
};
|
||||
parent.clickDetector.onmouseleave = (e) => {
|
||||
this.graphics.clear();
|
||||
};
|
||||
Engine.app.stage.addChild(this.graphics);
|
||||
Engine.GameMaster.currentScene.stage.addChild(this.graphics);
|
||||
}
|
||||
public GetCreepsInRange() {
|
||||
let creeps = Engine.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 towerX = this.column * Engine.GridCellSize + Engine.GridCellSize / 2;
|
||||
const towerY = this.row * Engine.GridCellSize + Engine.GridCellSize / 2;
|
||||
const radius = this.definition.stats.range * Engine.GridCellSize;
|
||||
const d = distance(towerX, towerY, x, y);
|
||||
return d < radius;
|
||||
});
|
||||
}
|
||||
public Shoot(creep: Creep) {
|
||||
let x = this.column * 64 + 32;
|
||||
let y = this.row * 64 + 32;
|
||||
let x = this.column * Engine.GridCellSize + Engine.GridCellSize / 2;
|
||||
let y = this.row * Engine.GridCellSize + Engine.GridCellSize / 2;
|
||||
let angle = calculateAngleToPoint(x, y, creep.x, creep.y);
|
||||
this.projectiles.push(
|
||||
new Projectile(x, y, GameAssets.BasicProjectileTexture, angle, this.definition.stats.damage)
|
||||
|
@ -18,9 +18,6 @@ export default class GemTab extends GuiObject {
|
||||
rightWidth: 1000,
|
||||
bottomHeight: 1000,
|
||||
});
|
||||
// this.towerTabSprite = new PIXI.Sprite({
|
||||
// texture: GameAssets.FrameBackground,
|
||||
// });
|
||||
this.gemTabSprite.x = 0;
|
||||
this.gemTabSprite.y = 0;
|
||||
this.gemTabSprite.width = this.bounds.width;
|
||||
|
@ -10,7 +10,6 @@ import NotificationManager from './classes/game/NotificationManager';
|
||||
(async () => {
|
||||
const app = new PIXI.Application();
|
||||
Engine.app = app;
|
||||
log('main - init()');
|
||||
await app.init({
|
||||
width: 1920, // Base width
|
||||
height: 1080, // Base height
|
||||
@ -19,7 +18,6 @@ import NotificationManager from './classes/game/NotificationManager';
|
||||
backgroundColor: 0xffffff,
|
||||
sharedTicker: true,
|
||||
});
|
||||
log('main - init() complete');
|
||||
|
||||
document.body.appendChild(app.canvas);
|
||||
|
||||
|
@ -10,7 +10,6 @@ import Scene from './Scene';
|
||||
import * as PIXI from 'pixi.js';
|
||||
import MissionStats from '../classes/game/MissionStats';
|
||||
import TowerManager from '../classes/game/TowerManager';
|
||||
import NotificationManager from '../classes/game/NotificationManager';
|
||||
import { MissionPickerScene } from './MissionPicker';
|
||||
|
||||
enum RoundMode {
|
||||
@ -30,6 +29,7 @@ export class GameScene extends Scene {
|
||||
private currentRound: number = 0;
|
||||
private isWaveManagerFinished: boolean = false;
|
||||
private playerWon: boolean = false;
|
||||
private destroyTicker: boolean = false;
|
||||
|
||||
constructor(name: string) {
|
||||
super();
|
||||
@ -45,9 +45,11 @@ export class GameScene extends Scene {
|
||||
this.ticker = new PIXI.Ticker();
|
||||
this.ticker.maxFPS = 60;
|
||||
this.ticker.minFPS = 30;
|
||||
this.ticker.add(() => this.update(this.ticker.elapsedMS)); // bruh
|
||||
this.ticker.add(() => {
|
||||
if (this.update) this.update(this.ticker.elapsedMS);
|
||||
});
|
||||
this.ticker.start();
|
||||
const SidebarRect = new PIXI.Rectangle(64 * 30 - 360, 0, 360, Engine.app.canvas.height);
|
||||
const SidebarRect = new PIXI.Rectangle(Engine.GridCellSize * 30 - 360, 0, 360, Engine.app.canvas.height);
|
||||
const changeRoundButtonRect = new PIXI.Rectangle(50, Engine.app.canvas.height - 100, 310, 100);
|
||||
new Grid(this.mission.gameMap, this.missionIndex);
|
||||
new TowerManager();
|
||||
@ -85,6 +87,13 @@ export class GameScene extends Scene {
|
||||
this.MissionStats = new MissionStats(100, 200);
|
||||
}
|
||||
public update(elapsedMS) {
|
||||
if (this.isGameOver) {
|
||||
if (this.destroyTicker) {
|
||||
this.destroyTicker = false;
|
||||
this.ticker.destroy();
|
||||
}
|
||||
return;
|
||||
}
|
||||
Engine.WaveManager.update(elapsedMS);
|
||||
Engine.Grid.update(elapsedMS);
|
||||
Engine.TowerManager.update(elapsedMS);
|
||||
@ -110,16 +119,13 @@ export class GameScene extends Scene {
|
||||
if (this.MissionStats.getHP() <= 0) {
|
||||
this.isGameOver = true;
|
||||
this.ShowScoreScreen(true);
|
||||
this.ticker.stop();
|
||||
} else if (this.playerWon) {
|
||||
this.isGameOver = true;
|
||||
this.ShowScoreScreen(false);
|
||||
this.ticker.stop();
|
||||
}
|
||||
}
|
||||
|
||||
private ShowScoreScreen(lost) {
|
||||
this.ticker.stop();
|
||||
// TODO: show to player for real
|
||||
if (lost) {
|
||||
console.log('LOSE!');
|
||||
@ -141,9 +147,16 @@ export class GameScene extends Scene {
|
||||
}
|
||||
}
|
||||
|
||||
public destroy(): void {
|
||||
super.destroy();
|
||||
this.isGameOver = true;
|
||||
this.destroyTicker = true;
|
||||
Engine.GameScene = null;
|
||||
}
|
||||
|
||||
private ReturnToMain() {
|
||||
this.destroy();
|
||||
Engine.app.stage.removeChildren();
|
||||
Engine.GameMaster.currentScene.stage.removeChildren();
|
||||
Engine.GameMaster.changeScene(new MissionPickerScene());
|
||||
}
|
||||
public onTowerPlaced() {}
|
||||
|
@ -39,7 +39,7 @@ export class MainScene extends Scene {
|
||||
},
|
||||
});
|
||||
text.x = text.x - text.width / 5;
|
||||
Engine.app.stage.addChild(text);
|
||||
Engine.GameMaster.currentScene.stage.addChild(text);
|
||||
let text2 = new PIXI.Text({
|
||||
x: 0,
|
||||
y: 0,
|
||||
@ -50,17 +50,17 @@ export class MainScene extends Scene {
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
});
|
||||
Engine.app.stage.addChild(text2);
|
||||
Engine.GameMaster.currentScene.stage.addChild(text2);
|
||||
const button01 = new Button(NewGameButton.rect, NewGameButton.caption, NewGameButton.texture, true);
|
||||
button01.onClick = (e) => {
|
||||
Engine.app.stage.removeChild(text);
|
||||
Engine.app.stage.removeChild(text2);
|
||||
Engine.GameMaster.currentScene.stage.removeChild(text);
|
||||
Engine.GameMaster.currentScene.stage.removeChild(text2);
|
||||
Engine.GameMaster.changeScene(new MissionPickerScene());
|
||||
};
|
||||
|
||||
let b2 = new Button(SettingsButton.rect, SettingsButton.caption, SettingsButton.texture, true);
|
||||
b2.onClick = (e) => {
|
||||
alert('Does nothing for now, just placeholder.');
|
||||
Engine.NotificationManager.Notify('Not finished.', 'info');
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +1,21 @@
|
||||
import { Engine } from '../classes/Bastion';
|
||||
import GuiObject from '../classes/GuiObject';
|
||||
import * as PIXI from 'pixi.js';
|
||||
|
||||
export default class Scene {
|
||||
public stage: PIXI.Container = new PIXI.Container();
|
||||
public gui: GuiObject[] = [];
|
||||
private _events: PIXI.EventEmitter = new PIXI.EventEmitter();
|
||||
|
||||
constructor() {
|
||||
Engine.app.stage.addChild(this.stage);
|
||||
}
|
||||
public destroy() {
|
||||
this.stage.destroy();
|
||||
this.gui.forEach((element) => {
|
||||
element.destroy();
|
||||
});
|
||||
}
|
||||
public GetGuiObject(object: GuiObject) {
|
||||
return this.gui.find((obj) => obj == object);
|
||||
}
|
||||
public GetGuiObjectByName(name: string) {
|
||||
return this.gui.filter((obj) => obj.name == name);
|
||||
}
|
||||
|
||||
public get events(): PIXI.EventEmitter {
|
||||
return this._events;
|
||||
|
Loading…
x
Reference in New Issue
Block a user