improvement
@ -12,3 +12,7 @@ The [design document](/docs/design.md) contains the starting idea which was init
|
|||||||
## Todos
|
## Todos
|
||||||
|
|
||||||
Todos are available [here](/docs/todos.md) which contain self-made tasks which should get done or are already done.
|
Todos are available [here](/docs/todos.md) which contain self-made tasks which should get done or are already done.
|
||||||
|
|
||||||
|
## Extra documentation
|
||||||
|
|
||||||
|
Extra documentation is available [here](/docs)
|
||||||
|
43
docs/linecount.md
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
Generated by: `find ./src -name '*.ts' | xargs wc -l`
|
||||||
|
92 ./src/main.ts
|
||||||
|
1 ./src/vite-env.d.ts
|
||||||
|
17 ./src/classes/GameUIConstants.ts
|
||||||
|
145 ./src/classes/gui/TowerTab.ts
|
||||||
|
375 ./src/classes/gui/TowerPanel.ts
|
||||||
|
52 ./src/classes/gui/TextInput.ts
|
||||||
|
211 ./src/classes/gui/ModalDialog.ts
|
||||||
|
51 ./src/classes/gui/Sidebar.ts
|
||||||
|
122 ./src/classes/gui/HighScoreDialog.ts
|
||||||
|
70 ./src/classes/gui/Button.ts
|
||||||
|
60 ./src/classes/gui/Gemsmith.ts
|
||||||
|
154 ./src/classes/gui/EndGameDialog.ts
|
||||||
|
220 ./src/classes/gui/GemTab.ts
|
||||||
|
59 ./src/classes/gui/GamePausedDialog.ts
|
||||||
|
36 ./src/classes/gui/MessageBox.ts
|
||||||
|
205 ./src/classes/gui/Tooltip.ts
|
||||||
|
126 ./src/classes/Definitions.ts
|
||||||
|
77 ./src/classes/game/WaveManager.ts
|
||||||
|
260 ./src/classes/game/Grid.ts
|
||||||
|
51 ./src/classes/game/Gem.ts
|
||||||
|
114 ./src/classes/game/TowerBehaviours.ts
|
||||||
|
154 ./src/classes/game/Tower.ts
|
||||||
|
180 ./src/classes/game/MissionStats.ts
|
||||||
|
100 ./src/classes/game/AnimationManager.ts
|
||||||
|
177 ./src/classes/game/Creep.ts
|
||||||
|
47 ./src/classes/game/KeyboardManager.ts
|
||||||
|
104 ./src/classes/game/Projectile.ts
|
||||||
|
86 ./src/classes/game/NotificationManager.ts
|
||||||
|
130 ./src/classes/game/TowerManager.ts
|
||||||
|
71 ./src/classes/game/HighScoreManager.ts
|
||||||
|
76 ./src/classes/GuiObject.ts
|
||||||
|
203 ./src/classes/Assets.ts
|
||||||
|
52 ./src/classes/GameObject.ts
|
||||||
|
68 ./src/classes/Bastion.ts
|
||||||
|
30 ./src/classes/Events.ts
|
||||||
|
37 ./src/scenes/Scene.ts
|
||||||
|
17 ./src/scenes/Settings.ts
|
||||||
|
67 ./src/scenes/HowToPlay.ts
|
||||||
|
59 ./src/scenes/Main.ts
|
||||||
|
353 ./src/scenes/Game.ts
|
||||||
|
27 ./src/scenes/MissionPicker.ts
|
||||||
|
`4536 total`
|
@ -17,6 +17,7 @@ List of things to implement following the "release" of the minimum viable produc
|
|||||||
- [x] Tower info on click
|
- [x] Tower info on click
|
||||||
- [x] Animate projectiles
|
- [x] Animate projectiles
|
||||||
- [x] Better mouseover tracking when placing tower and showing radius
|
- [x] Better mouseover tracking when placing tower and showing radius
|
||||||
|
- [x] Sell tower button
|
||||||
|
|
||||||
## Gems
|
## Gems
|
||||||
|
|
||||||
@ -25,8 +26,8 @@ List of things to implement following the "release" of the minimum viable produc
|
|||||||
|
|
||||||
## Other
|
## Other
|
||||||
|
|
||||||
- [ ] Create mission authoring tool
|
- [ ] Disable player action during combat phase.
|
||||||
- [ ] Add sound effects
|
- [ ] Add sound effects
|
||||||
- [ ] Tutorial image/mission
|
- [x] Tutorial image/mission
|
||||||
- [ ] Pause menu
|
- [ ] Pause menu
|
||||||
- [x] Score screen when winning/losing map
|
- [x] Score screen when winning/losing map
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<map version="1.10" tiledversion="1.11.0" orientation="orthogonal" renderorder="right-down" width="30" height="17" tilewidth="64" tileheight="64" infinite="0" nextlayerid="2" nextobjectid="1">
|
|
||||||
<tileset firstgid="1" source="Tileset.tsx"/>
|
|
||||||
<layer id="1" name="Tile Layer 1" width="30" height="17">
|
|
||||||
<data encoding="csv">
|
|
||||||
15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
|
|
||||||
15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
|
|
||||||
15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
|
|
||||||
4,4,4,4,4,4,4,4,4,4,4,4,4,5,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
|
|
||||||
18,18,18,18,18,18,18,18,18,18,18,18,18,19,15,15,15,15,15,3,4,4,4,4,4,4,4,4,4,4,
|
|
||||||
32,32,32,32,32,32,32,32,32,32,32,7,18,19,15,15,15,15,15,17,18,18,18,18,18,18,18,18,18,18,
|
|
||||||
15,15,15,15,15,15,15,15,15,15,15,17,18,19,15,15,15,15,15,17,18,6,32,32,32,32,32,32,32,32,
|
|
||||||
15,15,15,15,15,15,15,15,15,15,15,17,18,19,15,15,15,15,15,17,18,19,15,15,15,15,15,15,15,15,
|
|
||||||
15,15,15,15,15,15,15,15,15,15,15,17,18,19,15,15,15,15,15,17,18,19,15,15,15,15,15,15,15,15,
|
|
||||||
15,15,3,4,4,4,4,4,4,4,4,21,18,19,15,15,15,15,15,17,18,19,15,15,15,15,15,15,15,15,
|
|
||||||
15,15,17,18,18,18,18,18,18,18,18,18,18,19,15,15,15,15,15,17,18,19,15,15,15,15,15,15,15,15,
|
|
||||||
15,15,17,18,6,32,32,32,32,32,32,32,32,33,15,15,15,15,15,17,18,19,15,15,15,15,15,15,15,15,
|
|
||||||
15,15,17,18,19,15,15,15,15,15,15,15,15,15,15,15,15,15,15,17,18,19,15,15,15,15,15,15,15,15,
|
|
||||||
15,15,17,18,20,4,4,4,4,4,4,4,4,4,4,4,4,4,4,21,18,19,15,15,15,15,15,15,15,15,
|
|
||||||
15,15,17,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,19,15,15,15,15,15,15,15,15,
|
|
||||||
15,15,31,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,33,15,15,15,15,15,15,15,15,
|
|
||||||
15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15
|
|
||||||
</data>
|
|
||||||
</layer>
|
|
||||||
</map>
|
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
BIN
public/assets/gui/main_background.jpg
Normal file
After Width: | Height: | Size: 112 KiB |
@ -49,5 +49,56 @@
|
|||||||
"frostfire": 0
|
"frostfire": 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "cloaker",
|
||||||
|
"textures": [],
|
||||||
|
"textureArrayLength": 12,
|
||||||
|
"stats": {
|
||||||
|
"health": 12,
|
||||||
|
"speed": 2,
|
||||||
|
"special": null,
|
||||||
|
"resistance": {
|
||||||
|
"physical": 0,
|
||||||
|
"divine": 0,
|
||||||
|
"fire": 0,
|
||||||
|
"ice": 0,
|
||||||
|
"frostfire": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "demon",
|
||||||
|
"textures": [],
|
||||||
|
"textureArrayLength": 8,
|
||||||
|
"stats": {
|
||||||
|
"health": 12,
|
||||||
|
"speed": 2,
|
||||||
|
"special": null,
|
||||||
|
"resistance": {
|
||||||
|
"physical": 0,
|
||||||
|
"divine": 0,
|
||||||
|
"fire": 0,
|
||||||
|
"ice": 0,
|
||||||
|
"frostfire": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "maker",
|
||||||
|
"textures": [],
|
||||||
|
"textureArrayLength": 11,
|
||||||
|
"stats": {
|
||||||
|
"health": 11,
|
||||||
|
"speed": 2,
|
||||||
|
"special": null,
|
||||||
|
"resistance": {
|
||||||
|
"physical": 0,
|
||||||
|
"divine": 0,
|
||||||
|
"fire": 0,
|
||||||
|
"ice": 0,
|
||||||
|
"frostfire": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"name": "Fire Gem",
|
"name": "Fire Gem",
|
||||||
"description": "Forged from molten lava, the Fire Gem imbues your tower's attacks and adds 50% extra fire damage. It can be merged with any gem and is common. This text shouldn't be long.",
|
"description": "Forged from molten lava, the Fire Gem imbues your tower's attacks and adds 50% extra fire damage. It can be merged with any gem and is common.",
|
||||||
"color": "red",
|
"color": "red",
|
||||||
"type": "Fire",
|
"type": "Fire",
|
||||||
"totalLevels": 2,
|
"totalLevels": 2,
|
||||||
@ -12,16 +12,16 @@
|
|||||||
"genericImprovements": [
|
"genericImprovements": [
|
||||||
{
|
{
|
||||||
"damageUp": 2,
|
"damageUp": 2,
|
||||||
"attackSpeedUp": 10,
|
"attackSpeedUp": 0,
|
||||||
"rangeUp": 0.5,
|
"rangeUp": 0,
|
||||||
"timeToLiveUp": 0,
|
"timeToLiveUp": 0,
|
||||||
"pierceUp": 1,
|
"pierceUp": 1,
|
||||||
"gemValueUp": 0
|
"gemValueUp": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"damageUp": 2,
|
"damageUp": 2,
|
||||||
"attackSpeedUp": 10,
|
"attackSpeedUp": 0,
|
||||||
"rangeUp": 0.5,
|
"rangeUp": 0,
|
||||||
"timeToLiveUp": 0,
|
"timeToLiveUp": 0,
|
||||||
"pierceUp": 1,
|
"pierceUp": 1,
|
||||||
"gemValueUp": 10
|
"gemValueUp": 10
|
||||||
@ -58,7 +58,7 @@
|
|||||||
{
|
{
|
||||||
"damageUp": 2,
|
"damageUp": 2,
|
||||||
"attackSpeedUp": 10,
|
"attackSpeedUp": 10,
|
||||||
"rangeUp": 0.5,
|
"rangeUp": 0,
|
||||||
"timeToLiveUp": 0,
|
"timeToLiveUp": 0,
|
||||||
"pierceUp": 1,
|
"pierceUp": 1,
|
||||||
"gemValueUp": 0
|
"gemValueUp": 0
|
||||||
@ -66,7 +66,7 @@
|
|||||||
{
|
{
|
||||||
"damageUp": 2,
|
"damageUp": 2,
|
||||||
"attackSpeedUp": 10,
|
"attackSpeedUp": 10,
|
||||||
"rangeUp": 0.5,
|
"rangeUp": 0,
|
||||||
"timeToLiveUp": 0,
|
"timeToLiveUp": 0,
|
||||||
"pierceUp": 1,
|
"pierceUp": 1,
|
||||||
"gemValueUp": 10
|
"gemValueUp": 10
|
||||||
@ -103,7 +103,7 @@
|
|||||||
{
|
{
|
||||||
"damageUp": 2,
|
"damageUp": 2,
|
||||||
"attackSpeedUp": 10,
|
"attackSpeedUp": 10,
|
||||||
"rangeUp": 0.5,
|
"rangeUp": 0,
|
||||||
"timeToLiveUp": 0,
|
"timeToLiveUp": 0,
|
||||||
"pierceUp": 1,
|
"pierceUp": 1,
|
||||||
"gemValueUp": 0
|
"gemValueUp": 0
|
||||||
@ -163,7 +163,7 @@
|
|||||||
{
|
{
|
||||||
"damageUp": 2,
|
"damageUp": 2,
|
||||||
"attackSpeedUp": 10,
|
"attackSpeedUp": 10,
|
||||||
"rangeUp": 0.5,
|
"rangeUp": 0,
|
||||||
"timeToLiveUp": 0,
|
"timeToLiveUp": 0,
|
||||||
"pierceUp": 1,
|
"pierceUp": 1,
|
||||||
"gemValueUp": 0
|
"gemValueUp": 0
|
||||||
@ -171,7 +171,7 @@
|
|||||||
{
|
{
|
||||||
"damageUp": 2,
|
"damageUp": 2,
|
||||||
"attackSpeedUp": 10,
|
"attackSpeedUp": 10,
|
||||||
"rangeUp": 0.5,
|
"rangeUp": 0,
|
||||||
"timeToLiveUp": 0,
|
"timeToLiveUp": 0,
|
||||||
"pierceUp": 1,
|
"pierceUp": 1,
|
||||||
"gemValueUp": 10
|
"gemValueUp": 10
|
||||||
|
@ -9,11 +9,11 @@
|
|||||||
"description": "The building block of society, nothing more basic exists.",
|
"description": "The building block of society, nothing more basic exists.",
|
||||||
"stats": {
|
"stats": {
|
||||||
"damage": 2,
|
"damage": 2,
|
||||||
"cooldown": 120,
|
"cooldown": 2000,
|
||||||
"gemSlotsAmount": 2,
|
"gemSlotsAmount": 2,
|
||||||
"cost": 100,
|
"cost": 100,
|
||||||
"range": 3,
|
"range": 4,
|
||||||
"timeToLive": 120,
|
"timeToLive": 20,
|
||||||
"pierce": 1
|
"pierce": 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -27,11 +27,11 @@
|
|||||||
"description": "If you feel a little circular.",
|
"description": "If you feel a little circular.",
|
||||||
"stats": {
|
"stats": {
|
||||||
"damage": 2,
|
"damage": 2,
|
||||||
"cooldown": 120,
|
"cooldown": 2000,
|
||||||
"gemSlotsAmount": 3,
|
"gemSlotsAmount": 3,
|
||||||
"cost": 125,
|
"cost": 125,
|
||||||
"range": 2,
|
"range": 2.5,
|
||||||
"timeToLive": 8,
|
"timeToLive": 12,
|
||||||
"pierce": 30
|
"pierce": 30
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
BIN
public/assets/tutorial/tutorial01.jpg
Normal file
After Width: | Height: | Size: 239 KiB |
BIN
public/assets/tutorial/tutorial02.jpg
Normal file
After Width: | Height: | Size: 250 KiB |
BIN
public/assets/tutorial/tutorial03.jpg
Normal file
After Width: | Height: | Size: 109 KiB |
BIN
public/assets/tutorial/tutorial04.jpg
Normal file
After Width: | Height: | Size: 220 KiB |
BIN
public/assets/tutorial/tutorial05.jpg
Normal file
After Width: | Height: | Size: 296 KiB |
@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
|
Before Width: | Height: | Size: 1.5 KiB |
@ -3,6 +3,8 @@ import { CreepDefinition, GemDefinition, MissionDefinition, TowerDefinition } fr
|
|||||||
import { Engine } from './Bastion';
|
import { Engine } from './Bastion';
|
||||||
|
|
||||||
export default class GameAssets {
|
export default class GameAssets {
|
||||||
|
public static MainBackground: PIXI.Texture;
|
||||||
|
|
||||||
public static Frame01Texture: PIXI.Texture;
|
public static Frame01Texture: PIXI.Texture;
|
||||||
public static Frame02Texture: PIXI.Texture;
|
public static Frame02Texture: PIXI.Texture;
|
||||||
public static Frame03Texture: PIXI.Texture;
|
public static Frame03Texture: PIXI.Texture;
|
||||||
@ -26,9 +28,16 @@ export default class GameAssets {
|
|||||||
public static BannerGemsmith: PIXI.Texture;
|
public static BannerGemsmith: PIXI.Texture;
|
||||||
public static EndScreenDialog: PIXI.Texture;
|
public static EndScreenDialog: PIXI.Texture;
|
||||||
|
|
||||||
|
public static Tutorial01: PIXI.Texture;
|
||||||
|
public static Tutorial02: PIXI.Texture;
|
||||||
|
public static Tutorial03: PIXI.Texture;
|
||||||
|
public static Tutorial04: PIXI.Texture;
|
||||||
|
public static Tutorial05: PIXI.Texture;
|
||||||
|
|
||||||
public static PlayIconTexture: PIXI.Texture;
|
public static PlayIconTexture: PIXI.Texture;
|
||||||
public static PauseIconTexture: PIXI.Texture;
|
public static PauseIconTexture: PIXI.Texture;
|
||||||
public static ExclamationIconTexture: PIXI.Texture;
|
public static ExclamationIconTexture: PIXI.Texture;
|
||||||
|
public static FastForwardIconTexture: PIXI.Texture;
|
||||||
public static HomeIconTexture: PIXI.Texture;
|
public static HomeIconTexture: PIXI.Texture;
|
||||||
public static HammerIconTexture: PIXI.Texture;
|
public static HammerIconTexture: PIXI.Texture;
|
||||||
public static XIconTexture: PIXI.Texture;
|
public static XIconTexture: PIXI.Texture;
|
||||||
@ -98,6 +107,14 @@ export default class GameAssets {
|
|||||||
this.Load('./assets/gui/frame_blue.png').then((texture) => (this.BlueBackground = texture)),
|
this.Load('./assets/gui/frame_blue.png').then((texture) => (this.BlueBackground = texture)),
|
||||||
this.Load('./assets/gui/banner_01.png').then((texture) => (this.BannerGemsmith = texture)),
|
this.Load('./assets/gui/banner_01.png').then((texture) => (this.BannerGemsmith = texture)),
|
||||||
this.Load('./assets/gui/note.png').then((texture) => (this.EndScreenDialog = texture)),
|
this.Load('./assets/gui/note.png').then((texture) => (this.EndScreenDialog = texture)),
|
||||||
|
this.Load('./assets/gui/main_background.jpg').then((texture) => (this.MainBackground = texture)),
|
||||||
|
|
||||||
|
this.Load('./assets/tutorial/tutorial01.jpg').then((texture) => (this.Tutorial01 = texture)),
|
||||||
|
this.Load('./assets/tutorial/tutorial02.jpg').then((texture) => (this.Tutorial02 = texture)),
|
||||||
|
this.Load('./assets/tutorial/tutorial03.jpg').then((texture) => (this.Tutorial03 = texture)),
|
||||||
|
this.Load('./assets/tutorial/tutorial04.jpg').then((texture) => (this.Tutorial04 = texture)),
|
||||||
|
this.Load('./assets/tutorial/tutorial05.jpg').then((texture) => (this.Tutorial05 = texture)),
|
||||||
|
|
||||||
this.Load('./assets/gui/heart.png').then((texture) => (this.HealthTexture = texture)),
|
this.Load('./assets/gui/heart.png').then((texture) => (this.HealthTexture = texture)),
|
||||||
this.Load('./assets/gui/money.png').then((texture) => (this.GoldTexture = texture)),
|
this.Load('./assets/gui/money.png').then((texture) => (this.GoldTexture = texture)),
|
||||||
this.Load('./assets/gui/wave.png').then((texture) => (this.WaveTexture = texture)),
|
this.Load('./assets/gui/wave.png').then((texture) => (this.WaveTexture = texture)),
|
||||||
@ -105,7 +122,8 @@ export default class GameAssets {
|
|||||||
this.Load('./assets/gui/title01.png').then((texture) => (this.TitleTexture = texture)),
|
this.Load('./assets/gui/title01.png').then((texture) => (this.TitleTexture = texture)),
|
||||||
this.Load('./assets/gui/icons/play.png').then((texture) => (this.PlayIconTexture = texture)),
|
this.Load('./assets/gui/icons/play.png').then((texture) => (this.PlayIconTexture = texture)),
|
||||||
this.Load('./assets/gui/icons/pause.png').then((texture) => (this.PauseIconTexture = texture)),
|
this.Load('./assets/gui/icons/pause.png').then((texture) => (this.PauseIconTexture = texture)),
|
||||||
this.Load('./assets/gui/icons/exclamation.png').then((texture) => (this.ExclamationIconTexture = texture)),
|
this.Load('./assets/gui/icons/pause.png').then((texture) => (this.PauseIconTexture = texture)),
|
||||||
|
this.Load('./assets/gui/icons/fastforward.png').then((texture) => (this.FastForwardIconTexture = texture)),
|
||||||
this.Load('./assets/gui/icons/home.png').then((texture) => (this.HomeIconTexture = texture)),
|
this.Load('./assets/gui/icons/home.png').then((texture) => (this.HomeIconTexture = texture)),
|
||||||
this.Load('./assets/gui/icons/hammer.png').then((texture) => (this.HammerIconTexture = texture)),
|
this.Load('./assets/gui/icons/hammer.png').then((texture) => (this.HammerIconTexture = texture)),
|
||||||
this.Load('./assets/gui/icons/cross.png').then((texture) => (this.XIconTexture = texture)),
|
this.Load('./assets/gui/icons/cross.png').then((texture) => (this.XIconTexture = texture)),
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import * as PIXI from 'pixi.js';
|
import * as PIXI from 'pixi.js';
|
||||||
import GameObject from './GameObject';
|
|
||||||
import GuiObject from './GuiObject';
|
import GuiObject from './GuiObject';
|
||||||
import Scene from '../scenes/Scene';
|
import Scene from '../scenes/Scene';
|
||||||
import { Grid } from './game/Grid';
|
import { Grid } from './game/Grid';
|
||||||
@ -10,7 +9,6 @@ import { AnimationManager } from './game/AnimationManager';
|
|||||||
import NotificationManager from './game/NotificationManager';
|
import NotificationManager from './game/NotificationManager';
|
||||||
import Gem from './game/Gem';
|
import Gem from './game/Gem';
|
||||||
import GameAssets from './Assets';
|
import GameAssets from './Assets';
|
||||||
import { GemType } from './Definitions';
|
|
||||||
|
|
||||||
export class Engine {
|
export class Engine {
|
||||||
public static app: PIXI.Application;
|
public static app: PIXI.Application;
|
||||||
@ -33,10 +31,10 @@ export class Engine {
|
|||||||
public static TestSuite() {
|
public static TestSuite() {
|
||||||
let params = new URLSearchParams(location.href);
|
let params = new URLSearchParams(location.href);
|
||||||
if (params.entries().next().value[1] != 'game') return;
|
if (params.entries().next().value[1] != 'game') return;
|
||||||
|
|
||||||
Engine.NotificationManager.Notify('Loaded testing suite.', 'danger');
|
Engine.NotificationManager.Notify('Loaded testing suite.', 'danger');
|
||||||
|
let tower = GameAssets.Towers[0];
|
||||||
Engine.TowerManager.ToggleChoosingTowerLocation('RESET');
|
Engine.TowerManager.ToggleChoosingTowerLocation('RESET');
|
||||||
Engine.TowerManager.PlaceTower(GameAssets.Towers[1], 6, 10, GameAssets.Towers[1].behaviour, true);
|
Engine.TowerManager.PlaceTower(tower, 6, 10, tower.behaviour, true);
|
||||||
for (let i = 0; i < 29; i++) {
|
for (let i = 0; i < 29; i++) {
|
||||||
this.GameScene.MissionStats.giveGem(new Gem(i % 4), true);
|
this.GameScene.MissionStats.giveGem(new Gem(i % 4), true);
|
||||||
}
|
}
|
||||||
|
@ -108,6 +108,9 @@ export enum CreepType {
|
|||||||
Basic = 0,
|
Basic = 0,
|
||||||
Quick = 1,
|
Quick = 1,
|
||||||
Tank = 2,
|
Tank = 2,
|
||||||
|
Cloaker = 3,
|
||||||
|
Demon = 4,
|
||||||
|
Maker = 5,
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum GemType {
|
export enum GemType {
|
||||||
|
@ -131,8 +131,8 @@ export default class Creep extends GameObject {
|
|||||||
this.sprite.scale.x *= -1;
|
this.sprite.scale.x *= -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let deltaX = this.speed * elapsedMS * directionX;
|
let deltaX = this.speed * elapsedMS * directionX * Engine.GameScene.gameSpeedMultiplier;
|
||||||
let deltaY = this.speed * elapsedMS * directionY;
|
let deltaY = this.speed * elapsedMS * directionY * Engine.GameScene.gameSpeedMultiplier;
|
||||||
let increaseIndex = false;
|
let increaseIndex = false;
|
||||||
|
|
||||||
if (deltaX > 0 && this.x + deltaX > targetX) {
|
if (deltaX > 0 && this.x + deltaX > targetX) {
|
||||||
|
@ -67,6 +67,7 @@ export class Cell extends GameObject {
|
|||||||
Engine.GameScene.events.on(TowerEvents.TowerSoldEvent, (_, row, col) => {
|
Engine.GameScene.events.on(TowerEvents.TowerSoldEvent, (_, row, col) => {
|
||||||
if (row == this.row && col == this.column) {
|
if (row == this.row && col == this.column) {
|
||||||
this.hasTowerPlaced = false;
|
this.hasTowerPlaced = false;
|
||||||
|
Engine.Grid.rangePreview.clear();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* Handles keyboard events.
|
* Handles keyboard events.
|
||||||
*/
|
*/
|
||||||
class KeyboardManager {
|
export default class KeyboardManager {
|
||||||
private static listeners: ((event: KeyboardEvent) => void)[] = [];
|
private static listeners: ((event: KeyboardEvent) => void)[] = [];
|
||||||
|
|
||||||
public static init() {
|
public static init() {
|
||||||
@ -35,7 +35,7 @@ class KeyboardManager {
|
|||||||
|
|
||||||
private static handleKeyDown(event: KeyboardEvent) {
|
private static handleKeyDown(event: KeyboardEvent) {
|
||||||
if (KeyboardManager.listeners.length > 0) {
|
if (KeyboardManager.listeners.length > 0) {
|
||||||
console.log(`Key down: ${event.key}`);
|
// console.log(`Key down: ${event.key}`);
|
||||||
for (let i = KeyboardManager.listeners.length - 1; i >= 0; i--) {
|
for (let i = KeyboardManager.listeners.length - 1; i >= 0; i--) {
|
||||||
KeyboardManager.listeners[i](event);
|
KeyboardManager.listeners[i](event);
|
||||||
if (event.defaultPrevented) {
|
if (event.defaultPrevented) {
|
||||||
@ -45,5 +45,3 @@ class KeyboardManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default KeyboardManager;
|
|
||||||
|
@ -64,7 +64,7 @@ export default class Projectile extends GameObject {
|
|||||||
if (this.deleteMe) return;
|
if (this.deleteMe) return;
|
||||||
if (this.x > 2000 || this.x < 0 || this.y > 2000 || this.y < 0 || this.pierce <= 0 || this.timeToLive <= 0)
|
if (this.x > 2000 || this.x < 0 || this.y > 2000 || this.y < 0 || this.pierce <= 0 || this.timeToLive <= 0)
|
||||||
return this.destroy();
|
return this.destroy();
|
||||||
this.timeToLive--;
|
this.timeToLive -= Engine.GameScene.gameSpeedMultiplier;
|
||||||
Engine.Grid.creeps.forEach((creep) => {
|
Engine.Grid.creeps.forEach((creep) => {
|
||||||
if (this.pierce <= 0) return;
|
if (this.pierce <= 0) return;
|
||||||
if (creep && creep.container && this.checkCollision(creep)) {
|
if (creep && creep.container && this.checkCollision(creep)) {
|
||||||
@ -77,19 +77,25 @@ export default class Projectile extends GameObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.x += Math.cos(this.angle) * this.speed * elapsedMS;
|
this.x += Math.cos(this.angle) * this.speed * elapsedMS * Engine.GameScene.gameSpeedMultiplier;
|
||||||
this.y += Math.sin(this.angle) * this.speed * elapsedMS;
|
this.y += Math.sin(this.angle) * this.speed * elapsedMS * Engine.GameScene.gameSpeedMultiplier;
|
||||||
|
|
||||||
this.container.x = this.x;
|
this.container.x = this.x;
|
||||||
this.container.y = this.y;
|
this.container.y = this.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
public onCollide(creep) {
|
public onCollide(creep) {
|
||||||
|
/*
|
||||||
|
Note:
|
||||||
|
Right now it is possible for the bullet to 'overshoot' the creep if the bullet speed is too fast and the position is updated so that the
|
||||||
|
new position is beyond the creep (i.e. the bullet is never 'in the creep').
|
||||||
|
This should be fixed so that we calculate the hit if the creep is in a line from the previous position to the new position.
|
||||||
|
*/
|
||||||
Engine.GameScene.events.emit(CreepEvents.TakenDamage, creep.id, this.damage, this.gemResistanceModifications);
|
Engine.GameScene.events.emit(CreepEvents.TakenDamage, creep.id, this.damage, this.gemResistanceModifications);
|
||||||
}
|
}
|
||||||
|
|
||||||
public checkCollision(creep: Creep) {
|
public checkCollision(creep: Creep) {
|
||||||
console.debug(creep);
|
//console.debug(creep);
|
||||||
if (creep == null || creep.container == null || creep.container._position == null) return;
|
if (creep == null || creep.container == null || creep.container._position == null) return;
|
||||||
let mybb = this.copyContainerToBB();
|
let mybb = this.copyContainerToBB();
|
||||||
let otherbb = creep.copyContainerToBB();
|
let otherbb = creep.copyContainerToBB();
|
||||||
|
@ -16,16 +16,18 @@ export function distance(x1, y1, x2, y2) {
|
|||||||
export class Tower extends GameObject {
|
export class Tower extends GameObject {
|
||||||
public row: number;
|
public row: number;
|
||||||
public column: number;
|
public column: number;
|
||||||
|
public setAsSold: boolean = false;
|
||||||
|
public sold: boolean = false;
|
||||||
public definition: TowerDefinition;
|
public definition: TowerDefinition;
|
||||||
public slottedGems: Array<Gem> = [];
|
public slottedGems: Array<Gem> = [];
|
||||||
public damageDealt: number = 0;
|
public damageDealt: number = 0;
|
||||||
public projectiles: Projectile[] = [];
|
public projectiles: Projectile[] = [];
|
||||||
public behaviour: string;
|
public behaviour: string;
|
||||||
public sprite: PIXI.Sprite;
|
public sprite: PIXI.Sprite;
|
||||||
public ticksUntilNextShot: number;
|
public millisecondsUntilNextShot: number;
|
||||||
public graphics: PIXI.Graphics = new PIXI.Graphics();
|
public graphics: PIXI.Graphics = new PIXI.Graphics();
|
||||||
public computedDamageToDeal: number;
|
public computedDamageToDeal: number;
|
||||||
public computedAttackSpeed: number;
|
public computedCooldown: number;
|
||||||
public computedRange: number;
|
public computedRange: number;
|
||||||
public computedTimeToLive: number;
|
public computedTimeToLive: number;
|
||||||
public computedPierce: number;
|
public computedPierce: number;
|
||||||
@ -38,7 +40,7 @@ export class Tower extends GameObject {
|
|||||||
this.column = column;
|
this.column = column;
|
||||||
this.behaviour = behaviour;
|
this.behaviour = behaviour;
|
||||||
this.definition = definition;
|
this.definition = definition;
|
||||||
this.ticksUntilNextShot = 0;
|
this.millisecondsUntilNextShot = 0;
|
||||||
this.parent = Engine.Grid.getCellByRowAndCol(row, column);
|
this.parent = Engine.Grid.getCellByRowAndCol(row, column);
|
||||||
this.sprite = new PIXI.Sprite({
|
this.sprite = new PIXI.Sprite({
|
||||||
texture: texture,
|
texture: texture,
|
||||||
@ -74,6 +76,7 @@ export class Tower extends GameObject {
|
|||||||
}
|
}
|
||||||
public UnslotGem(index) {
|
public UnslotGem(index) {
|
||||||
const gem = this.slottedGems.splice(index, 1)[0];
|
const gem = this.slottedGems.splice(index, 1)[0];
|
||||||
|
if (gem == null || !gem) return console.warn('UnslotGem: Gem is null.');
|
||||||
Engine.GameScene.MissionStats.giveGem(gem, true);
|
Engine.GameScene.MissionStats.giveGem(gem, true);
|
||||||
for (let i = index; i < this.slottedGems.length - 1; i++) {
|
for (let i = index; i < this.slottedGems.length - 1; i++) {
|
||||||
if (this.slottedGems[i] == null) {
|
if (this.slottedGems[i] == null) {
|
||||||
@ -113,14 +116,6 @@ export class Tower extends GameObject {
|
|||||||
}
|
}
|
||||||
combinedTint = color;
|
combinedTint = color;
|
||||||
}
|
}
|
||||||
// this.slottedGems.forEach((gem) => {
|
|
||||||
// let rgb = new PIXI.Color(gem.definition.color).toRgb();
|
|
||||||
// combinedTint =
|
|
||||||
// ((combinedTint & 0xff0000) + (rgb.r << 16)) |
|
|
||||||
// ((combinedTint & 0x00ff00) + (rgb.g << 8)) |
|
|
||||||
// ((combinedTint & 0x0000ff) + rgb.b);
|
|
||||||
// });
|
|
||||||
// combinedTint = new PIXI.Color(this.slottedGems[0].definition.color).
|
|
||||||
let proj = new Projectile(
|
let proj = new Projectile(
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
@ -132,10 +127,20 @@ export class Tower extends GameObject {
|
|||||||
this.computedPierce,
|
this.computedPierce,
|
||||||
this.totalGemResistanceModifications
|
this.totalGemResistanceModifications
|
||||||
);
|
);
|
||||||
|
const time = new Date().toISOString();
|
||||||
|
console.log(`${time} ${this.definition.name} shot at ${angle} degrees`);
|
||||||
this.projectiles.push(proj);
|
this.projectiles.push(proj);
|
||||||
return proj;
|
return proj;
|
||||||
}
|
}
|
||||||
|
public Sell() {
|
||||||
|
this.setAsSold = true;
|
||||||
|
// Selling logic is handled in TowerManager.update()
|
||||||
|
}
|
||||||
public update(elapsedMS: any): void {
|
public update(elapsedMS: any): void {
|
||||||
|
if (this.sold) return;
|
||||||
|
if (this.setAsSold) {
|
||||||
|
this.sold = true;
|
||||||
|
}
|
||||||
if (this.behaviour == TowerBehaviours.BasicTowerBehaviour) BasicTowerBehaviour(this, elapsedMS);
|
if (this.behaviour == TowerBehaviours.BasicTowerBehaviour) BasicTowerBehaviour(this, elapsedMS);
|
||||||
if (this.behaviour == TowerBehaviours.CircleTowerBehaviour) CircleTowerBehaviour(this, elapsedMS);
|
if (this.behaviour == TowerBehaviours.CircleTowerBehaviour) CircleTowerBehaviour(this, elapsedMS);
|
||||||
}
|
}
|
||||||
|
@ -12,11 +12,13 @@ import { Tower } from './Tower';
|
|||||||
*/
|
*/
|
||||||
function projectileCheck(tower: Tower, elapsedMS: number) {
|
function projectileCheck(tower: Tower, elapsedMS: number) {
|
||||||
tower.projectiles.forEach((proj) => {
|
tower.projectiles.forEach((proj) => {
|
||||||
if (proj.deleteMe) {
|
if (proj.deleteMe || tower.sold) {
|
||||||
proj.collidedCreepIDs.forEach(() => {
|
proj.collidedCreepIDs.forEach(() => {
|
||||||
tower.damageDealt += tower.computedDamageToDeal;
|
tower.damageDealt += tower.computedDamageToDeal;
|
||||||
});
|
});
|
||||||
|
proj.collidedCreepIDs = [];
|
||||||
tower.projectiles.splice(tower.projectiles.indexOf(proj), 1);
|
tower.projectiles.splice(tower.projectiles.indexOf(proj), 1);
|
||||||
|
proj.destroy();
|
||||||
proj = null;
|
proj = null;
|
||||||
} else proj.update(elapsedMS);
|
} else proj.update(elapsedMS);
|
||||||
});
|
});
|
||||||
@ -57,7 +59,7 @@ export function computeGemImprovements(tower: Tower) {
|
|||||||
tower.totalGemResistanceModifications.frostfire += gemResMod.frostfire;
|
tower.totalGemResistanceModifications.frostfire += gemResMod.frostfire;
|
||||||
});
|
});
|
||||||
tower.computedDamageToDeal = tower.definition.stats.damage + gemDamage;
|
tower.computedDamageToDeal = tower.definition.stats.damage + gemDamage;
|
||||||
tower.computedAttackSpeed = tower.definition.stats.cooldown - gemAttackSpeedUp;
|
tower.computedCooldown = tower.definition.stats.cooldown - gemAttackSpeedUp;
|
||||||
tower.computedRange = tower.definition.stats.range + gemRangeUp;
|
tower.computedRange = tower.definition.stats.range + gemRangeUp;
|
||||||
tower.computedTimeToLive = tower.definition.stats.timeToLive + gemTimeToLiveUp;
|
tower.computedTimeToLive = tower.definition.stats.timeToLive + gemTimeToLiveUp;
|
||||||
tower.computedPierce = tower.definition.stats.pierce + gemPierceUp;
|
tower.computedPierce = tower.definition.stats.pierce + gemPierceUp;
|
||||||
@ -71,30 +73,32 @@ export function computeGemImprovements(tower: Tower) {
|
|||||||
* @param elapsedMS - The elapsed time in milliseconds since the last update.
|
* @param elapsedMS - The elapsed time in milliseconds since the last update.
|
||||||
*/
|
*/
|
||||||
export function BasicTowerBehaviour(tower: Tower, elapsedMS: number) {
|
export function BasicTowerBehaviour(tower: Tower, elapsedMS: number) {
|
||||||
if (tower.ticksUntilNextShot % 2 == 0) computeGemImprovements(tower);
|
computeGemImprovements(tower);
|
||||||
projectileCheck(tower, elapsedMS);
|
projectileCheck(tower, elapsedMS);
|
||||||
if (tower.ticksUntilNextShot > 0) tower.ticksUntilNextShot--;
|
if (tower.millisecondsUntilNextShot > 0)
|
||||||
|
tower.millisecondsUntilNextShot -= elapsedMS * Engine.GameScene.gameSpeedMultiplier;
|
||||||
let creepsInRange = tower.GetCreepsInRange();
|
let creepsInRange = tower.GetCreepsInRange();
|
||||||
if (creepsInRange.length > 0) {
|
if (creepsInRange.length > 0) {
|
||||||
let focus = creepsInRange[0];
|
let focus = creepsInRange[0];
|
||||||
if (tower.ticksUntilNextShot <= 0) {
|
if (tower.millisecondsUntilNextShot <= 0) {
|
||||||
let x = tower.column * Engine.GridCellSize + Engine.GridCellSize / 2;
|
let x = tower.column * Engine.GridCellSize + Engine.GridCellSize / 2;
|
||||||
let y = tower.row * Engine.GridCellSize + Engine.GridCellSize / 2;
|
let y = tower.row * Engine.GridCellSize + Engine.GridCellSize / 2;
|
||||||
tower.ticksUntilNextShot = tower.computedAttackSpeed;
|
tower.millisecondsUntilNextShot = tower.computedCooldown;
|
||||||
tower.Shoot(calculateAngleToPoint(x, y, focus.x, focus.y));
|
tower.Shoot(calculateAngleToPoint(x, y, focus.x, focus.y));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function CircleTowerBehaviour(tower: Tower, elapsedMS: number) {
|
export function CircleTowerBehaviour(tower: Tower, elapsedMS: number) {
|
||||||
if (tower.ticksUntilNextShot % 2 == 0) computeGemImprovements(tower);
|
computeGemImprovements(tower);
|
||||||
projectileCheck(tower, elapsedMS);
|
projectileCheck(tower, elapsedMS);
|
||||||
if (tower.ticksUntilNextShot > 0) tower.ticksUntilNextShot--;
|
if (tower.millisecondsUntilNextShot > 0)
|
||||||
|
tower.millisecondsUntilNextShot -= elapsedMS * Engine.GameScene.gameSpeedMultiplier;
|
||||||
let creepsInRange = tower.GetCreepsInRange();
|
let creepsInRange = tower.GetCreepsInRange();
|
||||||
if (creepsInRange.length > 0) {
|
if (creepsInRange.length > 0) {
|
||||||
let focus = creepsInRange[0];
|
let focus = creepsInRange[0];
|
||||||
if (tower.ticksUntilNextShot <= 0) {
|
if (tower.millisecondsUntilNextShot <= 0) {
|
||||||
tower.ticksUntilNextShot = tower.computedAttackSpeed;
|
tower.millisecondsUntilNextShot = tower.computedCooldown;
|
||||||
let x = tower.column * Engine.GridCellSize + Engine.GridCellSize / 2;
|
let x = tower.column * Engine.GridCellSize + Engine.GridCellSize / 2;
|
||||||
let y = tower.row * Engine.GridCellSize + Engine.GridCellSize / 2;
|
let y = tower.row * Engine.GridCellSize + Engine.GridCellSize / 2;
|
||||||
tower.Shoot(calculateAngleToPoint(x, y, x, y + 10)); // Up
|
tower.Shoot(calculateAngleToPoint(x, y, x, y + 10)); // Up
|
||||||
|
@ -114,8 +114,17 @@ export default class TowerManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public update(elapsedMS) {
|
public update(elapsedMS) {
|
||||||
this.towers.forEach((twr) => {
|
this.towers.forEach((twr, idx) => {
|
||||||
twr.update(elapsedMS);
|
if (twr.sold) {
|
||||||
|
twr.slottedGems = twr.slottedGems.filter((gem) => gem != null);
|
||||||
|
while (twr.slottedGems.length > 0) {
|
||||||
|
twr.UnslotGem(0);
|
||||||
|
}
|
||||||
|
Engine.GameScene.MissionStats.earnGold(twr.definition.stats.cost);
|
||||||
|
twr.destroy();
|
||||||
|
this.towers.splice(idx, 1);
|
||||||
|
Engine.GameScene.events.emit(TowerEvents.TowerSoldEvent, twr.name, twr.row, twr.column);
|
||||||
|
} else twr.update(elapsedMS);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ export default class WaveManager extends GameObject {
|
|||||||
}
|
}
|
||||||
public update(elapsedMS: number): void {
|
public update(elapsedMS: number): void {
|
||||||
if (this.started == false) return;
|
if (this.started == false) return;
|
||||||
this.ticks += elapsedMS;
|
this.ticks += elapsedMS * Engine.GameScene.gameSpeedMultiplier;
|
||||||
this.creeps.forEach((creep) => {
|
this.creeps.forEach((creep) => {
|
||||||
if (!creep.spawned && creep.tickToSpawnAt <= this.ticks) {
|
if (!creep.spawned && creep.tickToSpawnAt <= this.ticks) {
|
||||||
creep.spawned = true;
|
creep.spawned = true;
|
||||||
|
59
src/classes/gui/GamePausedDialog.ts
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import * as PIXI from 'pixi.js';
|
||||||
|
import ModalDialogBase from './ModalDialog';
|
||||||
|
import Button, { ButtonTexture } from './Button';
|
||||||
|
import { Engine } from '../Bastion';
|
||||||
|
import { MissionPickerScene } from '../../scenes/MissionPicker';
|
||||||
|
import { GameScene } from '../../scenes/Game';
|
||||||
|
import KeyboardManager from '../game/KeyboardManager';
|
||||||
|
|
||||||
|
export default class GamePausedDialog extends ModalDialogBase {
|
||||||
|
private btnMainMenu: Button;
|
||||||
|
private btnRetry: Button;
|
||||||
|
private btnContinue: Button;
|
||||||
|
private _unsubKeypress: () => void;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super([]);
|
||||||
|
this._unsubKeypress = KeyboardManager.onKeyPressed(this.onContinueClick.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
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.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);
|
||||||
|
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
|
private onMainMenuClick(): void {
|
||||||
|
this.close();
|
||||||
|
this._unsubKeypress();
|
||||||
|
Engine.GameScene.UnpauseGame();
|
||||||
|
Engine.GameScene.destroy();
|
||||||
|
Engine.GameMaster.changeScene(new MissionPickerScene());
|
||||||
|
}
|
||||||
|
|
||||||
|
private onRetryClick(): void {
|
||||||
|
const missionName = Engine.GameScene.mission.name;
|
||||||
|
this.close();
|
||||||
|
this._unsubKeypress();
|
||||||
|
Engine.GameScene.UnpauseGame();
|
||||||
|
Engine.GameScene.destroy();
|
||||||
|
Engine.GameMaster.changeScene(new MissionPickerScene());
|
||||||
|
Engine.GameMaster.changeScene(new GameScene(missionName));
|
||||||
|
Engine.NotificationManager.Notify('Retrying mission.', 'green');
|
||||||
|
}
|
||||||
|
|
||||||
|
private onContinueClick(): void {
|
||||||
|
this.close();
|
||||||
|
Engine.GameScene.UnpauseGame();
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,5 @@
|
|||||||
import * as PIXI from 'pixi.js';
|
import * as PIXI from 'pixi.js';
|
||||||
import ModalDialogBase from './ModalDialog';
|
import ModalDialogBase from './ModalDialog';
|
||||||
import GuiObject from '../GuiObject';
|
|
||||||
|
|
||||||
export default class MessageBox extends ModalDialogBase {
|
export default class MessageBox extends ModalDialogBase {
|
||||||
private caption: string;
|
private caption: string;
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import * as PIXI from 'pixi.js';
|
import * as PIXI from 'pixi.js';
|
||||||
import GuiObject from '../GuiObject';
|
import GuiObject from '../GuiObject';
|
||||||
import Assets from '../Assets';
|
|
||||||
import { Engine } from '../Bastion';
|
import { Engine } from '../Bastion';
|
||||||
import GameAssets from '../Assets';
|
import GameAssets from '../Assets';
|
||||||
import Button, { ButtonTexture } from './Button';
|
import Button, { ButtonTexture } from './Button';
|
||||||
@ -46,9 +45,9 @@ export default abstract class ModalDialogBase extends GuiObject {
|
|||||||
const contentBounds = `x: ${Math.round(this.dialogContent.x)}, y: ${Math.round(
|
const contentBounds = `x: ${Math.round(this.dialogContent.x)}, y: ${Math.round(
|
||||||
this.dialogContent.y
|
this.dialogContent.y
|
||||||
)}, width: ${Math.round(this.dialogContent.width)}, height: ${Math.round(this.dialogContent.height)}`;
|
)}, width: ${Math.round(this.dialogContent.width)}, height: ${Math.round(this.dialogContent.height)}`;
|
||||||
console.debug(
|
// console.debug(
|
||||||
`ModalDialogBase.show(dialog: ${dialogBounds}, content: ${contentBounds}, buttons: ${this.buttonCaptions})`
|
// `ModalDialogBase.show(dialog: ${dialogBounds}, content: ${contentBounds}, buttons: ${this.buttonCaptions})`
|
||||||
);
|
// );
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
Engine.app.stage.addChild(this.container);
|
Engine.app.stage.addChild(this.container);
|
||||||
this.onClosed = (button) => {
|
this.onClosed = (button) => {
|
||||||
|
@ -179,9 +179,14 @@ export default class Tooltip extends GuiObject {
|
|||||||
this.gemDescriptionText.alpha = 1;
|
this.gemDescriptionText.alpha = 1;
|
||||||
|
|
||||||
this.titleText.text = `Lv. ${gem.level} ` + gem.definition.name;
|
this.titleText.text = `Lv. ${gem.level} ` + gem.definition.name;
|
||||||
|
let costToLevelUp;
|
||||||
|
if (!gem.isMaxLevel())
|
||||||
|
costToLevelUp = `Costs ${gem.definition.genericImprovements[gem.level].gemValueUp} gold to level up.`;
|
||||||
|
else costToLevelUp = 'Max level.';
|
||||||
this.gemDescriptionText.text =
|
this.gemDescriptionText.text =
|
||||||
`Valued at ${gem.definition.initialGemValue + gem.currentGemImprovement().gemValueUp} gold. ` +
|
`${costToLevelUp} Valued at ${
|
||||||
gem.definition.description;
|
gem.definition.initialGemValue + gem.currentGemImprovement().gemValueUp
|
||||||
|
} gold. ` + gem.definition.description;
|
||||||
}
|
}
|
||||||
public Show(x, y) {
|
public Show(x, y) {
|
||||||
this.container.alpha = 1;
|
this.container.alpha = 1;
|
||||||
|
@ -73,7 +73,7 @@ export class VisualGemSlot extends GuiObject {
|
|||||||
this.container.addChild(this.background);
|
this.container.addChild(this.background);
|
||||||
this.container.addChild(this.iconSprite);
|
this.container.addChild(this.iconSprite);
|
||||||
this.container.addChild(this.frame);
|
this.container.addChild(this.frame);
|
||||||
let txt = gem ? gem.id : '';
|
let txt = gem ? gem.level : '';
|
||||||
let dbgText = new PIXI.Text({
|
let dbgText = new PIXI.Text({
|
||||||
text: txt,
|
text: txt,
|
||||||
zIndex: 11,
|
zIndex: 11,
|
||||||
@ -114,6 +114,7 @@ export default class TowerPanel extends GuiObject {
|
|||||||
public frostFireResDamage: PIXI.Text;
|
public frostFireResDamage: PIXI.Text;
|
||||||
public divineResDamage: PIXI.Text;
|
public divineResDamage: PIXI.Text;
|
||||||
public physicalResDamage: PIXI.Text;
|
public physicalResDamage: PIXI.Text;
|
||||||
|
private sellButton: Button;
|
||||||
|
|
||||||
constructor(bounds: PIXI.Rectangle) {
|
constructor(bounds: PIXI.Rectangle) {
|
||||||
super(false);
|
super(false);
|
||||||
@ -156,6 +157,7 @@ export default class TowerPanel extends GuiObject {
|
|||||||
zIndex: 5,
|
zIndex: 5,
|
||||||
style: new PIXI.TextStyle({
|
style: new PIXI.TextStyle({
|
||||||
fill: 0xffffff,
|
fill: 0xffffff,
|
||||||
|
fontSize: 25,
|
||||||
stroke: {
|
stroke: {
|
||||||
color: 0x000000,
|
color: 0x000000,
|
||||||
width: 2,
|
width: 2,
|
||||||
@ -280,6 +282,14 @@ export default class TowerPanel extends GuiObject {
|
|||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
this.container.addChild(this.physicalResDamage);
|
this.container.addChild(this.physicalResDamage);
|
||||||
|
this.sellButton = new Button(
|
||||||
|
new PIXI.Rectangle(5, this.towerPanel.height - 70, this.towerPanel.width - 115, 60),
|
||||||
|
'Sell',
|
||||||
|
ButtonTexture.Button02,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
this.sellButton.container.removeFromParent();
|
||||||
|
this.container.addChild(this.sellButton.container);
|
||||||
}
|
}
|
||||||
private MakeSlots(tower: Tower) {
|
private MakeSlots(tower: Tower) {
|
||||||
this.vGems.forEach((vGem) => {
|
this.vGems.forEach((vGem) => {
|
||||||
@ -319,7 +329,7 @@ export default class TowerPanel extends GuiObject {
|
|||||||
this.MakeSlots(tower);
|
this.MakeSlots(tower);
|
||||||
this.showingTower = tower;
|
this.showingTower = tower;
|
||||||
Engine.GameScene.sidebar.gemTab.selectingGemTowerObject = tower;
|
Engine.GameScene.sidebar.gemTab.selectingGemTowerObject = tower;
|
||||||
if (tower.container.parent.x < 900) {
|
if (tower.container.parent.x < 1270) {
|
||||||
this.ShowRight();
|
this.ShowRight();
|
||||||
} else {
|
} else {
|
||||||
this.ShowLeft();
|
this.ShowLeft();
|
||||||
@ -331,13 +341,18 @@ export default class TowerPanel extends GuiObject {
|
|||||||
this.damageText.text = 'Deals ' + tower.computedDamageToDeal + ' damage';
|
this.damageText.text = 'Deals ' + tower.computedDamageToDeal + ' damage';
|
||||||
this.totalDamage.text = 'Damage dealt: ' + tower.damageDealt + ' damage';
|
this.totalDamage.text = 'Damage dealt: ' + tower.damageDealt + ' damage';
|
||||||
this.attackSpeedText.x = this.damageText.width + 10;
|
this.attackSpeedText.x = this.damageText.width + 10;
|
||||||
this.attackSpeedText.text = ` every ${Math.floor((tower.computedAttackSpeed / 60) * 100) / 100}s`;
|
this.attackSpeedText.text = ` every ${Math.floor((tower.computedCooldown / 60) * 100) / 100}s`;
|
||||||
|
|
||||||
this.fireResDamage.text = `+${tower.totalGemResistanceModifications.fire * 100}% Fire damage`;
|
this.fireResDamage.text = `+${tower.totalGemResistanceModifications.fire * 100}% Fire damage`;
|
||||||
this.iceResDamage.text = `+${tower.totalGemResistanceModifications.ice * 100}% Ice damage`;
|
this.iceResDamage.text = `+${tower.totalGemResistanceModifications.ice * 100}% Ice damage`;
|
||||||
this.frostFireResDamage.text = `+${tower.totalGemResistanceModifications.frostfire * 100}% FrostFire damage`;
|
this.frostFireResDamage.text = `+${tower.totalGemResistanceModifications.frostfire * 100}% FrostFire damage`;
|
||||||
this.divineResDamage.text = `+${tower.totalGemResistanceModifications.divine * 100}% Divine damage`;
|
this.divineResDamage.text = `+${tower.totalGemResistanceModifications.divine * 100}% Divine damage`;
|
||||||
this.physicalResDamage.text = `+${tower.totalGemResistanceModifications.physical * 100}% Physical damage`;
|
this.physicalResDamage.text = `+${tower.totalGemResistanceModifications.physical * 100}% Physical damage`;
|
||||||
|
this.sellButton.setCaption('Sell for ' + tower.definition.stats.cost + ' gold');
|
||||||
|
this.sellButton.onClick = () => {
|
||||||
|
tower.Sell();
|
||||||
|
this.Hide();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
private ShowLeft() {
|
private ShowLeft() {
|
||||||
this.towerPanel.x = -100;
|
this.towerPanel.x = -100;
|
||||||
|
18
src/main.ts
@ -46,6 +46,7 @@ import { GemType } from './classes/Definitions';
|
|||||||
}
|
}
|
||||||
Engine.latestCommit = await fetch('/latest_commit').then((res) => res.text());
|
Engine.latestCommit = await fetch('/latest_commit').then((res) => res.text());
|
||||||
window.addEventListener('resize', resize);
|
window.addEventListener('resize', resize);
|
||||||
|
|
||||||
resize();
|
resize();
|
||||||
await Assets.LoadAssets();
|
await Assets.LoadAssets();
|
||||||
GameUIConstants.init();
|
GameUIConstants.init();
|
||||||
@ -71,4 +72,21 @@ import { GemType } from './classes/Definitions';
|
|||||||
return 'You are about to leave.';
|
return 'You are about to leave.';
|
||||||
};
|
};
|
||||||
else Engine.TestSuite();
|
else Engine.TestSuite();
|
||||||
|
|
||||||
|
let gamePausedDueToBlur = false;
|
||||||
|
|
||||||
|
window.addEventListener('blur', () => {
|
||||||
|
console.log('blur');
|
||||||
|
if (Engine.GameScene && !Engine.GameScene.isPaused) {
|
||||||
|
Engine.GameScene.PauseGame();
|
||||||
|
gamePausedDueToBlur = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
window.addEventListener('focus', () => {
|
||||||
|
console.log('focus');
|
||||||
|
if (Engine.GameScene && gamePausedDueToBlur && Engine.GameScene.isPaused) {
|
||||||
|
gamePausedDueToBlur = false;
|
||||||
|
Engine.GameScene.UnpauseGame();
|
||||||
|
}
|
||||||
|
});
|
||||||
})();
|
})();
|
||||||
|
@ -18,11 +18,12 @@ import TowerPanel, { VisualGemSlot } from '../classes/gui/TowerPanel';
|
|||||||
import Gem from '../classes/game/Gem';
|
import Gem from '../classes/game/Gem';
|
||||||
import EndGameDialog from '../classes/gui/EndGameDialog';
|
import EndGameDialog from '../classes/gui/EndGameDialog';
|
||||||
import HighScoreDialog, { HighScoreDialogButtons } from '../classes/gui/HighScoreDialog';
|
import HighScoreDialog, { HighScoreDialogButtons } from '../classes/gui/HighScoreDialog';
|
||||||
|
import GamePausedDialog from '../classes/gui/GamePausedDialog';
|
||||||
|
|
||||||
enum RoundMode {
|
enum RoundMode {
|
||||||
Purchase = 0,
|
Purchase = 0,
|
||||||
Combat = 1,
|
Combat = 1,
|
||||||
OfferingGems = 2,
|
Misc = 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
export class GameScene extends Scene {
|
export class GameScene extends Scene {
|
||||||
@ -36,6 +37,10 @@ export class GameScene extends Scene {
|
|||||||
public sidebar: Sidebar;
|
public sidebar: Sidebar;
|
||||||
public tooltip: Tooltip;
|
public tooltip: Tooltip;
|
||||||
public towerPanel: TowerPanel;
|
public towerPanel: TowerPanel;
|
||||||
|
public isPaused: boolean = false;
|
||||||
|
public gameSpeedMultiplier: number = 1;
|
||||||
|
|
||||||
|
private pauseButton: Button;
|
||||||
private visualGems: VisualGemSlot[] = [];
|
private visualGems: VisualGemSlot[] = [];
|
||||||
private currentRound: number = 0;
|
private currentRound: number = 0;
|
||||||
private isWaveManagerFinished: boolean = false;
|
private isWaveManagerFinished: boolean = false;
|
||||||
@ -47,10 +52,12 @@ export class GameScene extends Scene {
|
|||||||
y: 0,
|
y: 0,
|
||||||
zIndex: 120,
|
zIndex: 120,
|
||||||
});
|
});
|
||||||
|
private windowTitle: string;
|
||||||
|
|
||||||
constructor(name: string) {
|
constructor(name: string) {
|
||||||
super();
|
super();
|
||||||
Engine.GameScene = this;
|
Engine.GameScene = this;
|
||||||
|
this.windowTitle = document.title;
|
||||||
GameAssets.Missions.forEach((mission, index) => {
|
GameAssets.Missions.forEach((mission, index) => {
|
||||||
if (mission.name == name) {
|
if (mission.name == name) {
|
||||||
this.mission = mission;
|
this.mission = mission;
|
||||||
@ -101,15 +108,21 @@ export class GameScene extends Scene {
|
|||||||
this.changeRoundButton.CustomButtonLogic();
|
this.changeRoundButton.CustomButtonLogic();
|
||||||
this.changeRoundButton.onClick = () => {
|
this.changeRoundButton.onClick = () => {
|
||||||
if (this.playerWon) return this.ReturnToMain();
|
if (this.playerWon) return this.ReturnToMain();
|
||||||
if (this.roundMode == RoundMode.Combat)
|
if (this.roundMode == RoundMode.Combat) {
|
||||||
return Engine.NotificationManager.Notify('Wave is already in progress.', 'warn');
|
if (this.gameSpeedMultiplier !== 1) {
|
||||||
|
this.UpdateGameSpeedMultiplier(1);
|
||||||
|
} else {
|
||||||
|
this.UpdateGameSpeedMultiplier(2);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (this.isGameOver) return Engine.NotificationManager.Notify('No more waves.', 'danger');
|
if (this.isGameOver) return Engine.NotificationManager.Notify('No more waves.', 'danger');
|
||||||
if (this.roundMode == RoundMode.OfferingGems) return;
|
if (this.roundMode == RoundMode.Misc) return;
|
||||||
this.setRoundMode(RoundMode.Combat);
|
this.setRoundMode(RoundMode.Combat);
|
||||||
this.changeRoundButton.buttonIcon.texture = GameAssets.ExclamationIconTexture;
|
this.changeRoundButton.buttonIcon.texture = GameAssets.FastForwardIconTexture;
|
||||||
this.events.emit(WaveManagerEvents.NewWave, `${this.currentRound + 1}`);
|
this.events.emit(WaveManagerEvents.NewWave, `${this.currentRound + 1}`);
|
||||||
};
|
};
|
||||||
this.MissionStats = new MissionStats(100, 200);
|
this.MissionStats = new MissionStats(125, 450);
|
||||||
this.events.on(GemEvents.TowerPanelSelectGem, (gem, index, tower) => {
|
this.events.on(GemEvents.TowerPanelSelectGem, (gem, index, tower) => {
|
||||||
if (gem == null) {
|
if (gem == null) {
|
||||||
if (!this.MissionStats.checkIfPlayerHasAnyGems())
|
if (!this.MissionStats.checkIfPlayerHasAnyGems())
|
||||||
@ -120,6 +133,30 @@ export class GameScene extends Scene {
|
|||||||
}
|
}
|
||||||
this.sidebar.gemTab.TowerPanelSelectingGem(gem, index, tower);
|
this.sidebar.gemTab.TowerPanelSelectingGem(gem, index, tower);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.pauseButton = new Button(new PIXI.Rectangle(5, 5, 120, 80), '', ButtonTexture.Button01, true);
|
||||||
|
this.pauseButton.container.removeFromParent();
|
||||||
|
this.stage.addChild(this.pauseButton.container);
|
||||||
|
this.pauseButton.CustomButtonLogic = () => {
|
||||||
|
this.pauseButton.buttonIcon = new PIXI.Sprite({
|
||||||
|
texture: GameAssets.PauseIconTexture,
|
||||||
|
x: this.pauseButton.container.width / 2,
|
||||||
|
y: this.pauseButton.container.height / 2,
|
||||||
|
scale: 0.2,
|
||||||
|
});
|
||||||
|
this.pauseButton.buttonIcon.anchor.set(0.5, 0.5);
|
||||||
|
this.pauseButton.container.addChild(this.pauseButton.buttonIcon);
|
||||||
|
};
|
||||||
|
this.pauseButton.CustomButtonLogic();
|
||||||
|
this.pauseButton.onClick = () => {
|
||||||
|
if (this.isPaused) {
|
||||||
|
this.UnpauseGame();
|
||||||
|
} else {
|
||||||
|
this.ShowPauseDialog();
|
||||||
|
this.PauseGame();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
this.ticker = new PIXI.Ticker();
|
this.ticker = new PIXI.Ticker();
|
||||||
this.ticker.maxFPS = 60;
|
this.ticker.maxFPS = 60;
|
||||||
this.ticker.minFPS = 30;
|
this.ticker.minFPS = 30;
|
||||||
@ -130,10 +167,10 @@ export class GameScene extends Scene {
|
|||||||
|
|
||||||
this.ticker.add(() => {
|
this.ticker.add(() => {
|
||||||
if (this.update) this.update(this.ticker.elapsedMS);
|
if (this.update) this.update(this.ticker.elapsedMS);
|
||||||
|
// if (this.isFastForwarded) this.update(this.ticker.elapsedMS);
|
||||||
});
|
});
|
||||||
this.ticker.start();
|
this.ticker.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public update(elapsedMS) {
|
public update(elapsedMS) {
|
||||||
if (this.isGameOver) {
|
if (this.isGameOver) {
|
||||||
if (this.destroyTicker) {
|
if (this.destroyTicker) {
|
||||||
@ -183,7 +220,7 @@ export class GameScene extends Scene {
|
|||||||
Engine.Grid.gridInteractionEnabled = false;
|
Engine.Grid.gridInteractionEnabled = false;
|
||||||
Engine.GameScene.sidebar.towerTab.resetTint();
|
Engine.GameScene.sidebar.towerTab.resetTint();
|
||||||
Engine.TowerManager.ResetChooseTower();
|
Engine.TowerManager.ResetChooseTower();
|
||||||
this.setRoundMode(RoundMode.OfferingGems);
|
this.setRoundMode(RoundMode.Misc);
|
||||||
let gemsToOffer = this.mission.rounds[this.currentRound].offeredGems;
|
let gemsToOffer = this.mission.rounds[this.currentRound].offeredGems;
|
||||||
this.DarkenScreen();
|
this.DarkenScreen();
|
||||||
this.offerGemsSprite = new PIXI.NineSliceSprite({
|
this.offerGemsSprite = new PIXI.NineSliceSprite({
|
||||||
@ -245,6 +282,21 @@ export class GameScene extends Scene {
|
|||||||
this.setRoundMode(RoundMode.Purchase);
|
this.setRoundMode(RoundMode.Purchase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PauseGame() {
|
||||||
|
this.isPaused = true;
|
||||||
|
this.ticker.stop();
|
||||||
|
document.title = '[PAUSED] ' + this.windowTitle;
|
||||||
|
}
|
||||||
|
public UnpauseGame() {
|
||||||
|
this.isPaused = false;
|
||||||
|
this.ticker.start();
|
||||||
|
document.title = this.windowTitle;
|
||||||
|
}
|
||||||
|
public ShowPauseDialog() {
|
||||||
|
const gamePausedDialog = new GamePausedDialog();
|
||||||
|
gamePausedDialog.show();
|
||||||
|
}
|
||||||
|
|
||||||
private async ShowEndgameDialog(lost) {
|
private async ShowEndgameDialog(lost) {
|
||||||
const endGameDialog = new EndGameDialog(this.mission.name, this.MissionStats, lost);
|
const endGameDialog = new EndGameDialog(this.mission.name, this.MissionStats, lost);
|
||||||
await endGameDialog.show();
|
await endGameDialog.show();
|
||||||
@ -292,4 +344,10 @@ export class GameScene extends Scene {
|
|||||||
private ReturnToMain() {
|
private ReturnToMain() {
|
||||||
Engine.GameMaster.changeScene(new MissionPickerScene());
|
Engine.GameMaster.changeScene(new MissionPickerScene());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private UpdateGameSpeedMultiplier(newMultiplier: number) {
|
||||||
|
this.gameSpeedMultiplier = newMultiplier;
|
||||||
|
if (newMultiplier === 1) Engine.NotificationManager.Notify('Regular speed.', 'info');
|
||||||
|
else Engine.NotificationManager.Notify('Fast forward activated.', 'info');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
67
src/scenes/HowToPlay.ts
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import GameAssets from '../classes/Assets';
|
||||||
|
import Assets from '../classes/Assets';
|
||||||
|
import { Engine } from '../classes/Bastion';
|
||||||
|
import Button, { ButtonTexture } from '../classes/gui/Button';
|
||||||
|
import { GameScene } from './Game';
|
||||||
|
import { MainScene } from './Main';
|
||||||
|
import Scene from './Scene';
|
||||||
|
import * as PIXI from 'pixi.js';
|
||||||
|
|
||||||
|
export class HowToPlay extends Scene {
|
||||||
|
public currentImg = 1;
|
||||||
|
public sprite;
|
||||||
|
public init() {
|
||||||
|
let sprites = [
|
||||||
|
null,
|
||||||
|
GameAssets.Tutorial01,
|
||||||
|
GameAssets.Tutorial02,
|
||||||
|
GameAssets.Tutorial03,
|
||||||
|
GameAssets.Tutorial04,
|
||||||
|
GameAssets.Tutorial05,
|
||||||
|
];
|
||||||
|
this.sprite = new PIXI.Sprite({
|
||||||
|
texture: GameAssets.Tutorial01,
|
||||||
|
scale: 0.6,
|
||||||
|
x: 250,
|
||||||
|
y: 150,
|
||||||
|
});
|
||||||
|
this.stage.addChild(this.sprite);
|
||||||
|
let leftButton = new Button(
|
||||||
|
new PIXI.Rectangle(250, this.sprite.height + 160, 120, 60),
|
||||||
|
'Back',
|
||||||
|
ButtonTexture.Button01
|
||||||
|
);
|
||||||
|
leftButton.container.alpha = 0;
|
||||||
|
leftButton.onClick = () => {
|
||||||
|
if (leftButton.container.alpha == 0 || this.currentImg == 1) return;
|
||||||
|
this.currentImg--;
|
||||||
|
if (this.currentImg == 3) this.sprite.scale = 1.1;
|
||||||
|
else this.sprite.scale = 0.6;
|
||||||
|
this.sprite.texture = sprites[this.currentImg];
|
||||||
|
if (this.currentImg == 1) leftButton.container.alpha = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
let right = new Button(
|
||||||
|
new PIXI.Rectangle(this.sprite.width + 130, this.sprite.height + 160, 120, 60),
|
||||||
|
'Next',
|
||||||
|
ButtonTexture.Button01
|
||||||
|
);
|
||||||
|
right.onClick = () => {
|
||||||
|
if (right.container.alpha == 0) return;
|
||||||
|
this.currentImg++;
|
||||||
|
if (this.currentImg == 3) this.sprite.scale = 1.1;
|
||||||
|
else this.sprite.scale = 0.6;
|
||||||
|
if (this.currentImg != 1) leftButton.container.alpha = 1;
|
||||||
|
this.sprite.texture = sprites[this.currentImg];
|
||||||
|
if (this.currentImg == 5) right.container.alpha = 0;
|
||||||
|
};
|
||||||
|
const button = new Button(
|
||||||
|
new PIXI.Rectangle(this.sprite.width - 540, this.sprite.height + 160, 200, 60),
|
||||||
|
'Main menu',
|
||||||
|
ButtonTexture.Button01
|
||||||
|
);
|
||||||
|
button.onClick = (e) => {
|
||||||
|
Engine.GameMaster.changeScene(new MainScene());
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -1,66 +1,59 @@
|
|||||||
|
import GameAssets from '../classes/Assets';
|
||||||
import { Engine } from '../classes/Bastion';
|
import { Engine } from '../classes/Bastion';
|
||||||
import { FadeInOut, Tween } from '../classes/game/AnimationManager';
|
import { FadeInOut, Tween } from '../classes/game/AnimationManager';
|
||||||
import Button, { ButtonTexture } from '../classes/gui/Button';
|
import Button, { ButtonTexture } from '../classes/gui/Button';
|
||||||
|
import { HowToPlay } from './HowToPlay';
|
||||||
import { MissionPickerScene } from './MissionPicker';
|
import { MissionPickerScene } from './MissionPicker';
|
||||||
import Scene from './Scene';
|
import Scene from './Scene';
|
||||||
import * as PIXI from 'pixi.js';
|
import * as PIXI from 'pixi.js';
|
||||||
|
import { SettingsScene } from './Settings';
|
||||||
|
|
||||||
export class MainScene extends Scene {
|
export class MainScene extends Scene {
|
||||||
public init() {
|
public init() {
|
||||||
|
// Background
|
||||||
|
this.addMainBackground();
|
||||||
|
|
||||||
const NewGameButton = {
|
const NewGameButton = {
|
||||||
caption: 'New Game',
|
caption: 'New Game',
|
||||||
rect: new PIXI.Rectangle(
|
rect: new PIXI.Rectangle(Engine.app.canvas.width / 2 - 300 / 2, 400 + 0 * 70, 300, 60),
|
||||||
Engine.app.canvas.width / 2 - 300 / 2,
|
|
||||||
Engine.app.canvas.height / 5 + 3 * 80,
|
texture: ButtonTexture.Button01,
|
||||||
300,
|
};
|
||||||
60
|
const TutorialButton = {
|
||||||
),
|
caption: 'How to play',
|
||||||
texture: ButtonTexture.Button02,
|
rect: new PIXI.Rectangle(Engine.app.canvas.width / 2 - 300 / 2, 400 + 1 * 70, 300, 60),
|
||||||
|
texture: ButtonTexture.Button01,
|
||||||
};
|
};
|
||||||
|
|
||||||
const SettingsButton = {
|
const SettingsButton = {
|
||||||
caption: 'Settings',
|
caption: 'Settings',
|
||||||
rect: new PIXI.Rectangle(
|
rect: new PIXI.Rectangle(Engine.app.canvas.width / 2 - 300 / 2, 400 + 2 * 70, 300, 60),
|
||||||
Engine.app.canvas.width / 2 - 300 / 2,
|
texture: ButtonTexture.Button01,
|
||||||
Engine.app.canvas.height / 5 + 4 * 80,
|
|
||||||
300,
|
|
||||||
60
|
|
||||||
),
|
|
||||||
texture: ButtonTexture.Button02,
|
|
||||||
};
|
};
|
||||||
let text = new PIXI.Text({
|
|
||||||
x: Engine.app.canvas.width / 2 - 300 / 2,
|
|
||||||
y: Engine.app.canvas.height / 5 + 1 * 80,
|
|
||||||
text: 'BASTION',
|
|
||||||
style: {
|
|
||||||
fill: 0xffaa00,
|
|
||||||
fontFamily: 'Aclonica',
|
|
||||||
fontSize: 100,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
text.x = text.x - text.width / 5;
|
|
||||||
Engine.GameMaster.currentScene.stage.addChild(text);
|
|
||||||
let text2 = new PIXI.Text({
|
let text2 = new PIXI.Text({
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
text: 'Latest commit: ' + Engine.latestCommit,
|
text: 'Latest commit: ' + Engine.latestCommit,
|
||||||
style: {
|
style: {
|
||||||
fill: 0x000000,
|
fill: 0xffffff,
|
||||||
fontSize: 10,
|
fontSize: 10,
|
||||||
fontWeight: 'bold',
|
fontWeight: 'bold',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
Engine.GameMaster.currentScene.stage.addChild(text2);
|
this.stage.addChild(text2);
|
||||||
const button01 = new Button(NewGameButton.rect, NewGameButton.caption, NewGameButton.texture, true);
|
const button01 = new Button(NewGameButton.rect, NewGameButton.caption, NewGameButton.texture, true);
|
||||||
button01.onClick = (e) => {
|
button01.onClick = (e) => {
|
||||||
Engine.GameMaster.currentScene.stage.removeChild(text);
|
|
||||||
Engine.GameMaster.currentScene.stage.removeChild(text2);
|
|
||||||
Engine.GameMaster.changeScene(new MissionPickerScene());
|
Engine.GameMaster.changeScene(new MissionPickerScene());
|
||||||
};
|
};
|
||||||
|
|
||||||
let b2 = new Button(SettingsButton.rect, SettingsButton.caption, SettingsButton.texture, true);
|
// let b2 = new Button(SettingsButton.rect, SettingsButton.caption, SettingsButton.texture, true);
|
||||||
b2.onClick = (e) => {
|
// b2.onClick = (e) => {
|
||||||
Engine.NotificationManager.Notify('Not finished.', 'info');
|
// Engine.GameMaster.changeScene(new SettingsScene());
|
||||||
|
// };
|
||||||
|
let b3 = new Button(TutorialButton.rect, TutorialButton.caption, TutorialButton.texture, true);
|
||||||
|
b3.onClick = (e) => {
|
||||||
|
Engine.GameMaster.changeScene(new HowToPlay());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,18 +8,14 @@ import * as PIXI from 'pixi.js';
|
|||||||
|
|
||||||
export class MissionPickerScene extends Scene {
|
export class MissionPickerScene extends Scene {
|
||||||
public init() {
|
public init() {
|
||||||
const button = new Button(new PIXI.Rectangle(0, 0, 300, 60), 'Back to main', ButtonTexture.Button01);
|
this.addMainBackground();
|
||||||
|
const button = new Button(new PIXI.Rectangle(10, 10, 300, 60), 'Back to main', ButtonTexture.Button01);
|
||||||
button.onClick = (e) => {
|
button.onClick = (e) => {
|
||||||
Engine.GameMaster.changeScene(new MainScene());
|
Engine.GameMaster.changeScene(new MainScene());
|
||||||
};
|
};
|
||||||
Assets.Missions.forEach((mission, index) => {
|
Assets.Missions.forEach((mission, index) => {
|
||||||
const button = new Button(
|
const button = new Button(
|
||||||
new PIXI.Rectangle(
|
new PIXI.Rectangle(Engine.app.canvas.width / 2 - 300 / 2, 400 + index * 70, 300, 60),
|
||||||
Engine.app.canvas.width / 2 - 300 / 2,
|
|
||||||
Engine.app.canvas.height / 5 + index * 80,
|
|
||||||
300,
|
|
||||||
60
|
|
||||||
),
|
|
||||||
mission.name,
|
mission.name,
|
||||||
ButtonTexture.Button01
|
ButtonTexture.Button01
|
||||||
);
|
);
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import GameAssets from '../classes/Assets';
|
||||||
import { Engine } from '../classes/Bastion';
|
import { Engine } from '../classes/Bastion';
|
||||||
import GuiObject from '../classes/GuiObject';
|
import GuiObject from '../classes/GuiObject';
|
||||||
import * as PIXI from 'pixi.js';
|
import * as PIXI from 'pixi.js';
|
||||||
@ -18,6 +19,14 @@ export default class Scene {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public addMainBackground() {
|
||||||
|
// Background
|
||||||
|
const sprite = new PIXI.Sprite(GameAssets.MainBackground);
|
||||||
|
sprite.width = Engine.app.canvas.width;
|
||||||
|
sprite.height = Engine.app.canvas.height;
|
||||||
|
this.stage.addChild(sprite);
|
||||||
|
}
|
||||||
|
|
||||||
public get events(): PIXI.EventEmitter {
|
public get events(): PIXI.EventEmitter {
|
||||||
return this._events;
|
return this._events;
|
||||||
}
|
}
|
||||||
|
17
src/scenes/Settings.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import Assets from '../classes/Assets';
|
||||||
|
import { Engine } from '../classes/Bastion';
|
||||||
|
import Button, { ButtonTexture } from '../classes/gui/Button';
|
||||||
|
import { GameScene } from './Game';
|
||||||
|
import { MainScene } from './Main';
|
||||||
|
import Scene from './Scene';
|
||||||
|
import * as PIXI from 'pixi.js';
|
||||||
|
|
||||||
|
export class SettingsScene extends Scene {
|
||||||
|
public init() {
|
||||||
|
this.addMainBackground();
|
||||||
|
const button = new Button(new PIXI.Rectangle(10, 10, 300, 60), 'Back to main', ButtonTexture.Button01);
|
||||||
|
button.onClick = (e) => {
|
||||||
|
Engine.GameMaster.changeScene(new MainScene());
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|