diff --git a/public/assets/gui/frame_c3_01.png b/public/assets/gui/frame_03.png similarity index 100% rename from public/assets/gui/frame_c3_01.png rename to public/assets/gui/frame_03.png diff --git a/public/assets/json/Towers.json b/public/assets/json/Towers.json index eac4067..f60e715 100644 --- a/public/assets/json/Towers.json +++ b/public/assets/json/Towers.json @@ -4,6 +4,8 @@ "behaviour": "BasicTowerBehaviour", "sprite": "basic_tower", "texture": null, + "projectileTextures": [], + "projectileTexturesArrayLength": 5, "description": "The building block of society, nothing more basic exists.", "stats": { "damage": 2, diff --git a/public/assets/projectiles/basic_tower.png b/public/assets/projectiles/basic_tower.png deleted file mode 100644 index 272ad51..0000000 Binary files a/public/assets/projectiles/basic_tower.png and /dev/null differ diff --git a/public/assets/projectiles/basic_tower/0.png b/public/assets/projectiles/basic_tower/0.png new file mode 100644 index 0000000..5bcdebd Binary files /dev/null and b/public/assets/projectiles/basic_tower/0.png differ diff --git a/public/assets/projectiles/basic_tower/1.png b/public/assets/projectiles/basic_tower/1.png new file mode 100644 index 0000000..40ff7ae Binary files /dev/null and b/public/assets/projectiles/basic_tower/1.png differ diff --git a/public/assets/projectiles/basic_tower/2.png b/public/assets/projectiles/basic_tower/2.png new file mode 100644 index 0000000..1fe70f0 Binary files /dev/null and b/public/assets/projectiles/basic_tower/2.png differ diff --git a/public/assets/projectiles/basic_tower/3.png b/public/assets/projectiles/basic_tower/3.png new file mode 100644 index 0000000..b5258c0 Binary files /dev/null and b/public/assets/projectiles/basic_tower/3.png differ diff --git a/public/assets/projectiles/basic_tower/4.png b/public/assets/projectiles/basic_tower/4.png new file mode 100644 index 0000000..5bcdebd Binary files /dev/null and b/public/assets/projectiles/basic_tower/4.png differ diff --git a/src/classes/Assets.ts b/src/classes/Assets.ts index 86a1189..a9a016a 100644 --- a/src/classes/Assets.ts +++ b/src/classes/Assets.ts @@ -1,14 +1,11 @@ import * as PIXI from 'pixi.js'; -import { CreepDefinition, CreepStatsDefinition, MissionDefinition, TowerDefinition } from './Definitions'; +import { CreepDefinition, MissionDefinition, TowerDefinition } from './Definitions'; import { Engine } from './Bastion'; 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 Frame03Texture: PIXI.Texture; public static FrameBackground: PIXI.Texture; public static FrameTowerTab: PIXI.Texture; public static VioletBackground: PIXI.Texture; @@ -29,6 +26,7 @@ export default class GameAssets { private static text; private static async Load(src) { this.text.text = 'Loading asset: ' + src; + console.log('LOADING ' + src); return await PIXI.Assets.load({ src: src, }); @@ -63,11 +61,12 @@ export default class GameAssets { this.text.y = Engine.app.canvas.height / 2 + 50; this.text.anchor.set(0.5, 0.5); Engine.app.stage.addChild(this.text); - this.Load('/aclonica.woff2'); + await this.Load('/aclonica.woff2'); this.Button01Texture = await this.Load('/assets/gui/button_01.png'); this.Button02Texture = await this.Load('/assets/gui/button_02.png'); this.Frame01Texture = await this.Load('/assets/gui/frame_01.png'); this.Frame02Texture = await this.Load('/assets/gui/frame_02.png'); + this.Frame03Texture = await this.Load('/assets/gui/frame_03.png'); this.FrameBackground = await this.Load('/assets/gui/background_01.png'); this.FrameTowerTab = await this.Load('/assets/gui/background_02.png'); this.VioletBackground = await this.Load('/assets/gui/frame_violet.png'); @@ -76,8 +75,6 @@ export default class GameAssets { this.HealthTexture = await this.Load('/assets/gui/heart.png'); this.GoldTexture = await this.Load('/assets/gui/money.png'); this.WaveTexture = await this.Load('/assets/gui/wave.png'); - this.BasicTowerTexture = await this.Load('/assets/towers/basic_tower.png'); - this.BasicProjectileTexture = await this.Load('/assets/projectiles/basic_tower.png'); await this.LoadMissions(); await this.LoadTowers(); await this.LoadCreeps(); @@ -108,7 +105,17 @@ export default class GameAssets { private static async LoadTowers() { const res = await fetch('/assets/json/Towers.json'); const towers = await res.json(); - GameAssets.Towers = towers; + this.Towers = towers; + console.log(this.Towers); + for (let idx = 0; idx < this.Towers.length; idx++) { + const tower = this.Towers[idx]; + for (let i = 0; i < tower.projectileTexturesArrayLength; i++) { + console.log(`WANT TO LOAD /assets/projectiles/${tower.sprite}/${i}.png`); + const texture = await this.Load(`/assets/projectiles/${tower.sprite}/${i}.png`); + tower.projectileTextures[i] = texture; + console.log(tower.projectileTextures); + } + } towers.forEach(async (tower) => { let index = this.TowerSprites.length - 1; if (index == -1) index = 0; diff --git a/src/classes/Definitions.ts b/src/classes/Definitions.ts index c75319d..da4701d 100644 --- a/src/classes/Definitions.ts +++ b/src/classes/Definitions.ts @@ -57,6 +57,8 @@ export type TowerDefinition = { sprite: string; description: string; texture: PIXI.Texture; + projectileTextures: PIXI.Texture[]; + projectileTexturesArrayLength: number; stats: TowerStatsDefinition; }; @@ -90,6 +92,6 @@ export enum GemType { } export enum TowerType { - Shooting = 0, + Basic = 0, Circle = 1, } diff --git a/src/classes/game/Creep.ts b/src/classes/game/Creep.ts index 78e9403..2b6e1cc 100644 --- a/src/classes/game/Creep.ts +++ b/src/classes/game/Creep.ts @@ -21,6 +21,8 @@ export default class Creep extends GameObject { private pathIndex: number = 0; private speed: number; private direction: number = 1; + private healthBarGraphics: PIXI.Graphics = new PIXI.Graphics(); + private healthBarWidth = 50; public health: number; public maxHealth: number; public escaped: boolean = false; @@ -37,6 +39,7 @@ export default class Creep extends GameObject { // Initially flip sprite to the right, since the asset is facing left. this.sprite.scale.x *= -1; this.sprite.anchor.set(0.5, 0.5); + this.sprite.animationSpeed = 0.3; this.sprite.play(); this.id = id; // Explanation: WaveManager spawns all creeps instantly, and since I don't want @@ -46,6 +49,7 @@ export default class Creep extends GameObject { this.container.y = -50; this.sprite.width = Engine.GridCellSize; this.sprite.height = Engine.GridCellSize; + this.bb.width = this.sprite.width; this.speed = this.stats.speed / 60; this.health = this.stats.health; this.maxHealth = this.stats.health; @@ -56,9 +60,24 @@ export default class Creep extends GameObject { Engine.GameScene.events.on(CreepEvents.TakenDamage, (creepID, damage) => { if (creepID != this.id) return; this.health -= damage; + this.UpdateHealthbar(); }); Engine.Grid.container.addChild(this.container); + this.container.addChild(this.healthBarGraphics); this.container.addChild(this.sprite); + this.UpdateHealthbar(); + } + private UpdateHealthbar() { + this.healthBarGraphics.clear(); + const hp = this.health; + const maxHp = this.maxHealth; + const percent = hp / maxHp; + const width = this.healthBarWidth * percent; + // ! TODO: MAKE THIS BETTER! It works like this now, but I don't like how its implemented. + this.healthBarGraphics.rect(-this.healthBarWidth / 2 + 5, -30, this.healthBarWidth, 10); + this.healthBarGraphics.fill({ color: 0x00ff00 }); + this.healthBarGraphics.rect(-this.healthBarWidth / 2 + 5, -30, width, 10); + this.healthBarGraphics.fill({ color: 0xff0000 }); } public update(elapsedMS: number) { if (this.dead) return; diff --git a/src/classes/game/Grid.ts b/src/classes/game/Grid.ts index 7959cf6..1209044 100644 --- a/src/classes/game/Grid.ts +++ b/src/classes/game/Grid.ts @@ -37,20 +37,6 @@ export class Cell extends GameObject { this.clickDetector.onpointerdown = (e) => { Engine.Grid.onGridCellClicked(row, column); }; - - // const text = new PIXI.Text({ - // text: `${this.row}|${this.column}`, - // style: new PIXI.TextStyle({ - // fill: 0xffffff, - // dropShadow: true, - // fontSize: 16, - // }), - // }); - // this.container.addChild(text); - // text.anchor.set(0.5, 0.5); - // text.x = this.bb.width / 2; - // text.y = this.bb.height / 2; - // if (isPath) text.text += 'p'; } public gDraw() { this.g = new PIXI.Graphics({ @@ -143,5 +129,6 @@ export class Grid extends GameObject { public getCellByRowAndCol(row, column) { return this.cells.filter((item) => item.row == row && item.column == column)[0]; } + // Not defined here, rather GameScene defines it. This is just for TS. public onGridCellClicked(row, column) {} } diff --git a/src/classes/game/Projectile.ts b/src/classes/game/Projectile.ts index d36bb38..e4811ac 100644 --- a/src/classes/game/Projectile.ts +++ b/src/classes/game/Projectile.ts @@ -11,21 +11,21 @@ export function calculateAngleToPoint(x, y, targetX, targetY) { export default class Projectile extends GameObject { public deleteMe: boolean = false; - public sprite: PIXI.Sprite; + public sprite: PIXI.AnimatedSprite; public x: number; public y: number; public angle: number; public speed: number; public damage: number; public timeToLive: number = 1; - constructor(x, y, spriteTexture, angle, damage) { + constructor(x, y, textures, angle, damage) { super(); this.x = x; this.y = y; this.damage = damage; - - this.sprite = new PIXI.Sprite({ texture: spriteTexture, scale: 0.5, rotation: angle }); + this.sprite = new PIXI.AnimatedSprite({ textures: textures, scale: 0.25, rotation: angle }); this.sprite.anchor.set(0.5); + this.sprite.play(); this.container.x = this.x; this.container.y = this.y; this.container.addChild(this.sprite); diff --git a/src/classes/game/Tower.ts b/src/classes/game/Tower.ts index 971d2a5..d2506d8 100644 --- a/src/classes/game/Tower.ts +++ b/src/classes/game/Tower.ts @@ -57,17 +57,21 @@ export class Tower extends GameObject { this.container.addChild(this.sprite); parent.container.addChild(this.container); parent.clickDetector.onmouseenter = (e) => { - 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 }); + this.showRangeDisplay(); }; parent.clickDetector.onmouseleave = (e) => { this.graphics.clear(); }; Engine.GameMaster.currentScene.stage.addChild(this.graphics); + this.showRangeDisplay(); + } + public showRangeDisplay() { + 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 }); } public GetCreepsInRange() { let creeps = Engine.Grid.creeps; @@ -86,7 +90,7 @@ export class Tower extends GameObject { 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) + new Projectile(x, y, this.definition.projectileTextures, angle, this.definition.stats.damage) ); } public update(elapsedMS: any): void { diff --git a/src/classes/game/TowerManager.ts b/src/classes/game/TowerManager.ts index afc8d28..e4fcd73 100644 --- a/src/classes/game/TowerManager.ts +++ b/src/classes/game/TowerManager.ts @@ -2,8 +2,8 @@ import * as PIXI from 'pixi.js'; import { Engine } from '../Bastion'; import { TerrainType, TowerDefinition } from '../Definitions'; import GameAssets from '../Assets'; -import GameObject from '../GameObject'; import { Tower, TowerEvents } from './Tower'; +import { Cell } from './Grid'; export enum TowerBehaviours { BasicTowerBehaviour = 'BasicTowerBehaviour', @@ -34,8 +34,13 @@ export default class TowerManager { public PlayerClickOnGrid(row, column) { if (!this.canPlaceTowers) return; if (this.isPlacingTower) { - if (!this.selectedTower) + if (!this.selectedTower) { + Engine.NotificationManager.Notify( + 'TowerManager.selectedTower is null when trying to place tower.', + 'danger' + ); throw console.warn('TowerManager.selectedTower is null when trying to place tower.'); + } this.PlaceTower(this.selectedTower, row, column, this.selectedTower.behaviour); } } @@ -65,11 +70,13 @@ export default class TowerManager { let tower = new Tower(row, column, sprite, definition, behaviour); this.towers.push(tower); this.ToggleChoosingTowerLocation('RESET'); - console.log('SHOULDVE PLACED TOWER'); - console.log(this.selectedTower); this.selectedTower = null; Engine.GameScene.events.emit(TowerEvents.TowerPlacedEvent, definition.name); } else { + Engine.NotificationManager.Notify( + 'Can not place tower on path or other tower, choose another spot.', + 'warn' + ); console.warn('Can not place tower on occupied spot or path. Try again.'); } } diff --git a/src/classes/gui/SelectedTowerPanel.ts b/src/classes/gui/SelectedTowerPanel.ts new file mode 100644 index 0000000..322f407 --- /dev/null +++ b/src/classes/gui/SelectedTowerPanel.ts @@ -0,0 +1,32 @@ +import * as PIXI from 'pixi.js'; +import GuiObject from '../GuiObject'; +import GameAssets from '../Assets'; +import { Engine } from '../Bastion'; + +// ! TODO NEXT! + +export default class SelectedTowerPanel extends GuiObject { + private bounds: PIXI.Rectangle; + private towerPanel: PIXI.NineSliceSprite; + + constructor(bounds: PIXI.Rectangle) { + super(false); + this.bounds = bounds; + this.container.x = this.bounds.x; + this.container.y = this.bounds.y; + this.towerPanel = new PIXI.NineSliceSprite({ + texture: GameAssets.FrameTowerTab, + leftWidth: 1000, + topHeight: 1000, + rightWidth: 1000, + bottomHeight: 1000, + }); + this.towerPanel.x = -300; + this.towerPanel.y = -300; + this.towerPanel.width = this.bounds.width; + this.towerPanel.height = this.bounds.height; + + this.container.addChild(this.towerPanel); + Engine.GameMaster.currentScene.stage.addChild(this.container); + } +} diff --git a/src/classes/gui/Tooltip.ts b/src/classes/gui/Tooltip.ts new file mode 100644 index 0000000..28cdb15 --- /dev/null +++ b/src/classes/gui/Tooltip.ts @@ -0,0 +1,30 @@ +import * as PIXI from 'pixi.js'; +import GuiObject from '../GuiObject'; +import GameAssets from '../Assets'; + +// ! TODO NEXT! + +export default class Tooltip extends GuiObject { + private bounds: PIXI.Rectangle; + private tooltipSprite: PIXI.NineSliceSprite; + + constructor(bounds: PIXI.Rectangle) { + super(false); + this.bounds = bounds; + this.container.x = this.bounds.x; + this.container.y = this.bounds.y; + this.tooltipSprite = new PIXI.NineSliceSprite({ + texture: GameAssets.FrameTowerTab, + leftWidth: 1000, + topHeight: 1000, + rightWidth: 1000, + bottomHeight: 1000, + }); + this.tooltipSprite.x = 0; + this.tooltipSprite.y = 0; + this.tooltipSprite.width = this.bounds.width; + this.tooltipSprite.height = this.bounds.height; + + this.container.addChild(this.tooltipSprite); + } +} diff --git a/src/utils.ts b/src/utils.ts deleted file mode 100644 index c604173..0000000 --- a/src/utils.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function log(msg: any) { - console.log(msg); -}