Working on end-game menu
This commit is contained in:
parent
92f196310d
commit
13f4c4610e
@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<tileset version="1.10" tiledversion="1.11.0" name="TiledTDThree64" tilewidth="64" tileheight="64" tilecount="140" columns="14">
|
<tileset version="1.10" tiledversion="1.11.0" name="TiledTDThree64" tilewidth="64" tileheight="64" tilecount="140" columns="14">
|
||||||
<image source="../../../../dumping/tiles/TiledTDThree64.png" width="896" height="640"/>
|
<image source="c:\Work\Projects\Matej\towerdefense-tiles\TiledTDThree64.png" width="896" height="640"/>
|
||||||
</tileset>
|
</tileset>
|
||||||
|
@ -24,6 +24,7 @@ export default class GameAssets {
|
|||||||
public static SwordsTexture: PIXI.Texture;
|
public static SwordsTexture: PIXI.Texture;
|
||||||
public static TitleTexture: PIXI.Texture;
|
public static TitleTexture: PIXI.Texture;
|
||||||
public static BannerGemsmith: PIXI.Texture;
|
public static BannerGemsmith: PIXI.Texture;
|
||||||
|
public static EndScreenDialog: PIXI.Texture;
|
||||||
|
|
||||||
public static PlayIconTexture: PIXI.Texture;
|
public static PlayIconTexture: PIXI.Texture;
|
||||||
public static PauseIconTexture: PIXI.Texture;
|
public static PauseIconTexture: PIXI.Texture;
|
||||||
@ -96,6 +97,7 @@ export default class GameAssets {
|
|||||||
this.Load('./assets/gui/frame_green.png').then((texture) => (this.GreenBackground = texture)),
|
this.Load('./assets/gui/frame_green.png').then((texture) => (this.GreenBackground = texture)),
|
||||||
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/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)),
|
||||||
|
@ -28,3 +28,9 @@ export enum StatsEvents {
|
|||||||
export enum GemEvents {
|
export enum GemEvents {
|
||||||
TowerPanelSelectGem = 'towerTabSelectGem',
|
TowerPanelSelectGem = 'towerTabSelectGem',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum EndMissionDialogEvents {
|
||||||
|
NextMission = 'nextMission',
|
||||||
|
RetryMission = 'retryMission',
|
||||||
|
MainMenu = 'mainMenu',
|
||||||
|
}
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import * as PIXI from 'pixi.js';
|
import * as PIXI from 'pixi.js';
|
||||||
import { Engine } from './Bastion';
|
import { Engine } from './Bastion';
|
||||||
export default class GameUIConstants {
|
export default class GameUIConstants {
|
||||||
public static SidebarRect;
|
public static SidebarRect: PIXI.Rectangle;
|
||||||
public static ChangeRoundButtonRect;
|
public static ChangeRoundButtonRect: PIXI.Rectangle;
|
||||||
|
public static EndGameDialogRect: PIXI.Rectangle;
|
||||||
|
|
||||||
public static init() {
|
public static init() {
|
||||||
GameUIConstants.SidebarRect = new PIXI.Rectangle(
|
GameUIConstants.SidebarRect = new PIXI.Rectangle(
|
||||||
Engine.app.canvas.width - 360,
|
Engine.app.canvas.width - 360,
|
||||||
@ -11,5 +13,13 @@ export default class GameUIConstants {
|
|||||||
Engine.app.canvas.height
|
Engine.app.canvas.height
|
||||||
);
|
);
|
||||||
GameUIConstants.ChangeRoundButtonRect = new PIXI.Rectangle(50, Engine.app.canvas.height - 100, 310, 100);
|
GameUIConstants.ChangeRoundButtonRect = new PIXI.Rectangle(50, Engine.app.canvas.height - 100, 310, 100);
|
||||||
|
const endGameDialogWidth = 600;
|
||||||
|
const endGameDialogHeight = 800;
|
||||||
|
GameUIConstants.EndGameDialogRect = new PIXI.Rectangle(
|
||||||
|
(Engine.app.canvas.width - endGameDialogWidth) / 2,
|
||||||
|
(Engine.app.canvas.height - endGameDialogHeight) / 2,
|
||||||
|
endGameDialogWidth,
|
||||||
|
endGameDialogHeight
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,6 +51,7 @@ export default class Creep extends GameObject {
|
|||||||
// Added + 32 to center them.
|
// Added + 32 to center them.
|
||||||
this.x = path[0][1] * Engine.GridCellSize + Engine.GridCellSize / 2;
|
this.x = path[0][1] * Engine.GridCellSize + Engine.GridCellSize / 2;
|
||||||
this.y = path[0][0] * Engine.GridCellSize + Engine.GridCellSize / 2;
|
this.y = path[0][0] * Engine.GridCellSize + Engine.GridCellSize / 2;
|
||||||
|
// TODO: Unsubscribe from events once the scene is destroyed
|
||||||
Engine.GameScene.events.on(CreepEvents.TakenDamage, (creepID, damage) => {
|
Engine.GameScene.events.on(CreepEvents.TakenDamage, (creepID, damage) => {
|
||||||
if (creepID != this.id) return;
|
if (creepID != this.id) return;
|
||||||
this.health -= damage;
|
this.health -= damage;
|
||||||
|
52
src/classes/game/KeyboardManager.ts
Normal file
52
src/classes/game/KeyboardManager.ts
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/**
|
||||||
|
* Handles keyboard events.
|
||||||
|
*/
|
||||||
|
class KeyboardManager {
|
||||||
|
private static listeners: Map<string, ((event: KeyboardEvent) => void)[]> = new Map();
|
||||||
|
|
||||||
|
public static init() {
|
||||||
|
window.addEventListener('keydown', KeyboardManager.handleKeyDown);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a callback to be called when the specified key is pressed.
|
||||||
|
* Note: Calling preventDefault() on the event will prevent other callbacks from being called.
|
||||||
|
* @param key The key to listen for.
|
||||||
|
* @param callback The callback to call when the key is pressed.
|
||||||
|
* @returns A function that can be called to remove the callback.
|
||||||
|
*/
|
||||||
|
public static onKey(key: string, callback: (event: KeyboardEvent) => void) {
|
||||||
|
if (!KeyboardManager.listeners.has(key)) {
|
||||||
|
KeyboardManager.listeners.set(key, []);
|
||||||
|
}
|
||||||
|
KeyboardManager.listeners.get(key).push(callback);
|
||||||
|
return () => KeyboardManager.offKey(key, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a callback from the specified key.
|
||||||
|
*/
|
||||||
|
public static offKey(key: string, callback: (event: KeyboardEvent) => void) {
|
||||||
|
if (KeyboardManager.listeners.has(key)) {
|
||||||
|
const index = KeyboardManager.listeners.get(key).indexOf(callback);
|
||||||
|
if (index >= 0) {
|
||||||
|
KeyboardManager.listeners.get(key).splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static handleKeyDown(event: KeyboardEvent) {
|
||||||
|
if (KeyboardManager.listeners.has(event.key)) {
|
||||||
|
console.log(`Key down: ${event.key}`);
|
||||||
|
const callbacks = KeyboardManager.listeners.get(event.key);
|
||||||
|
for (let i = callbacks.length - 1; i >= 0; i--) {
|
||||||
|
callbacks[i](event);
|
||||||
|
if (event.defaultPrevented) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default KeyboardManager;
|
@ -23,6 +23,7 @@ export default class TowerManager {
|
|||||||
});
|
});
|
||||||
private towers: Tower[] = [];
|
private towers: Tower[] = [];
|
||||||
constructor() {
|
constructor() {
|
||||||
|
// TODO: Unsubscribe from events once the scene is destroyed
|
||||||
Engine.TowerManager = this;
|
Engine.TowerManager = this;
|
||||||
Engine.GameScene.events.on(GridEvents.CellMouseOver, (cell: Cell) => {
|
Engine.GameScene.events.on(GridEvents.CellMouseOver, (cell: Cell) => {
|
||||||
if (this.isPlacingTower) {
|
if (this.isPlacingTower) {
|
||||||
|
@ -22,6 +22,10 @@ export default class Button extends GuiObject {
|
|||||||
this.buttonText.text = caption;
|
this.buttonText.text = caption;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getCaption(): string {
|
||||||
|
return this.caption;
|
||||||
|
}
|
||||||
|
|
||||||
constructor(bounds: PIXI.Rectangle, caption: string, buttonTexture: ButtonTexture, enabled: boolean = true) {
|
constructor(bounds: PIXI.Rectangle, caption: string, buttonTexture: ButtonTexture, enabled: boolean = true) {
|
||||||
super(true);
|
super(true);
|
||||||
if (buttonTexture == ButtonTexture.Button01) this.buttonTexture = Assets.Button01Texture;
|
if (buttonTexture == ButtonTexture.Button01) this.buttonTexture = Assets.Button01Texture;
|
||||||
|
119
src/classes/gui/EndGameDialog.ts
Normal file
119
src/classes/gui/EndGameDialog.ts
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
import * as PIXI from 'pixi.js';
|
||||||
|
import GuiObject from '../GuiObject';
|
||||||
|
import GameAssets from '../Assets';
|
||||||
|
import GameUIConstants from '../GameUIConstants';
|
||||||
|
import Button, { ButtonTexture } from './Button';
|
||||||
|
import { Engine } from '../Bastion';
|
||||||
|
import { EndMissionDialogEvents } from '../Events';
|
||||||
|
import MessageBox from './MessageBox';
|
||||||
|
import KeyboardManager from '../game/KeyboardManager';
|
||||||
|
|
||||||
|
export default class EndGameDialog extends GuiObject {
|
||||||
|
private dialogSprite: PIXI.NineSliceSprite;
|
||||||
|
private dialogCaption: PIXI.Text;
|
||||||
|
private nextMissionButton: Button;
|
||||||
|
private retryButton: Button;
|
||||||
|
private mainMenuButton: Button;
|
||||||
|
private overlay: PIXI.Graphics;
|
||||||
|
private lost: boolean;
|
||||||
|
private keyboardManagerUnsubscribe: () => void;
|
||||||
|
|
||||||
|
constructor(bounds: PIXI.Rectangle, lost: boolean) {
|
||||||
|
super();
|
||||||
|
this.lost = lost;
|
||||||
|
// Show overlay to prevent user from interacting with the game
|
||||||
|
this.overlay = new PIXI.Graphics();
|
||||||
|
this.overlay.rect(0, 0, bounds.width, bounds.height);
|
||||||
|
this.overlay.fill({ color: 0x000000, alpha: 0.5 });
|
||||||
|
// Prevent interaction with the underlying scene
|
||||||
|
this.overlay.interactive = true;
|
||||||
|
this.container.addChild(this.overlay);
|
||||||
|
|
||||||
|
this.dialogSprite = new PIXI.NineSliceSprite({
|
||||||
|
texture: GameAssets.EndScreenDialog,
|
||||||
|
leftWidth: 50,
|
||||||
|
topHeight: 100,
|
||||||
|
rightWidth: 50,
|
||||||
|
bottomHeight: 50,
|
||||||
|
});
|
||||||
|
this.dialogSprite.x = GameUIConstants.EndGameDialogRect.x;
|
||||||
|
this.dialogSprite.y = GameUIConstants.EndGameDialogRect.y;
|
||||||
|
this.dialogSprite.width = GameUIConstants.EndGameDialogRect.width;
|
||||||
|
this.dialogSprite.height = GameUIConstants.EndGameDialogRect.height;
|
||||||
|
this.container.addChild(this.dialogSprite);
|
||||||
|
this.dialogCaption = new PIXI.Text({
|
||||||
|
text: lost ? 'You lost!' : 'You won!',
|
||||||
|
style: new PIXI.TextStyle({
|
||||||
|
fill: 0xffffff,
|
||||||
|
fontSize: 36,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
this.container.addChild(this.dialogCaption);
|
||||||
|
this.dialogCaption.anchor.set(0.5, 0.5);
|
||||||
|
this.dialogCaption.x = GameUIConstants.EndGameDialogRect.x + GameUIConstants.EndGameDialogRect.width / 2;
|
||||||
|
this.dialogCaption.y = GameUIConstants.EndGameDialogRect.y + 50;
|
||||||
|
//this.setupButtons(lost);
|
||||||
|
this.keyboardManagerUnsubscribe = KeyboardManager.onKey('Escape', (e) => {
|
||||||
|
if (e.key === 'Escape') {
|
||||||
|
this.onMainMission();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.container.on('destroyed', () => {
|
||||||
|
this.keyboardManagerUnsubscribe();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private setupButtons(lost: boolean) {
|
||||||
|
const buttonContainer = new PIXI.Container();
|
||||||
|
const buttonWidth = 200;
|
||||||
|
const buttonHeight = 80;
|
||||||
|
const buttonPadding = 10;
|
||||||
|
if (lost) {
|
||||||
|
this.retryButton = new Button(
|
||||||
|
new PIXI.Rectangle(0, 0, buttonWidth, buttonHeight),
|
||||||
|
'Retry',
|
||||||
|
ButtonTexture.Button01
|
||||||
|
);
|
||||||
|
this.retryButton.onClick = () => {
|
||||||
|
Engine.GameScene.events.emit(EndMissionDialogEvents.RetryMission);
|
||||||
|
};
|
||||||
|
buttonContainer.addChild(this.retryButton.container);
|
||||||
|
} else {
|
||||||
|
this.nextMissionButton = new Button(
|
||||||
|
new PIXI.Rectangle(0, 0, buttonWidth, buttonHeight),
|
||||||
|
'Next Mission',
|
||||||
|
ButtonTexture.Button01
|
||||||
|
);
|
||||||
|
this.nextMissionButton.onClick = () => {
|
||||||
|
Engine.GameScene.events.emit(EndMissionDialogEvents.NextMission);
|
||||||
|
};
|
||||||
|
buttonContainer.addChild(this.nextMissionButton.container);
|
||||||
|
}
|
||||||
|
this.mainMenuButton = new Button(
|
||||||
|
new PIXI.Rectangle(0, buttonHeight + buttonPadding, buttonWidth, buttonHeight),
|
||||||
|
'Main Menu',
|
||||||
|
ButtonTexture.Button01
|
||||||
|
);
|
||||||
|
this.mainMenuButton.onClick = this.onMainMission.bind(this);
|
||||||
|
buttonContainer.addChild(this.mainMenuButton.container);
|
||||||
|
this.container.addChild(buttonContainer);
|
||||||
|
buttonContainer.x =
|
||||||
|
GameUIConstants.EndGameDialogRect.x +
|
||||||
|
GameUIConstants.EndGameDialogRect.width / 2 -
|
||||||
|
buttonContainer.width / 2;
|
||||||
|
buttonContainer.y =
|
||||||
|
GameUIConstants.EndGameDialogRect.y + GameUIConstants.EndGameDialogRect.height - buttonContainer.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
private showingMessageBox: boolean;
|
||||||
|
|
||||||
|
private async onMainMission() {
|
||||||
|
if (this.showingMessageBox) return;
|
||||||
|
this.showingMessageBox = true;
|
||||||
|
const result = await MessageBox.show('Are you sure you want to return to the main menu?', ['Yes', 'No']);
|
||||||
|
this.showingMessageBox = false;
|
||||||
|
if (result === 'Yes') {
|
||||||
|
Engine.GameScene.events.emit(EndMissionDialogEvents.MainMenu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
143
src/classes/gui/MessageBox.ts
Normal file
143
src/classes/gui/MessageBox.ts
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
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';
|
||||||
|
import KeyboardManager from '../game/KeyboardManager';
|
||||||
|
|
||||||
|
export default class MessageBox extends GuiObject {
|
||||||
|
private overlay: PIXI.Graphics;
|
||||||
|
private buttonPadding = 10;
|
||||||
|
private buttons: Button[] = [];
|
||||||
|
private escapeKeyIndex: number;
|
||||||
|
private keyboardManagerUnsubscribe: () => void;
|
||||||
|
|
||||||
|
constructor(caption: string, buttons: string[], escapeKeyIndex: number = buttons.length - 1) {
|
||||||
|
super();
|
||||||
|
console.log(`MessageBox(caption: ${caption}, buttons: ${buttons})`);
|
||||||
|
this.escapeKeyIndex = escapeKeyIndex;
|
||||||
|
// Show overlay to prevent user from interacting with the game
|
||||||
|
this.overlay = new PIXI.Graphics();
|
||||||
|
this.overlay.rect(0, 0, Engine.app.canvas.width, Engine.app.canvas.height);
|
||||||
|
this.overlay.fill({ color: 0x000000, alpha: 0.5 });
|
||||||
|
// Prevent interaction with the underlying scene
|
||||||
|
this.overlay.interactive = true;
|
||||||
|
this.container.addChild(this.overlay);
|
||||||
|
|
||||||
|
const buttonDefs = buttons.map((btn) => ({
|
||||||
|
caption: btn,
|
||||||
|
width: btn.length * 10 + 40,
|
||||||
|
height: 60,
|
||||||
|
click: () => this.buttonClicked(btn),
|
||||||
|
}));
|
||||||
|
let buttonTotalWidth = 0;
|
||||||
|
for (const buttonDef of buttonDefs) {
|
||||||
|
if (buttonTotalWidth > 0) buttonTotalWidth += this.buttonPadding;
|
||||||
|
buttonTotalWidth += buttonDef.width;
|
||||||
|
}
|
||||||
|
const captionWidth = caption.length * 10 + 100;
|
||||||
|
let width = Math.max(buttonTotalWidth, captionWidth);
|
||||||
|
|
||||||
|
const height = 150;
|
||||||
|
const inputContainerBounds = new PIXI.Rectangle(
|
||||||
|
Engine.app.canvas.width / 2 - width / 2,
|
||||||
|
Engine.app.canvas.height / 2 - height / 2,
|
||||||
|
width,
|
||||||
|
height
|
||||||
|
);
|
||||||
|
|
||||||
|
const inputContainer = new PIXI.Container();
|
||||||
|
inputContainer.x = inputContainerBounds.x;
|
||||||
|
inputContainer.y = inputContainerBounds.y;
|
||||||
|
inputContainer.width = inputContainerBounds.width;
|
||||||
|
inputContainer.height = inputContainerBounds.height;
|
||||||
|
|
||||||
|
const background = new PIXI.NineSliceSprite({
|
||||||
|
texture: GameAssets.Frame04Texture,
|
||||||
|
leftWidth: 200,
|
||||||
|
topHeight: 200,
|
||||||
|
rightWidth: 200,
|
||||||
|
bottomHeight: 200,
|
||||||
|
});
|
||||||
|
background.x = 0;
|
||||||
|
background.y = 0;
|
||||||
|
background.width = inputContainerBounds.width;
|
||||||
|
background.height = inputContainerBounds.height;
|
||||||
|
inputContainer.addChild(background);
|
||||||
|
|
||||||
|
const text = new PIXI.Text({
|
||||||
|
text: caption,
|
||||||
|
style: new PIXI.TextStyle({
|
||||||
|
fill: 0xffffff,
|
||||||
|
fontSize: 24,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
text.anchor.set(0.5, 0.5);
|
||||||
|
text.x = inputContainerBounds.width / 2;
|
||||||
|
text.y = 40;
|
||||||
|
inputContainer.addChild(text);
|
||||||
|
|
||||||
|
let buttonXPos = inputContainerBounds.width / 2 - buttonTotalWidth / 2;
|
||||||
|
for (const buttonDef of buttonDefs) {
|
||||||
|
const button = new Button(
|
||||||
|
new PIXI.Rectangle(
|
||||||
|
buttonXPos,
|
||||||
|
inputContainerBounds.height - buttonDef.height - 20,
|
||||||
|
buttonDef.width,
|
||||||
|
buttonDef.height
|
||||||
|
),
|
||||||
|
buttonDef.caption,
|
||||||
|
ButtonTexture.Button01
|
||||||
|
);
|
||||||
|
button.onClick = buttonDef.click;
|
||||||
|
this.buttons.push(button);
|
||||||
|
inputContainer.addChild(button.container);
|
||||||
|
buttonXPos += buttonDef.width + this.buttonPadding;
|
||||||
|
}
|
||||||
|
this.container.addChild(inputContainer);
|
||||||
|
this.keyboardManagerUnsubscribe = KeyboardManager.onKey('Escape', this.onKeyPress.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event that is triggered when the button is clicked.
|
||||||
|
*/
|
||||||
|
public onButtonClicked: (button: string) => void;
|
||||||
|
|
||||||
|
override destroy(): void {
|
||||||
|
this.keyboardManagerUnsubscribe();
|
||||||
|
super.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private buttonClicked(button: string) {
|
||||||
|
if (this.onButtonClicked) this.onButtonClicked(button);
|
||||||
|
this.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private onKeyPress(event: KeyboardEvent) {
|
||||||
|
// Message box is modal, so we can safely prevent the default behavior
|
||||||
|
event.preventDefault();
|
||||||
|
if (event.key === 'Escape') {
|
||||||
|
this.onButtonClicked(this.buttons[this.escapeKeyIndex].getCaption());
|
||||||
|
} else if (event.key === 'Enter') {
|
||||||
|
this.onButtonClicked(this.buttons[0].getCaption());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows a message box with the specified caption and buttons.
|
||||||
|
* @param caption The caption of the message box.
|
||||||
|
* @param buttons The buttons to show.
|
||||||
|
* @returns A promise that resolves with the button that was clicked.
|
||||||
|
*/
|
||||||
|
public static show(caption: string, buttons: string[], escapeKeyButtonIndex: number = 0): Promise<string> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const messageBox = new MessageBox(caption, buttons);
|
||||||
|
Engine.app.stage.addChild(messageBox.container);
|
||||||
|
messageBox.onButtonClicked = (button) => {
|
||||||
|
messageBox.destroy();
|
||||||
|
resolve(button);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
53
src/classes/gui/TextInput.ts
Normal file
53
src/classes/gui/TextInput.ts
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import * as PIXI from 'pixi.js';
|
||||||
|
import GuiObject from '../GuiObject';
|
||||||
|
import Assets from '../Assets';
|
||||||
|
import GameAssets from '../Assets';
|
||||||
|
|
||||||
|
export default class TextInput extends GuiObject {
|
||||||
|
private bounds: PIXI.Rectangle;
|
||||||
|
private backgroundSprite: PIXI.NineSliceSprite;
|
||||||
|
private text: PIXI.Text;
|
||||||
|
private maxLength: number;
|
||||||
|
|
||||||
|
constructor(bounds: PIXI.Rectangle, maxLength: number) {
|
||||||
|
super();
|
||||||
|
this.bounds = bounds;
|
||||||
|
this.maxLength = maxLength;
|
||||||
|
this.container.x = this.bounds.x;
|
||||||
|
this.container.y = this.bounds.y;
|
||||||
|
this.container.width = this.bounds.width;
|
||||||
|
this.container.height = this.bounds.height;
|
||||||
|
this.backgroundSprite = new PIXI.NineSliceSprite({
|
||||||
|
texture: GameAssets.Frame01Texture,
|
||||||
|
leftWidth: 20,
|
||||||
|
topHeight: 20,
|
||||||
|
rightWidth: 20,
|
||||||
|
bottomHeight: 20,
|
||||||
|
});
|
||||||
|
this.backgroundSprite.x = 0;
|
||||||
|
this.backgroundSprite.y = 0;
|
||||||
|
this.backgroundSprite.width = this.bounds.width;
|
||||||
|
this.backgroundSprite.height = this.bounds.height;
|
||||||
|
this.container.addChild(this.backgroundSprite);
|
||||||
|
this.container.x = this.bounds.x;
|
||||||
|
this.container.y = this.bounds.y;
|
||||||
|
this.text = new PIXI.Text({
|
||||||
|
text: '',
|
||||||
|
style: new PIXI.TextStyle({
|
||||||
|
fill: 0xffffff,
|
||||||
|
fontSize: 16,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
this.text.x = 10;
|
||||||
|
this.text.y = 10;
|
||||||
|
this.container.addChild(this.text);
|
||||||
|
}
|
||||||
|
|
||||||
|
private onKeyPress(event: KeyboardEvent) {
|
||||||
|
if (event.key == 'Backspace') {
|
||||||
|
this.text.text = this.text.text.slice(0, -1);
|
||||||
|
} else if (event.key.length == 1 && this.text.text.length < this.maxLength) {
|
||||||
|
this.text.text += event.key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,6 +6,8 @@ import { GameScene } from './scenes/Game';
|
|||||||
import { AnimationManager } from './classes/game/AnimationManager';
|
import { AnimationManager } from './classes/game/AnimationManager';
|
||||||
import NotificationManager from './classes/game/NotificationManager';
|
import NotificationManager from './classes/game/NotificationManager';
|
||||||
import GameUIConstants from './classes/GameUIConstants';
|
import GameUIConstants from './classes/GameUIConstants';
|
||||||
|
import MessageBox from './classes/gui/MessageBox';
|
||||||
|
import KeyboardManager from './classes/game/KeyboardManager';
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
const app = new PIXI.Application();
|
const app = new PIXI.Application();
|
||||||
@ -47,6 +49,7 @@ import GameUIConstants from './classes/GameUIConstants';
|
|||||||
resize();
|
resize();
|
||||||
await Assets.LoadAssets();
|
await Assets.LoadAssets();
|
||||||
GameUIConstants.init();
|
GameUIConstants.init();
|
||||||
|
KeyboardManager.init();
|
||||||
new GameMaster();
|
new GameMaster();
|
||||||
Engine.AnimationManager = new AnimationManager();
|
Engine.AnimationManager = new AnimationManager();
|
||||||
Engine.NotificationManager = new NotificationManager();
|
Engine.NotificationManager = new NotificationManager();
|
||||||
|
@ -4,7 +4,7 @@ import { MissionDefinition } from '../classes/Definitions';
|
|||||||
import Creep from '../classes/game/Creep';
|
import Creep from '../classes/game/Creep';
|
||||||
import { Grid } from '../classes/game/Grid';
|
import { Grid } from '../classes/game/Grid';
|
||||||
import WaveManager from '../classes/game/WaveManager';
|
import WaveManager from '../classes/game/WaveManager';
|
||||||
import { WaveManagerEvents, CreepEvents, GemEvents } from '../classes/Events';
|
import { WaveManagerEvents, CreepEvents, GemEvents, EndMissionDialogEvents } from '../classes/Events';
|
||||||
import Sidebar from '../classes/gui/Sidebar';
|
import Sidebar from '../classes/gui/Sidebar';
|
||||||
import Button, { ButtonTexture } from '../classes/gui/Button';
|
import Button, { ButtonTexture } from '../classes/gui/Button';
|
||||||
import Scene from './Scene';
|
import Scene from './Scene';
|
||||||
@ -16,6 +16,7 @@ import GameUIConstants from '../classes/GameUIConstants';
|
|||||||
import Tooltip from '../classes/gui/Tooltip';
|
import Tooltip from '../classes/gui/Tooltip';
|
||||||
import TowerPanel, { VisualGemSlot } from '../classes/gui/TowerPanel';
|
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';
|
||||||
|
|
||||||
enum RoundMode {
|
enum RoundMode {
|
||||||
Purchase = 0,
|
Purchase = 0,
|
||||||
@ -40,6 +41,7 @@ export class GameScene extends Scene {
|
|||||||
private playerWon: boolean = false;
|
private playerWon: boolean = false;
|
||||||
private destroyTicker: boolean = false;
|
private destroyTicker: boolean = false;
|
||||||
private offerGemsSprite: PIXI.NineSliceSprite;
|
private offerGemsSprite: PIXI.NineSliceSprite;
|
||||||
|
private endGameDialog: EndGameDialog;
|
||||||
private dimGraphics: PIXI.Graphics = new PIXI.Graphics({
|
private dimGraphics: PIXI.Graphics = new PIXI.Graphics({
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
@ -117,6 +119,9 @@ export class GameScene extends Scene {
|
|||||||
}
|
}
|
||||||
this.sidebar.gemTab.TowerPanelSelectingGem(gem, index, tower);
|
this.sidebar.gemTab.TowerPanelSelectingGem(gem, index, tower);
|
||||||
});
|
});
|
||||||
|
this.events.on(EndMissionDialogEvents.MainMenu, this.onEndMissionDialogMainMenuClicked.bind(this));
|
||||||
|
this.events.on(EndMissionDialogEvents.RetryMission, this.onEndMissionDialogRetryMissionClicked.bind(this));
|
||||||
|
this.events.on(EndMissionDialogEvents.NextMission, this.onEndMissionDialogNextMissionClicked.bind(this));
|
||||||
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,6 +135,7 @@ export class GameScene extends Scene {
|
|||||||
});
|
});
|
||||||
this.ticker.start();
|
this.ticker.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public update(elapsedMS) {
|
public update(elapsedMS) {
|
||||||
if (this.isGameOver) {
|
if (this.isGameOver) {
|
||||||
if (this.destroyTicker) {
|
if (this.destroyTicker) {
|
||||||
@ -242,12 +248,9 @@ export class GameScene extends Scene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ShowScoreScreen(lost) {
|
private ShowScoreScreen(lost) {
|
||||||
// TODO: show to player for real (see how this.OfferPlayerGems() does it)
|
const bounds = new PIXI.Rectangle(0, 0, Engine.app.canvas.width, Engine.app.canvas.height);
|
||||||
if (lost) {
|
this.endGameDialog = new EndGameDialog(bounds, lost);
|
||||||
console.log('LOSE!');
|
Engine.GameMaster.currentScene.stage.addChild(this.endGameDialog.container);
|
||||||
} else {
|
|
||||||
console.log('WIN!');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public onCreepEscaped(creep: Creep) {
|
public onCreepEscaped(creep: Creep) {
|
||||||
@ -263,6 +266,14 @@ export class GameScene extends Scene {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private onEndMissionDialogMainMenuClicked() {
|
||||||
|
this.ReturnToMain();
|
||||||
|
}
|
||||||
|
|
||||||
|
private onEndMissionDialogRetryMissionClicked() {}
|
||||||
|
|
||||||
|
private onEndMissionDialogNextMissionClicked() {}
|
||||||
|
|
||||||
public destroy(): void {
|
public destroy(): void {
|
||||||
super.destroy();
|
super.destroy();
|
||||||
this.isGameOver = true;
|
this.isGameOver = true;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user