diff --git a/docs/todos.md b/docs/todos.md index 808b08a..dc3bc74 100644 --- a/docs/todos.md +++ b/docs/todos.md @@ -26,8 +26,7 @@ List of things to implement following the "release" of the minimum viable produc ## Other -- [ ] Disable player action during combat phase. - [ ] Add sound effects - [x] Tutorial image/mission -- [ ] Pause menu +- [x] Pause menu - [x] Score screen when winning/losing map diff --git a/public/assets/creeps/green_spritesheet.png b/public/assets/creeps/green_spritesheet.png new file mode 100644 index 0000000..18c03de Binary files /dev/null and b/public/assets/creeps/green_spritesheet.png differ diff --git a/public/assets/creeps/orange_spritesheet.png b/public/assets/creeps/orange_spritesheet.png new file mode 100644 index 0000000..10cafe6 Binary files /dev/null and b/public/assets/creeps/orange_spritesheet.png differ diff --git a/public/assets/creeps/phood_spritesheet.png b/public/assets/creeps/phood_spritesheet.png new file mode 100644 index 0000000..eb5970f Binary files /dev/null and b/public/assets/creeps/phood_spritesheet.png differ diff --git a/public/assets/json/Creeps.json b/public/assets/json/Creeps.json index d1ad5fc..b4e43e6 100644 --- a/public/assets/json/Creeps.json +++ b/public/assets/json/Creeps.json @@ -2,14 +2,15 @@ { "name": "basic", "sprite": "wood", + "tint": "0xffffff", "textures": [], "textureArrayLength": 12, "stats": { - "health": 5, - "speed": 4, + "health": 2, + "speed": 3, "special": null, "resistance": { - "physical": 0, + "physical": 0.05, "divine": 0, "fire": 0, "ice": 0, @@ -20,11 +21,12 @@ { "name": "quick", "sprite": "zombie", + "tint": "0xffffff", "textures": [], "textureArrayLength": 8, "stats": { - "health": 2, - "speed": 6, + "health": 1, + "speed": 5, "special": null, "resistance": { "physical": 0, @@ -38,10 +40,11 @@ { "name": "tank", "sprite": "skeleton", + "tint": "0xffffff", "textures": [], "textureArrayLength": 12, "stats": { - "health": 12, + "health": 5, "speed": 2, "special": null, "resistance": { @@ -56,29 +59,50 @@ { "name": "cloaker", "sprite": "hood", + "tint": "0xffffff", "textures": [], "textureArrayLength": 12, "stats": { - "health": 12, - "speed": 2, + "health": 7, + "speed": 3, "special": null, "resistance": { "physical": 0, - "divine": 0, - "fire": 0, - "ice": 0, - "frostfire": 0 + "divine": 1, + "fire": 1, + "ice": 1, + "frostfire": 1 } } }, { "name": "demon", "sprite": "demon", + "tint": "0xffffff", "textures": [], "textureArrayLength": 8, "stats": { - "health": 12, - "speed": 2, + "health": 5, + "speed": 3, + "special": null, + "resistance": { + "physical": 1, + "divine": -0.25, + "fire": 1, + "ice": 1, + "frostfire": 1 + } + } + }, + { + "name": "maker", + "sprite": "pumpkin", + "tint": "0xffffff", + "textures": [], + "textureArrayLength": 11, + "stats": { + "health": 5, + "speed": 3, "special": null, "resistance": { "physical": 0, @@ -89,17 +113,57 @@ } } }, + { - "name": "maker", - "sprite": "pumpkin", + "name": "monster", + "sprite": "green", + "tint": "0xffffff", "textures": [], - "textureArrayLength": 11, + "textureArrayLength": 12, "stats": { - "health": 11, - "speed": 2, + "health": 30, + "speed": 1, "special": null, "resistance": { - "physical": 0, + "physical": 0.05, + "divine": 0.05, + "fire": -0.25, + "ice": 0.05, + "frostfire": 0.05 + } + } + }, + { + "name": "remaker", + "sprite": "orange", + "tint": "0xffffff", + "textures": [], + "textureArrayLength": 12, + "stats": { + "health": 2, + "speed": 3, + "special": null, + "resistance": { + "physical": 0.05, + "divine": 0, + "fire": 0, + "ice": 0, + "frostfire": 0 + } + } + }, + { + "name": "elite", + "sprite": "phood", + "tint": "0xffffff", + "textures": [], + "textureArrayLength": 12, + "stats": { + "health": 2, + "speed": 3, + "special": null, + "resistance": { + "physical": 0.05, "divine": 0, "fire": 0, "ice": 0, diff --git a/public/assets/json/Gems.json b/public/assets/json/Gems.json index ab4106b..3c694c2 100644 --- a/public/assets/json/Gems.json +++ b/public/assets/json/Gems.json @@ -584,7 +584,7 @@ "attackSpeedUp": 100, "rangeUp": 2, "timeToLiveUp": 200, - "pierceUp": 20, + "pierceUp": 3, "gemValueUp": 0 } ], diff --git a/public/assets/json/Towers.json b/public/assets/json/Towers.json index 7f15e5f..c8e1f19 100644 --- a/public/assets/json/Towers.json +++ b/public/assets/json/Towers.json @@ -28,12 +28,12 @@ "projectileTexturesArrayLength": 4, "description": "Shoots 8 projectiles in a circle, they may miss.", "stats": { - "damage": 3, - "cooldown": 3000, + "damage": 1, + "cooldown": 2000, "gemSlotsAmount": 2, - "cost": 50, + "cost": 55, "range": 3, - "timeToLive": 20, + "timeToLive": 18, "pierce": 5 } }, @@ -47,10 +47,10 @@ "projectileTexturesArrayLength": 4, "description": "Zap zap zap! This towers shots connect to other enemies!", "stats": { - "damage": 3, + "damage": 2, "cooldown": 3500, "gemSlotsAmount": 2, - "cost": 100, + "cost": 110, "range": 3, "timeToLive": 12, "pierce": 1 @@ -66,7 +66,7 @@ "projectileTexturesArrayLength": 4, "description": "Doesn't shoot, instead buffs other towers with some of its power.", "stats": { - "damage": 4, + "damage": 3, "cooldown": 1000, "gemSlotsAmount": 3, "cost": 200, @@ -86,12 +86,12 @@ "description": "Behaves like the Basic Tower, only its shots stop creeps in their tracks!", "stats": { "damage": 2, - "cooldown": 2250, + "cooldown": 2200, "gemSlotsAmount": 2, - "cost": 75, + "cost": 80, "range": 3.25, "timeToLive": 12, - "pierce": 1 + "pierce": 2 } }, { @@ -104,13 +104,13 @@ "projectileTexturesArrayLength": 4, "description": "Shoots a quick, high pierce rail projectile at creeps.", "stats": { - "damage": 4, - "cooldown": 3750, + "damage": 5, + "cooldown": 5020, "gemSlotsAmount": 3, - "cost": 125, + "cost": 134, "range": 2.5, "timeToLive": 12, - "pierce": 30 + "pierce": 10 } }, { diff --git a/public/assets/missions/01_first_steps.json b/public/assets/missions/01_first_steps.json index 313c3ea..35f17a4 100644 --- a/public/assets/missions/01_first_steps.json +++ b/public/assets/missions/01_first_steps.json @@ -62,15 +62,30 @@ { "firstCreepSpawnTick": 500, "spawnIntervalTicks": 1000, - "creeps": [0, 0, 0] + "creeps": [0, 0, 0, 0, 0] }, { "firstCreepSpawnTick": 4000, "spawnIntervalTicks": 1000, - "creeps": [0, 0, 0, 0] + "creeps": [0, 0, 0, 0, 0] } ], - "offeredGems": [0, 1] + "offeredGems": [0, 1, 0, 1] + }, + { + "waves": [ + { + "firstCreepSpawnTick": 500, + "spawnIntervalTicks": 1000, + "creeps": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + }, + { + "firstCreepSpawnTick": 1000, + "spawnIntervalTicks": 1000, + "creeps": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + } + ], + "offeredGems": [0, 1, 0, 1] } ] } diff --git a/public/assets/missions/02_the_turn.json b/public/assets/missions/02_the_turn.json index e404c94..4fd1211 100644 --- a/public/assets/missions/02_the_turn.json +++ b/public/assets/missions/02_the_turn.json @@ -99,7 +99,7 @@ { "firstCreepSpawnTick": 500, "spawnIntervalTicks": 500, - "creeps": [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 2] + "creeps": [0] } ], "offeredGems": [0, 0, 0, 0] diff --git a/src/classes/Assets.ts b/src/classes/Assets.ts index 2da0b83..6d2c5de 100644 --- a/src/classes/Assets.ts +++ b/src/classes/Assets.ts @@ -49,7 +49,7 @@ export default class GameAssets { private static text; private static counter = 0; private static async Load(src) { - this.text.text = `Loading asset: ${src} (${this.counter}/99)`; + this.text.text = `Loading asset: ${src} (${this.counter}/102)`; this.counter++; return await PIXI.Assets.load({ src: src, diff --git a/src/classes/Definitions.ts b/src/classes/Definitions.ts index b411dcb..bb88c22 100644 --- a/src/classes/Definitions.ts +++ b/src/classes/Definitions.ts @@ -32,6 +32,7 @@ export type WaveDefinition = { export type CreepDefinition = { name: string; sprite: string; + tint: PIXI.ColorSource; textures: PIXI.Texture[]; textureArrayLength: number; stats: CreepStatsDefinition; @@ -113,6 +114,9 @@ export enum CreepType { Cloaker = 3, Demon = 4, Maker = 5, + Monster = 6, + Remaker = 7, + Elite = 8, } export enum GemType { diff --git a/src/classes/game/Creep.ts b/src/classes/game/Creep.ts index 6483cc3..0934bab 100644 --- a/src/classes/game/Creep.ts +++ b/src/classes/game/Creep.ts @@ -49,6 +49,7 @@ export default class Creep extends GameObject { this.sprite.scale.x *= -1; this.sprite.anchor.set(0.5, 0.5); this.sprite.animationSpeed = 0.3; + this.sprite.tint = Assets.Creeps[this.creepType].tint; this.sprite.play(); this.id = id; // Explanation: WaveManager spawns all creeps instantly, and since I don't want @@ -63,20 +64,20 @@ export default class Creep extends GameObject { this.health = this.stats.health; this.maxHealth = this.stats.health; this.path = path; - // Added + 32 to center them. this.x = path[0][0] * Engine.GridCellSize + Engine.GridCellSize / 2; this.y = path[0][1] * Engine.GridCellSize + Engine.GridCellSize / 2; - // TODO: Unsubscribe from events once the scene is destroyed Engine.GameScene.events.on( CreepEvents.TakenDamage, (creepID, damage, gemResistanceModifications: CreepResistancesDefinition) => { if (creepID != this.id) return; if (this.effects.find((e) => e.effectEnum == CreepEffects.DebuffTowerDebuff)) { damage = damage * 1.5; - console.log('multiplying damage, ' + damage); } // Apply resistances. - this.health -= damage + damage * (gemResistanceModifications.physical - this.stats.resistance.physical); + this.health -= Math.max( + damage + damage * (gemResistanceModifications.physical - this.stats.resistance.physical), + 0 + ); if (gemResistanceModifications.fire != 0) this.health -= Math.max(damage * (gemResistanceModifications.fire - this.stats.resistance.fire), 0); if (gemResistanceModifications.ice != 0) @@ -98,7 +99,6 @@ export default class Creep extends GameObject { CreepEvents.GiveEffect, (creepID: number, effect: CreepEffects, durationInMS: number) => { if (creepID != this.id) return; - console.log(' I CAUGHT THE EVENT!'); if (this.effects.find((e) => e.effectEnum == effect) == undefined) this.effects.push(new Effect(effect, durationInMS)); } @@ -224,13 +224,13 @@ export default class Creep extends GameObject { this.container.y = this.y; } - public takeDamage(amount: number) { - this.health -= amount; - if (this.health < 0 && !this.died) { - this.died = true; - this.events.emit(CreepEvents.Died, this); - } - } + // public takeDamage(amount: number) { + // this.health -= amount; + // if (this.health < 0 && !this.died) { + // this.died = true; + // this.events.emit(CreepEvents.Died, this); + // } + // } public destroy() { super.destroy(); diff --git a/src/classes/gui/GamePausedDialog.ts b/src/classes/gui/GamePausedDialog.ts index 9a19fb9..19c3635 100644 --- a/src/classes/gui/GamePausedDialog.ts +++ b/src/classes/gui/GamePausedDialog.ts @@ -19,16 +19,15 @@ export default class GamePausedDialog extends ModalDialogBase { protected override createContent(): PIXI.Container { const container = new PIXI.Container(); - this.btnMainMenu = new Button(new PIXI.Rectangle(0, 0, 300, 60), 'Main Menu', ButtonTexture.Button01); - this.btnMainMenu.onClick = this.onMainMenuClick.bind(this); - container.addChild(this.btnMainMenu.container); + this.btnContinue = new Button(new PIXI.Rectangle(0, 0, 300, 60), 'Continue', ButtonTexture.Button01); + this.btnContinue.onClick = this.onContinueClick.bind(this); + container.addChild(this.btnContinue.container); this.btnRetry = new Button(new PIXI.Rectangle(0, 70, 300, 60), 'Retry', ButtonTexture.Button01); this.btnRetry.onClick = this.onRetryClick.bind(this); container.addChild(this.btnRetry.container); - - this.btnContinue = new Button(new PIXI.Rectangle(0, 140, 300, 60), 'Continue', ButtonTexture.Button01); - this.btnContinue.onClick = this.onContinueClick.bind(this); - container.addChild(this.btnContinue.container); + this.btnMainMenu = new Button(new PIXI.Rectangle(0, 140, 300, 60), 'Main Menu', ButtonTexture.Button01); + this.btnMainMenu.onClick = this.onMainMenuClick.bind(this); + container.addChild(this.btnMainMenu.container); return container; } diff --git a/src/scenes/Game.ts b/src/scenes/Game.ts index 0570a41..1ba6765 100644 --- a/src/scenes/Game.ts +++ b/src/scenes/Game.ts @@ -251,7 +251,6 @@ export class GameScene extends Scene { }, }, }); - // offerText.x -= offerText.width; Engine.GameMaster.currentScene.stage.addChildAt(offerText, 0); gemsToOffer.forEach((gType, index) => { let _Gem = new Gem(gType, true);