diff --git a/README.md b/README.md index 02b0f56..04c6143 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ _The Watchers Lament_ +[latest demo](https://youtu.be/x9l2zzIlhNE) + # Game description and functionality Bastion is a Tower Defense type of game. @@ -47,21 +49,22 @@ The mission selection screen has the following content: Mission screen is reached when the player selects a mission from the Mission selection screen. The Mission screen has the following content: -- The map of the mission (image representation) -- The path of the creeps (line on the map) -- Amount of waves in the mission -- The entrance and exit of the map (marked on the map) -- Starting Gems - The amount of Gems the player starts with -- Button to start the mission (Game screen - Buy phase) -- Button to go back to the Mission selection screen +- The map of the mission (image representation) +- The path of the creeps (line on the map) +- Amount of waves in the mission +- The entrance and exit of the map (marked on the map) +- Starting Gems - The amount of Gems the player starts with +- Button to start the mission (Game screen - Buy phase) +- Button to go back to the Mission selection screen ## Game screen Every game screen (Buy or Combat phase) has the following content: -- Game map -- Options button - Opens the Options panel -- Sidebar - Content changes based on the phase -- Topbar - Shows the player's current HP, Gold, Score and Wave/Total Waves + +- Game map +- Options button - Opens the Options panel +- Sidebar - Content changes based on the phase +- Topbar - Shows the player's current HP, Gold, Score and Wave/Total Waves Example: ![](README_images/2024-09-15-18-47-55.png) @@ -70,17 +73,18 @@ Example: The map is covering the majority of the screen (80%). There is no zooming or panning. Depending on the map aspect ratio, the map may be cropped on the sides. The map is a grid where the player can place towers and through which the creeps will travel. There are two types of ground on the map: -- Path - The path where the creeps will travel -- Buildable - The ground where the player can place towers -- Non-buildable - The ground where the player can not place towers + +- Path - The path where the creeps will travel +- Buildable - The ground where the player can place towers +- Non-buildable - The ground where the player can not place towers ### Options Panel The options panel is opened by pressed the options button located on the top left corner. The options panel allows the player to: -- Restart mission -- Return to main menu -- Close panel (opening it automatically pauses the game) +- Restart mission +- Return to main menu +- Close panel (opening it automatically pauses the game) ### Sidebar @@ -117,6 +121,7 @@ _(razmisljam o tome da se gemovi na pocetku buy phasea moraju kupit i/ili mogu s _(takodjer razmisljam da ima market tower koji se moze buildat)_ ## Game screen - Combat phase + During this phase the player has no input (excep the Options menu) and the game is played 'automatically'. At specific points in time the creeps will spawn at the entrance of the map and start moving towards the exit traversing the preset path. If a tower has an ability to attack a creep it will do so automatically. Type of attack depends on the tower type and the Gems empowering it. @@ -125,6 +130,7 @@ Player may invoke the Options menu at any time during the combat phase. This wil Combat phase will end when all creeps are dead / passed the exit or the player's HP reaches 0. ### Sidebar - Combat phase + In the combat phase the sidebar displays same information but it is disabled. ## Towers @@ -132,33 +138,38 @@ In the combat phase the sidebar displays same information but it is disabled. Towers are the buildings you build on the map grid which attack/help you in defeating the creeps that are traversing the path. Towers always target the the creep closest to the exit. Tower may switch targets if another creep is closer to the exit. They always have a circular range around them within which they will attack creeps (if they have an attack). -Placing a tower on the grid costs a certain amount of Gold defined by the tower, while empowering it via Gem does not cost anything (Gems are not consumed, they are "slotted" and can be later removed). +Placing a tower on the grid costs a certain amount of Gold defined by the tower, while empowering it via Gem does not cost anything (Gems are not consumed, they are "slotted" and can be later removed). Towers on their own can not be upgraded, only the Gems that are empowering them can be. Not all towers can be empowered (via Gems) and they would serve more for utility purposes instead of attacking creeps. ### Tower effects + There are several possible tower effects which describe the general behavior of the tower: #### Shooter + This is standard effect available to each tower. It enables the tower to attack the creeps by shooting projectile(s) at them. #### Trap + The tower places a trap on the ground which will deal damage to the creeps that pass over it. The trap is placed in the range of the tower randomly #### Necromancer tower + This tower spawns creeps which will attack the other creeps. The spawned creeps will have a limited lifespan and will die after a certain amount of time. When this anti-creep meets another creep then one of them will 'die' instantly depending on the their health. ### Shooting Tower + Basic tower that shoots 1 projectile at the closest creep. -- Damage: 1 -- Attack Cooldown: 2s -- Slot count: 3 -- Cost: 100g -- Range: 2.5 Grid units -- Default effects: Shooter +- Damage: 1 +- Attack Cooldown: 2s +- Slot count: 3 +- Cost: 100g +- Range: 2.5 Grid units +- Default effects: Shooter ### Circular Tower [WIP] @@ -167,12 +178,14 @@ Basic tower that shoots 1 projectile at the closest creep. ### Chain tower [WIP] ### Damage types + We have several types of damage within the game: -- Physical (default damage type) -- Divine -- Fire -- Ice -- FrostFire + +- Physical (default damage type) +- Divine +- Fire +- Ice +- FrostFire ## Creeps @@ -184,20 +197,21 @@ Creeps may go through another creep if they are faster (they may overlap). Creeps may have special attributes. ### Creep resistance and weaknesses + Creep may be resistant or weak to a specific type of damage. For each creep there will be a percentage of damage reduction/increase for each damage type. ### Basic Creep -- Health: 2 HP -- Speed: 1 Grid unit per second -- Special attributes: None -- Damage resistance: - - Physical: 0% - - Divine: 0% - - Fire: 0% - - Ice: 0% - - FrostFire: 0% +- Health: 2 HP +- Speed: 1 Grid unit per second +- Special attributes: None +- Damage resistance: + - Physical: 0% + - Divine: 0% + - Fire: 0% + - Ice: 0% + - FrostFire: 0% ### Quick Creep [WIP] @@ -207,18 +221,19 @@ For each creep there will be a percentage of damage reduction/increase for each Requires tower to be empowered with a divinity gem to deal damage, otherwise immune to damage. -- Health: 5 HP -- Speed: 40 pixels per second -- Special attributes: Undead, Weak to Divinity, Resistant to Soulforge -- Damage resistance: - - Physical: 100% - - Divine: -50% - - Fire: 100% - - Ice: 100% - - FrostFire: 100% +- Health: 5 HP +- Speed: 40 pixels per second +- Special attributes: Undead, Weak to Divinity, Resistant to Soulforge +- Damage resistance: + - Physical: 100% + - Divine: -50% + - Fire: 100% + - Ice: 100% + - FrostFire: 100% -## Creep waves -Each round may have multiple waves of creeps. +## Creep waves + +Each round may have multiple waves of creeps. Each wave may have different types of creeps and different amounts of creeps. A new wave may start at any time, even if the previous wave is not finished. Every wave a creep is 'generated' at the map entrance. Once the creep has moved a bit then the next creep in the wave will be 'generated'. @@ -234,42 +249,46 @@ The player starts the game with 200 Gold and can not go below 0 Gold. Gems are not a number resource like Gold is, rather you earn one of the possible Gems upon completing a round. They are placed in your Gem bag which is accessible via the sidebar. Gem has the following properties: -- Name -- Color (used for visual representation) -- Description -- Damage type (used for empowering towers) -- Game effects (used for empowering towers) -- Level +- Name +- Color (used for visual representation) +- Description +- Damage type (used for empowering towers) +- Game effects (used for empowering towers) +- Level #### Possible gem effects + Games can only be sloted in towers. When slotted the gem may provide following effects for that tower: -- Increase damage -- Change the damage type -- Increase attack speed -- Increase range -- Increase number of targets (multi shot) -- Increase number of projectiles + +- Increase damage +- Change the damage type +- Increase attack speed +- Increase range +- Increase number of targets (multi shot) +- Increase number of projectiles #### Gem level + Gem level is a number from 1 to 5. Each level of a Gem enhances the effect of the Gem. The higher the level the more powerful the Gem is. The actual effect of the level depends on the Gem type. #### Gem types + Currently there are 6 Gems: 1. Fire Gem (#FF0000) (fire) - - Description: A firey gem found inside the ancient ruins of a lost volcano dwelling civilization, this gem is infused with many eons of firey, quicky, volcanic energy to deliver fast and burning blows to all creeps. + - Description: A firey gem found inside the ancient ruins of a lost volcano dwelling civilization, this gem is infused with many eons of firey, quicky, volcanic energy to deliver fast and burning blows to all creeps. 2. Yeti Gem (#0000FF) (ice) - - Description: [WIP] + - Description: [WIP] 3. Titalium Gem (#FFFFFF) (white) - - Description: [WIP] + - Description: [WIP] 4. Soulforge Gem (#00FFFF) (cyan) - - Description: [WIP] + - Description: [WIP] 5. Rift Gem (#FF00FF) (purple) - - Description: [WIP] + - Description: [WIP] 6. Divinity Gem (#00FF00) (green) - - Description: [WIP] + - Description: [WIP] _(idealno 6 \* 4 combos)_ _(impossible combos:_ @@ -294,105 +313,118 @@ If the player loses the game, the score is always 0. # Data structures and algorithms ## Mission definition -- Name -- Description -- Map image -- Game map definition -- Array of rounds -- Array of Gem definitions (random type given to player at mission start) + +- Name +- Description +- Map image +- Game map definition +- Array of rounds +- Array of Gem definitions (random type given to player at mission start) ### Game map definition -- Grid size (width, height) -- 2d array of terrain types (Path, Buildable, Non-buildable) -- Array of paths (array of rows and column which represent the path, first cell is the entrance, last cell is the exit) + +- Grid size (width, height) +- 2d array of terrain types (Path, Buildable, Non-buildable) +- Array of paths (array of rows and column which represent the path, first cell is the entrance, last cell is the exit) ### Mission round definition -- Array of waves -- Array of Gem types (which the player can get at the end of the round - only 1 picked out of 3) + +- Array of waves +- Array of Gem types (which the player can get at the end of the round - only 1 picked out of 3) ### Wave definition -- Tick when first creep is generated (calculated once all creeps of the previous wave are generated) -- Ticks between creeps -- Array of creep definitions (identified by creep definition name) together with number of creeps per type + +- Tick when first creep is generated (calculated once all creeps of the previous wave are generated) +- Ticks between creeps +- Array of creep definitions (identified by creep definition name) together with number of creeps per type ## Mission instance -- Mission definition -- Current round index -- Array of waves -- Current HP -- Current Gold -- Current Score -- Array of Gems -- Current game map instance -- Current tick + +- Mission definition +- Current round index +- Array of waves +- Current HP +- Current Gold +- Current Score +- Array of Gems +- Current game map instance +- Current tick ## Game map instance -- Game map definition -- Array of tower instances -- Array of creep instances -- Array of fired bullets + +- Game map definition +- Array of tower instances +- Array of creep instances +- Array of fired bullets ## Wave instance -- Wave definition -- Array of creeps left to be generated (once the array is empty the wave is finished) -## Tower definition -- Name -- Cost (Gold amount) -- Gem slot count (0 if not empowerable) -- Image (sprite) -- Description -- Base damage amount (damage dealt to creeps) -- Attack Cooldown (time between attacks) -- Attack range (in Grid units) -- Array of initial tower effects (enumeration) -- Array of allowed Gem types (enumeration) +- Wave definition +- Array of creeps left to be generated (once the array is empty the wave is finished) +## Tower definition -## Tower instance -- Tower definition -- Grid row and column (position on the map) -- Gems (array of Gems) -- Round in which it was built (used for selling) -- Ticks from last attack (used for attack cooldown) -- Current damage amount -- Current damage type (depends on Gems) -- Array of tower effects (enumeration) +- Name +- Cost (Gold amount) +- Gem slot count (0 if not empowerable) +- Image (sprite) +- Description +- Base damage amount (damage dealt to creeps) +- Attack Cooldown (time between attacks) +- Attack range (in Grid units) +- Array of initial tower effects (enumeration) +- Array of allowed Gem types (enumeration) + +## Tower instance + +- Tower definition +- Grid row and column (position on the map) +- Gems (array of Gems) +- Round in which it was built (used for selling) +- Ticks from last attack (used for attack cooldown) +- Current damage amount +- Current damage type (depends on Gems) +- Array of tower effects (enumeration) ## Trap instance -- Position (x, y in Grid units) -- Damage type -- Damage amount -- Tick created -- Tick duration (lifespan) -- Image (sprite) + +- Position (x, y in Grid units) +- Damage type +- Damage amount +- Tick created +- Tick duration (lifespan) +- Image (sprite) ## Bullet instance -- Current position (x, y in Grid units) -- Target position (x, y in Grid units) -- Damage type -- Damage amount -- Image (sprite) + +- Current position (x, y in Grid units) +- Target position (x, y in Grid units) +- Damage type +- Damage amount +- Image (sprite) ## Creep definition -- Name -- Maximum HP -- Speed -- Image (sprite) -- Damage resistance (percentage for each damage type) -- Special attributes (hardcoded attribute types) + +- Name +- Maximum HP +- Speed +- Image (sprite) +- Damage resistance (percentage for each damage type) +- Special attributes (hardcoded attribute types) ## Creep instance -- Creep definition -- Current position (x, y in Grid units) -- Current HP (also represents damage dealt to player if reaches exit and damage dealt to other creeps if it is an anti-creep) -- Current speed -- Is anti-creep (if true then it will attack other creeps) -- Anti-creep damage type (if anti-creep) + +- Creep definition +- Current position (x, y in Grid units) +- Current HP (also represents damage dealt to player if reaches exit and damage dealt to other creeps if it is an anti-creep) +- Current speed +- Is anti-creep (if true then it will attack other creeps) +- Anti-creep damage type (if anti-creep) # Future work -- Add leaderboard functionality to [Mission screen] -- Ability to restart at the current round of the mission [Options panel] -- When in combat phase the 'Go' button should be replaced with 'Speed up' toggle button [Sidebar - Combat phase] -- Add tower selling functionality [Game screen - Combat phase] -- Add Gem combining functionality [Sidebar - Buy phase] \ No newline at end of file + +- Add leaderboard functionality to [Mission screen] +- Ability to restart at the current round of the mission [Options panel] +- When in combat phase the 'Go' button should be replaced with 'Speed up' toggle button [Sidebar - Combat phase] +- Add tower selling functionality [Game screen - Combat phase] +- Add Gem combining functionality [Sidebar - Buy phase] diff --git a/public/assets/missions/mission_01.json b/public/assets/missions/mission_01.json index ca88432..2d81053 100644 --- a/public/assets/missions/mission_01.json +++ b/public/assets/missions/mission_01.json @@ -3,29 +3,29 @@ "description": "This is the first mission", "gameMap": { "rows": 15, - "columns": 15, + "columns": 20, "cells": [ - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] ], "paths": [ [ diff --git a/public/maps/mission_01.png b/public/maps/mission_01.png new file mode 100644 index 0000000..f741499 Binary files /dev/null and b/public/maps/mission_01.png differ