improvement

This commit is contained in:
Koneko 2025-02-10 20:06:18 +01:00 committed by GitHub
commit 5b18dd601a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
38 changed files with 491 additions and 141 deletions

View File

@ -12,3 +12,7 @@ The [design document](/docs/design.md) contains the starting idea which was init
## Todos
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
View 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`

View File

@ -17,6 +17,7 @@ List of things to implement following the "release" of the minimum viable produc
- [x] Tower info on click
- [x] Animate projectiles
- [x] Better mouseover tracking when placing tower and showing radius
- [x] Sell tower button
## Gems
@ -25,8 +26,8 @@ List of things to implement following the "release" of the minimum viable produc
## Other
- [ ] Create mission authoring tool
- [ ] Disable player action during combat phase.
- [ ] Add sound effects
- [ ] Tutorial image/mission
- [x] Tutorial image/mission
- [ ] Pause menu
- [x] Score screen when winning/losing map

View File

@ -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>

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

View File

@ -49,5 +49,56 @@
"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
}
}
}
]

View File

@ -1,7 +1,7 @@
[
{
"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",
"type": "Fire",
"totalLevels": 2,
@ -12,16 +12,16 @@
"genericImprovements": [
{
"damageUp": 2,
"attackSpeedUp": 10,
"rangeUp": 0.5,
"attackSpeedUp": 0,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 1,
"gemValueUp": 0
},
{
"damageUp": 2,
"attackSpeedUp": 10,
"rangeUp": 0.5,
"attackSpeedUp": 0,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 1,
"gemValueUp": 10
@ -58,7 +58,7 @@
{
"damageUp": 2,
"attackSpeedUp": 10,
"rangeUp": 0.5,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 1,
"gemValueUp": 0
@ -66,7 +66,7 @@
{
"damageUp": 2,
"attackSpeedUp": 10,
"rangeUp": 0.5,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 1,
"gemValueUp": 10
@ -103,7 +103,7 @@
{
"damageUp": 2,
"attackSpeedUp": 10,
"rangeUp": 0.5,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 1,
"gemValueUp": 0
@ -163,7 +163,7 @@
{
"damageUp": 2,
"attackSpeedUp": 10,
"rangeUp": 0.5,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 1,
"gemValueUp": 0
@ -171,7 +171,7 @@
{
"damageUp": 2,
"attackSpeedUp": 10,
"rangeUp": 0.5,
"rangeUp": 0,
"timeToLiveUp": 0,
"pierceUp": 1,
"gemValueUp": 10

View File

@ -9,11 +9,11 @@
"description": "The building block of society, nothing more basic exists.",
"stats": {
"damage": 2,
"cooldown": 120,
"cooldown": 2000,
"gemSlotsAmount": 2,
"cost": 100,
"range": 3,
"timeToLive": 120,
"range": 4,
"timeToLive": 20,
"pierce": 1
}
},
@ -27,11 +27,11 @@
"description": "If you feel a little circular.",
"stats": {
"damage": 2,
"cooldown": 120,
"cooldown": 2000,
"gemSlotsAmount": 3,
"cost": 125,
"range": 2,
"timeToLive": 8,
"range": 2.5,
"timeToLive": 12,
"pierce": 30
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 296 KiB

View File

@ -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

View File

@ -3,6 +3,8 @@ import { CreepDefinition, GemDefinition, MissionDefinition, TowerDefinition } fr
import { Engine } from './Bastion';
export default class GameAssets {
public static MainBackground: PIXI.Texture;
public static Frame01Texture: PIXI.Texture;
public static Frame02Texture: PIXI.Texture;
public static Frame03Texture: PIXI.Texture;
@ -26,9 +28,16 @@ export default class GameAssets {
public static BannerGemsmith: 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 PauseIconTexture: PIXI.Texture;
public static ExclamationIconTexture: PIXI.Texture;
public static FastForwardIconTexture: PIXI.Texture;
public static HomeIconTexture: PIXI.Texture;
public static HammerIconTexture: 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/banner_01.png').then((texture) => (this.BannerGemsmith = 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/money.png').then((texture) => (this.GoldTexture = 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/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/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/hammer.png').then((texture) => (this.HammerIconTexture = texture)),
this.Load('./assets/gui/icons/cross.png').then((texture) => (this.XIconTexture = texture)),

View File

@ -1,5 +1,4 @@
import * as PIXI from 'pixi.js';
import GameObject from './GameObject';
import GuiObject from './GuiObject';
import Scene from '../scenes/Scene';
import { Grid } from './game/Grid';
@ -10,7 +9,6 @@ import { AnimationManager } from './game/AnimationManager';
import NotificationManager from './game/NotificationManager';
import Gem from './game/Gem';
import GameAssets from './Assets';
import { GemType } from './Definitions';
export class Engine {
public static app: PIXI.Application;
@ -33,10 +31,10 @@ export class Engine {
public static TestSuite() {
let params = new URLSearchParams(location.href);
if (params.entries().next().value[1] != 'game') return;
Engine.NotificationManager.Notify('Loaded testing suite.', 'danger');
let tower = GameAssets.Towers[0];
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++) {
this.GameScene.MissionStats.giveGem(new Gem(i % 4), true);
}

View File

@ -108,6 +108,9 @@ export enum CreepType {
Basic = 0,
Quick = 1,
Tank = 2,
Cloaker = 3,
Demon = 4,
Maker = 5,
}
export enum GemType {

View File

@ -131,8 +131,8 @@ export default class Creep extends GameObject {
this.sprite.scale.x *= -1;
}
}
let deltaX = this.speed * elapsedMS * directionX;
let deltaY = this.speed * elapsedMS * directionY;
let deltaX = this.speed * elapsedMS * directionX * Engine.GameScene.gameSpeedMultiplier;
let deltaY = this.speed * elapsedMS * directionY * Engine.GameScene.gameSpeedMultiplier;
let increaseIndex = false;
if (deltaX > 0 && this.x + deltaX > targetX) {

View File

@ -67,6 +67,7 @@ export class Cell extends GameObject {
Engine.GameScene.events.on(TowerEvents.TowerSoldEvent, (_, row, col) => {
if (row == this.row && col == this.column) {
this.hasTowerPlaced = false;
Engine.Grid.rangePreview.clear();
}
});

View File

@ -1,7 +1,7 @@
/**
* Handles keyboard events.
*/
class KeyboardManager {
export default class KeyboardManager {
private static listeners: ((event: KeyboardEvent) => void)[] = [];
public static init() {
@ -35,7 +35,7 @@ class KeyboardManager {
private static handleKeyDown(event: KeyboardEvent) {
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--) {
KeyboardManager.listeners[i](event);
if (event.defaultPrevented) {
@ -45,5 +45,3 @@ class KeyboardManager {
}
}
}
export default KeyboardManager;

View File

@ -64,7 +64,7 @@ export default class Projectile extends GameObject {
if (this.deleteMe) return;
if (this.x > 2000 || this.x < 0 || this.y > 2000 || this.y < 0 || this.pierce <= 0 || this.timeToLive <= 0)
return this.destroy();
this.timeToLive--;
this.timeToLive -= Engine.GameScene.gameSpeedMultiplier;
Engine.Grid.creeps.forEach((creep) => {
if (this.pierce <= 0) return;
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.y += Math.sin(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 * Engine.GameScene.gameSpeedMultiplier;
this.container.x = this.x;
this.container.y = this.y;
}
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);
}
public checkCollision(creep: Creep) {
console.debug(creep);
//console.debug(creep);
if (creep == null || creep.container == null || creep.container._position == null) return;
let mybb = this.copyContainerToBB();
let otherbb = creep.copyContainerToBB();

View File

@ -16,16 +16,18 @@ export function distance(x1, y1, x2, y2) {
export class Tower extends GameObject {
public row: number;
public column: number;
public setAsSold: boolean = false;
public sold: boolean = false;
public definition: TowerDefinition;
public slottedGems: Array<Gem> = [];
public damageDealt: number = 0;
public projectiles: Projectile[] = [];
public behaviour: string;
public sprite: PIXI.Sprite;
public ticksUntilNextShot: number;
public millisecondsUntilNextShot: number;
public graphics: PIXI.Graphics = new PIXI.Graphics();
public computedDamageToDeal: number;
public computedAttackSpeed: number;
public computedCooldown: number;
public computedRange: number;
public computedTimeToLive: number;
public computedPierce: number;
@ -38,7 +40,7 @@ export class Tower extends GameObject {
this.column = column;
this.behaviour = behaviour;
this.definition = definition;
this.ticksUntilNextShot = 0;
this.millisecondsUntilNextShot = 0;
this.parent = Engine.Grid.getCellByRowAndCol(row, column);
this.sprite = new PIXI.Sprite({
texture: texture,
@ -74,6 +76,7 @@ export class Tower extends GameObject {
}
public UnslotGem(index) {
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);
for (let i = index; i < this.slottedGems.length - 1; i++) {
if (this.slottedGems[i] == null) {
@ -113,14 +116,6 @@ export class Tower extends GameObject {
}
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(
x,
y,
@ -132,10 +127,20 @@ export class Tower extends GameObject {
this.computedPierce,
this.totalGemResistanceModifications
);
const time = new Date().toISOString();
console.log(`${time} ${this.definition.name} shot at ${angle} degrees`);
this.projectiles.push(proj);
return proj;
}
public Sell() {
this.setAsSold = true;
// Selling logic is handled in TowerManager.update()
}
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.CircleTowerBehaviour) CircleTowerBehaviour(this, elapsedMS);
}

View File

@ -12,11 +12,13 @@ import { Tower } from './Tower';
*/
function projectileCheck(tower: Tower, elapsedMS: number) {
tower.projectiles.forEach((proj) => {
if (proj.deleteMe) {
if (proj.deleteMe || tower.sold) {
proj.collidedCreepIDs.forEach(() => {
tower.damageDealt += tower.computedDamageToDeal;
});
proj.collidedCreepIDs = [];
tower.projectiles.splice(tower.projectiles.indexOf(proj), 1);
proj.destroy();
proj = null;
} else proj.update(elapsedMS);
});
@ -57,7 +59,7 @@ export function computeGemImprovements(tower: Tower) {
tower.totalGemResistanceModifications.frostfire += gemResMod.frostfire;
});
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.computedTimeToLive = tower.definition.stats.timeToLive + gemTimeToLiveUp;
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.
*/
export function BasicTowerBehaviour(tower: Tower, elapsedMS: number) {
if (tower.ticksUntilNextShot % 2 == 0) computeGemImprovements(tower);
computeGemImprovements(tower);
projectileCheck(tower, elapsedMS);
if (tower.ticksUntilNextShot > 0) tower.ticksUntilNextShot--;
if (tower.millisecondsUntilNextShot > 0)
tower.millisecondsUntilNextShot -= elapsedMS * Engine.GameScene.gameSpeedMultiplier;
let creepsInRange = tower.GetCreepsInRange();
if (creepsInRange.length > 0) {
let focus = creepsInRange[0];
if (tower.ticksUntilNextShot <= 0) {
if (tower.millisecondsUntilNextShot <= 0) {
let x = tower.column * 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));
}
}
}
export function CircleTowerBehaviour(tower: Tower, elapsedMS: number) {
if (tower.ticksUntilNextShot % 2 == 0) computeGemImprovements(tower);
computeGemImprovements(tower);
projectileCheck(tower, elapsedMS);
if (tower.ticksUntilNextShot > 0) tower.ticksUntilNextShot--;
if (tower.millisecondsUntilNextShot > 0)
tower.millisecondsUntilNextShot -= elapsedMS * Engine.GameScene.gameSpeedMultiplier;
let creepsInRange = tower.GetCreepsInRange();
if (creepsInRange.length > 0) {
let focus = creepsInRange[0];
if (tower.ticksUntilNextShot <= 0) {
tower.ticksUntilNextShot = tower.computedAttackSpeed;
if (tower.millisecondsUntilNextShot <= 0) {
tower.millisecondsUntilNextShot = tower.computedCooldown;
let x = tower.column * Engine.GridCellSize + Engine.GridCellSize / 2;
let y = tower.row * Engine.GridCellSize + Engine.GridCellSize / 2;
tower.Shoot(calculateAngleToPoint(x, y, x, y + 10)); // Up

View File

@ -114,8 +114,17 @@ export default class TowerManager {
}
}
public update(elapsedMS) {
this.towers.forEach((twr) => {
twr.update(elapsedMS);
this.towers.forEach((twr, idx) => {
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);
});
}
}

View File

@ -60,7 +60,7 @@ export default class WaveManager extends GameObject {
}
public update(elapsedMS: number): void {
if (this.started == false) return;
this.ticks += elapsedMS;
this.ticks += elapsedMS * Engine.GameScene.gameSpeedMultiplier;
this.creeps.forEach((creep) => {
if (!creep.spawned && creep.tickToSpawnAt <= this.ticks) {
creep.spawned = true;

View 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();
}
}

View File

@ -1,6 +1,5 @@
import * as PIXI from 'pixi.js';
import ModalDialogBase from './ModalDialog';
import GuiObject from '../GuiObject';
export default class MessageBox extends ModalDialogBase {
private caption: string;

View File

@ -1,6 +1,5 @@
import * as PIXI from 'pixi.js';
import GuiObject from '../GuiObject';
import Assets from '../Assets';
import { Engine } from '../Bastion';
import GameAssets from '../Assets';
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(
this.dialogContent.y
)}, width: ${Math.round(this.dialogContent.width)}, height: ${Math.round(this.dialogContent.height)}`;
console.debug(
`ModalDialogBase.show(dialog: ${dialogBounds}, content: ${contentBounds}, buttons: ${this.buttonCaptions})`
);
// console.debug(
// `ModalDialogBase.show(dialog: ${dialogBounds}, content: ${contentBounds}, buttons: ${this.buttonCaptions})`
// );
return new Promise((resolve, reject) => {
Engine.app.stage.addChild(this.container);
this.onClosed = (button) => {

View File

@ -179,9 +179,14 @@ export default class Tooltip extends GuiObject {
this.gemDescriptionText.alpha = 1;
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 =
`Valued at ${gem.definition.initialGemValue + gem.currentGemImprovement().gemValueUp} gold. ` +
gem.definition.description;
`${costToLevelUp} Valued at ${
gem.definition.initialGemValue + gem.currentGemImprovement().gemValueUp
} gold. ` + gem.definition.description;
}
public Show(x, y) {
this.container.alpha = 1;

View File

@ -73,7 +73,7 @@ export class VisualGemSlot extends GuiObject {
this.container.addChild(this.background);
this.container.addChild(this.iconSprite);
this.container.addChild(this.frame);
let txt = gem ? gem.id : '';
let txt = gem ? gem.level : '';
let dbgText = new PIXI.Text({
text: txt,
zIndex: 11,
@ -114,6 +114,7 @@ export default class TowerPanel extends GuiObject {
public frostFireResDamage: PIXI.Text;
public divineResDamage: PIXI.Text;
public physicalResDamage: PIXI.Text;
private sellButton: Button;
constructor(bounds: PIXI.Rectangle) {
super(false);
@ -156,6 +157,7 @@ export default class TowerPanel extends GuiObject {
zIndex: 5,
style: new PIXI.TextStyle({
fill: 0xffffff,
fontSize: 25,
stroke: {
color: 0x000000,
width: 2,
@ -280,6 +282,14 @@ export default class TowerPanel extends GuiObject {
}),
});
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) {
this.vGems.forEach((vGem) => {
@ -319,7 +329,7 @@ export default class TowerPanel extends GuiObject {
this.MakeSlots(tower);
this.showingTower = tower;
Engine.GameScene.sidebar.gemTab.selectingGemTowerObject = tower;
if (tower.container.parent.x < 900) {
if (tower.container.parent.x < 1270) {
this.ShowRight();
} else {
this.ShowLeft();
@ -331,13 +341,18 @@ export default class TowerPanel extends GuiObject {
this.damageText.text = 'Deals ' + tower.computedDamageToDeal + ' damage';
this.totalDamage.text = 'Damage dealt: ' + tower.damageDealt + ' damage';
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.iceResDamage.text = `+${tower.totalGemResistanceModifications.ice * 100}% Ice damage`;
this.frostFireResDamage.text = `+${tower.totalGemResistanceModifications.frostfire * 100}% FrostFire damage`;
this.divineResDamage.text = `+${tower.totalGemResistanceModifications.divine * 100}% Divine 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() {
this.towerPanel.x = -100;

View File

@ -46,6 +46,7 @@ import { GemType } from './classes/Definitions';
}
Engine.latestCommit = await fetch('/latest_commit').then((res) => res.text());
window.addEventListener('resize', resize);
resize();
await Assets.LoadAssets();
GameUIConstants.init();
@ -71,4 +72,21 @@ import { GemType } from './classes/Definitions';
return 'You are about to leave.';
};
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();
}
});
})();

View File

@ -18,11 +18,12 @@ import TowerPanel, { VisualGemSlot } from '../classes/gui/TowerPanel';
import Gem from '../classes/game/Gem';
import EndGameDialog from '../classes/gui/EndGameDialog';
import HighScoreDialog, { HighScoreDialogButtons } from '../classes/gui/HighScoreDialog';
import GamePausedDialog from '../classes/gui/GamePausedDialog';
enum RoundMode {
Purchase = 0,
Combat = 1,
OfferingGems = 2,
Misc = 2,
}
export class GameScene extends Scene {
@ -36,6 +37,10 @@ export class GameScene extends Scene {
public sidebar: Sidebar;
public tooltip: Tooltip;
public towerPanel: TowerPanel;
public isPaused: boolean = false;
public gameSpeedMultiplier: number = 1;
private pauseButton: Button;
private visualGems: VisualGemSlot[] = [];
private currentRound: number = 0;
private isWaveManagerFinished: boolean = false;
@ -47,10 +52,12 @@ export class GameScene extends Scene {
y: 0,
zIndex: 120,
});
private windowTitle: string;
constructor(name: string) {
super();
Engine.GameScene = this;
this.windowTitle = document.title;
GameAssets.Missions.forEach((mission, index) => {
if (mission.name == name) {
this.mission = mission;
@ -101,15 +108,21 @@ export class GameScene extends Scene {
this.changeRoundButton.CustomButtonLogic();
this.changeRoundButton.onClick = () => {
if (this.playerWon) return this.ReturnToMain();
if (this.roundMode == RoundMode.Combat)
return Engine.NotificationManager.Notify('Wave is already in progress.', 'warn');
if (this.roundMode == RoundMode.Combat) {
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.roundMode == RoundMode.OfferingGems) return;
if (this.roundMode == RoundMode.Misc) return;
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.MissionStats = new MissionStats(100, 200);
this.MissionStats = new MissionStats(125, 450);
this.events.on(GemEvents.TowerPanelSelectGem, (gem, index, tower) => {
if (gem == null) {
if (!this.MissionStats.checkIfPlayerHasAnyGems())
@ -120,6 +133,30 @@ export class GameScene extends Scene {
}
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.maxFPS = 60;
this.ticker.minFPS = 30;
@ -130,10 +167,10 @@ export class GameScene extends Scene {
this.ticker.add(() => {
if (this.update) this.update(this.ticker.elapsedMS);
// if (this.isFastForwarded) this.update(this.ticker.elapsedMS);
});
this.ticker.start();
}
public update(elapsedMS) {
if (this.isGameOver) {
if (this.destroyTicker) {
@ -183,7 +220,7 @@ export class GameScene extends Scene {
Engine.Grid.gridInteractionEnabled = false;
Engine.GameScene.sidebar.towerTab.resetTint();
Engine.TowerManager.ResetChooseTower();
this.setRoundMode(RoundMode.OfferingGems);
this.setRoundMode(RoundMode.Misc);
let gemsToOffer = this.mission.rounds[this.currentRound].offeredGems;
this.DarkenScreen();
this.offerGemsSprite = new PIXI.NineSliceSprite({
@ -245,6 +282,21 @@ export class GameScene extends Scene {
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) {
const endGameDialog = new EndGameDialog(this.mission.name, this.MissionStats, lost);
await endGameDialog.show();
@ -292,4 +344,10 @@ export class GameScene extends Scene {
private ReturnToMain() {
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
View 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());
};
}
}

View File

@ -1,66 +1,59 @@
import GameAssets from '../classes/Assets';
import { Engine } from '../classes/Bastion';
import { FadeInOut, Tween } from '../classes/game/AnimationManager';
import Button, { ButtonTexture } from '../classes/gui/Button';
import { HowToPlay } from './HowToPlay';
import { MissionPickerScene } from './MissionPicker';
import Scene from './Scene';
import * as PIXI from 'pixi.js';
import { SettingsScene } from './Settings';
export class MainScene extends Scene {
public init() {
// Background
this.addMainBackground();
const NewGameButton = {
caption: 'New Game',
rect: new PIXI.Rectangle(
Engine.app.canvas.width / 2 - 300 / 2,
Engine.app.canvas.height / 5 + 3 * 80,
300,
60
),
texture: ButtonTexture.Button02,
rect: new PIXI.Rectangle(Engine.app.canvas.width / 2 - 300 / 2, 400 + 0 * 70, 300, 60),
texture: ButtonTexture.Button01,
};
const TutorialButton = {
caption: 'How to play',
rect: new PIXI.Rectangle(Engine.app.canvas.width / 2 - 300 / 2, 400 + 1 * 70, 300, 60),
texture: ButtonTexture.Button01,
};
const SettingsButton = {
caption: 'Settings',
rect: new PIXI.Rectangle(
Engine.app.canvas.width / 2 - 300 / 2,
Engine.app.canvas.height / 5 + 4 * 80,
300,
60
),
texture: ButtonTexture.Button02,
rect: new PIXI.Rectangle(Engine.app.canvas.width / 2 - 300 / 2, 400 + 2 * 70, 300, 60),
texture: ButtonTexture.Button01,
};
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({
x: 0,
y: 0,
text: 'Latest commit: ' + Engine.latestCommit,
style: {
fill: 0x000000,
fill: 0xffffff,
fontSize: 10,
fontWeight: 'bold',
},
});
Engine.GameMaster.currentScene.stage.addChild(text2);
this.stage.addChild(text2);
const button01 = new Button(NewGameButton.rect, NewGameButton.caption, NewGameButton.texture, true);
button01.onClick = (e) => {
Engine.GameMaster.currentScene.stage.removeChild(text);
Engine.GameMaster.currentScene.stage.removeChild(text2);
Engine.GameMaster.changeScene(new MissionPickerScene());
};
let b2 = new Button(SettingsButton.rect, SettingsButton.caption, SettingsButton.texture, true);
b2.onClick = (e) => {
Engine.NotificationManager.Notify('Not finished.', 'info');
// let b2 = new Button(SettingsButton.rect, SettingsButton.caption, SettingsButton.texture, true);
// b2.onClick = (e) => {
// Engine.GameMaster.changeScene(new SettingsScene());
// };
let b3 = new Button(TutorialButton.rect, TutorialButton.caption, TutorialButton.texture, true);
b3.onClick = (e) => {
Engine.GameMaster.changeScene(new HowToPlay());
};
}
}

View File

@ -8,18 +8,14 @@ import * as PIXI from 'pixi.js';
export class MissionPickerScene extends Scene {
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) => {
Engine.GameMaster.changeScene(new MainScene());
};
Assets.Missions.forEach((mission, index) => {
const button = new Button(
new PIXI.Rectangle(
Engine.app.canvas.width / 2 - 300 / 2,
Engine.app.canvas.height / 5 + index * 80,
300,
60
),
new PIXI.Rectangle(Engine.app.canvas.width / 2 - 300 / 2, 400 + index * 70, 300, 60),
mission.name,
ButtonTexture.Button01
);

View File

@ -1,3 +1,4 @@
import GameAssets from '../classes/Assets';
import { Engine } from '../classes/Bastion';
import GuiObject from '../classes/GuiObject';
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 {
return this._events;
}

17
src/scenes/Settings.ts Normal file
View 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());
};
}
}