diff --git a/public/assets/Towers.json b/public/assets/Towers.json new file mode 100644 index 0000000..01f0acd --- /dev/null +++ b/public/assets/Towers.json @@ -0,0 +1,12 @@ +[ + { + "name": "Basic Tower", + "stats": { + "damage": 2, + "cooldown": 2, + "gemSlotsAmount": 2, + "cost": 100, + "range": 7 + } + } +] diff --git a/public/assets/gui/button_02.png b/public/assets/gui/button_02.png old mode 100755 new mode 100644 diff --git a/public/assets/gui/frame.png b/public/assets/gui/frame.png new file mode 100755 index 0000000..2eb8e3b Binary files /dev/null and b/public/assets/gui/frame.png differ diff --git a/public/assets/gui/heart.png b/public/assets/gui/heart.png new file mode 100755 index 0000000..9bbc21d Binary files /dev/null and b/public/assets/gui/heart.png differ diff --git a/public/assets/gui/shield.png b/public/assets/gui/shield.png new file mode 100755 index 0000000..57969ac Binary files /dev/null and b/public/assets/gui/shield.png differ diff --git a/public/assets/gui/star.png b/public/assets/gui/star.png new file mode 100755 index 0000000..20ce16c Binary files /dev/null and b/public/assets/gui/star.png differ diff --git a/public/assets/gui/star_empty.png b/public/assets/gui/star_empty.png new file mode 100755 index 0000000..2682b22 Binary files /dev/null and b/public/assets/gui/star_empty.png differ diff --git a/public/assets/gui/sword_01.png b/public/assets/gui/sword_01.png new file mode 100755 index 0000000..3331068 Binary files /dev/null and b/public/assets/gui/sword_01.png differ diff --git a/public/assets/gui/sword_02.png b/public/assets/gui/sword_02.png new file mode 100755 index 0000000..a6f2ced Binary files /dev/null and b/public/assets/gui/sword_02.png differ diff --git a/src/base/Assets.ts b/src/base/Assets.ts index af333dc..894f7a2 100644 --- a/src/base/Assets.ts +++ b/src/base/Assets.ts @@ -1,5 +1,5 @@ import * as PIXI from 'pixi.js'; -import { CreepStats, MissionDefinition } from './Definitions'; +import { CreepStatsDefinition, MissionDefinition, TowerDefinition } from './Definitions'; export default class Assets { public static async LoadAssets() { @@ -7,11 +7,20 @@ export default class Assets { Assets.ButtonTexture = await PIXI.Assets.load({ src: '/assets/gui/button_02.png', }); + Assets.SidebarTexture = await PIXI.Assets.load({ + src: '/assets/gui/frame.png', + }); + Assets.HealthTexture = await PIXI.Assets.load({ + src: '/assets/gui/heart.png', + }); + Assets.GoldTexture = await PIXI.Assets.load({ + src: '/assets/gui/star.png', + }); Assets.BasicCreepTexture = await PIXI.Assets.load({ src: '/assets/creeps/basic.jpg', }); - console.log('Loading Missions'); await this.LoadMissions(); + await this.LoadTowers(); await this.LoadCreepStats(); } @@ -25,6 +34,12 @@ export default class Assets { Assets.Missions = [await this.LoadMission('/assets/missions/mission_01.json')]; } + private static async LoadTowers() { + const res = await fetch('/assets/Towers.json'); + const towers = await res.json(); + Assets.Towers = towers; + } + private static async LoadMission(missionUrl: string) { const res = await fetch(missionUrl); const mission = await res.json(); @@ -40,10 +55,16 @@ export default class Assets { }); } - public static ButtonTexture: PIXI.Texture; public static BasicCreepTexture: PIXI.Texture; + public static ButtonTexture: PIXI.Texture; + public static SidebarTexture: PIXI.Texture; + public static HealthTexture: PIXI.Texture; + public static GoldTexture: PIXI.Texture; + public static MissionBackgrounds: PIXI.Texture[] = []; public static Missions: MissionDefinition[]; - public static CreepStats: CreepStats[]; + public static Towers: TowerDefinition[]; + public static CreepStats: CreepStatsDefinition[]; + public static DebuggingEnabled: boolean = true; } diff --git a/src/base/Definitions.ts b/src/base/Definitions.ts index 3963d13..4f8bcaa 100644 --- a/src/base/Definitions.ts +++ b/src/base/Definitions.ts @@ -30,14 +30,14 @@ export type WaveDefinition = { creeps: CreepType[]; }; -export type CreepStats = { +export type CreepStatsDefinition = { health: number; speed: number; special: Function; - resistance: CreepResistances; + resistance: CreepResistancesDefinition; }; -export type CreepResistances = { +export type CreepResistancesDefinition = { physical: number; divine: number; fire: number; @@ -45,6 +45,19 @@ export type CreepResistances = { frostfire: number; }; +export type TowerDefinition = { + name: string; + stats: TowerStatsDefinition; +}; + +export type TowerStatsDefinition = { + damage: number; + cooldown: number; + gemSlotsAmount: number; + cost: number; + range: number; +}; + export type PathDefinition = [[row: number, column: number]]; export enum CreepType { @@ -64,3 +77,8 @@ export enum GemType { Titalium = 2, Soulforge = 3, } + +export enum TowerType { + Shooting = 0, + Circle = 1, +} diff --git a/src/components/Creep.ts b/src/components/Creep.ts index 4154d78..0f927c1 100644 --- a/src/components/Creep.ts +++ b/src/components/Creep.ts @@ -1,5 +1,5 @@ import Assets from '../base/Assets'; -import { CreepStats, CreepType, PathDefinition } from '../base/Definitions'; +import { CreepStatsDefinition, CreepType, PathDefinition } from '../base/Definitions'; import GameObject from '../base/GameObject'; import * as PIXI from 'pixi.js'; import GameScene from '../scenes/GameScene'; @@ -14,7 +14,7 @@ export enum CreepEvents { export default class Creep extends GameObject { public creepType: CreepType; private path: PathDefinition; - private stats: CreepStats; + private stats: CreepStatsDefinition; private pathIndex: number = 0; private speed: number; private gameScene: GameScene; diff --git a/src/components/Grid.ts b/src/components/Grid.ts index d7d4d75..4cc5e0b 100644 --- a/src/components/Grid.ts +++ b/src/components/Grid.ts @@ -40,7 +40,7 @@ export class Cell extends GameObject { this.container.addChild(g); this.container.x = this.bounds.x; this.container.y = this.bounds.y; - return; // comment to enable debugging + if (!Assets.DebuggingEnabled) return; const text = new PIXI.Text({ text: `${this.row}|${this.column}`, style: new PIXI.TextStyle({ @@ -101,10 +101,6 @@ export class Grid extends GameObject { protected draw() { console.log('Drawing Grid', this.bounds); this.container.removeChildren(); - // let g = new PIXI.Graphics(); - // g.rect(0, 0, this.bounds.width, this.bounds.height + 100); - // g.fill(0xffffff); - // this.container.addChild(g); let background = new PIXI.Sprite(Assets.MissionBackgrounds[this.gameScene.missionIndex]); background.x = 0; background.y = 0; @@ -113,8 +109,8 @@ export class Grid extends GameObject { this.container.addChild(background); for (let cell of this.cells) { cell.setBounds( - this.gridUnitsToPixels(cell.column), - this.gridUnitsToPixels(cell.row), + parseFloat(this.gridUnitsToPixels(cell.column).toFixed(2)), + parseFloat(this.gridUnitsToPixels(cell.row).toFixed(2)), this.gridUnitsToPixels(1), this.gridUnitsToPixels(1) ); diff --git a/src/components/MissionStats.ts b/src/components/MissionStats.ts index 2beb8eb..c452e03 100644 --- a/src/components/MissionStats.ts +++ b/src/components/MissionStats.ts @@ -1,3 +1,4 @@ +import Assets from '../base/Assets'; import GameObject from '../base/GameObject'; import * as PIXI from 'pixi.js'; @@ -33,18 +34,55 @@ export default class MissionStats extends GameObject { protected draw() { this.container.removeChildren(); - const g = new PIXI.Graphics(); - g.rect(0, 0, this.bounds.width, this.bounds.height); - g.fill(0x000000); - this.container.addChild(g); - const text = new PIXI.Text({ - text: `HP: ${this.hp}\nGold: ${this.gold}`, + const sprite = new PIXI.NineSliceSprite({ + texture: Assets.SidebarTexture, + leftWidth: 100, + topHeight: 100, + rightWidth: 100, + bottomHeight: 100, + }); + sprite.width = this.bounds.width + 200; + sprite.height = this.bounds.height + 5; + sprite.x = sprite.x - 100; + sprite.y = sprite.y - 5; + const healthText = new PIXI.Text({ + text: `HP: ${this.hp}`, style: new PIXI.TextStyle({ fill: 'white', fontSize: 24, + fontWeight: 'bold', + dropShadow: true, }), }); - this.container.addChild(text); + healthText.x = 400; + const goldText = new PIXI.Text({ + text: `Gold: ${this.gold}`, + style: new PIXI.TextStyle({ + fill: 'white', + fontSize: 24, + fontWeight: 'bold', + dropShadow: true, + }), + }); + goldText.x = 400; + goldText.y = 30; + + const healthSprite = new PIXI.Sprite(Assets.HealthTexture); + healthSprite.x = 365; + healthSprite.width = 30; + healthSprite.height = 26; + healthSprite.y = 1; + + const goldSprite = new PIXI.Sprite(Assets.GoldTexture); + goldSprite.x = 365; + goldSprite.width = 30; + goldSprite.height = 26; + goldSprite.y = 30; + this.container.addChild(sprite); + this.container.addChild(healthText); + this.container.addChild(goldText); + this.container.addChild(healthSprite); + this.container.addChild(goldSprite); this.container.x = this.bounds.x; this.container.y = this.bounds.y; } diff --git a/src/components/Sidebar.ts b/src/components/Sidebar.ts new file mode 100644 index 0000000..3969cf2 --- /dev/null +++ b/src/components/Sidebar.ts @@ -0,0 +1,27 @@ +import * as PIXI from 'pixi.js'; +import GameObject from '../base/GameObject'; +import GameScene from '../scenes/GameScene'; +import Assets from '../base/Assets'; + +export default class Sidebar extends GameObject { + private gameScene: GameScene; + constructor(gameScene: GameScene, bounds?: PIXI.Rectangle) { + super(bounds); + this.gameScene = gameScene; + } + protected draw() { + this.container.removeChildren(); + const sprite = new PIXI.NineSliceSprite({ + texture: Assets.SidebarTexture, + leftWidth: 100, + topHeight: 100, + rightWidth: 100, + bottomHeight: 100, + }); + 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; + } +} diff --git a/src/scenes/GameScene.ts b/src/scenes/GameScene.ts index ffb2697..6db7685 100644 --- a/src/scenes/GameScene.ts +++ b/src/scenes/GameScene.ts @@ -3,6 +3,7 @@ import { MissionDefinition } from '../base/Definitions'; import Creep, { CreepEvents } from '../components/Creep'; import { Grid } from '../components/Grid'; import MissionStats from '../components/MissionStats'; +import Sidebar from '../components/Sidebar'; import WaveManager, { WaveManagerEvents } from '../components/WaveManager'; import SceneBase from './SceneBase'; import * as PIXI from 'pixi.js'; @@ -17,6 +18,7 @@ export default class GameScene extends SceneBase { private ticker: PIXI.Ticker; private stats: MissionStats; private waveManager: WaveManager; + private sidebar: Sidebar; private roundMode = RoundMode.Purchase; private changeRoundButton: Button; private currentRound: number = 0; @@ -36,6 +38,7 @@ export default class GameScene extends SceneBase { }); this.stats = new MissionStats(100, 200); this.grid = new Grid(mission.gameMap, this); + this.sidebar = new Sidebar(this); this.gridWidth = mission.mapImage.width; this.gridHeight = mission.mapImage.height; this.ticker = new PIXI.Ticker(); @@ -108,7 +111,9 @@ export default class GameScene extends SceneBase { this.container.addChild(g); this.stats.setBounds(this.getStatusBounds()); this.grid.setBounds(this.getGridBounds()); + this.sidebar.setBounds(this.getSidebarBounds()); this.changeRoundButton.setBounds(this.getChangeRoundButtonBounds()); + this.container.addChild(this.sidebar.container); this.container.addChild(this.stats.container); this.container.addChild(this.grid.container); this.container.addChild(this.changeRoundButton.container); @@ -116,15 +121,16 @@ export default class GameScene extends SceneBase { this.container.y = this.bounds.y; } + private getSidebarBounds(): PIXI.Rectangle { + return new PIXI.Rectangle(this.bounds.width - 350, 0, 350, this.bounds.height); + } private getStatusBounds(): PIXI.Rectangle { // Top / Center - return new PIXI.Rectangle(this.bounds.width / 2 - 200 / 2, 0, 200, 100); + return new PIXI.Rectangle(0, 0, this.bounds.width, 100); } private getGridBounds(): PIXI.Rectangle { // Center / Center - let width = 600; - let height = 600; return new PIXI.Rectangle( this.bounds.width / 2 - this.gridWidth / 2, this.bounds.height / 2 - this.gridHeight / 2, @@ -134,7 +140,7 @@ export default class GameScene extends SceneBase { } private getChangeRoundButtonBounds(): PIXI.Rectangle { // Center / Center - let width = 300; + let width = 350; let height = 150; return new PIXI.Rectangle(this.bounds.width - width, this.bounds.height - height, width, height); }