Working on end-game menu
This commit is contained in:
parent
2e1c73c9dc
commit
93da72f55c
@ -3,8 +3,6 @@ import { Engine } from './Bastion';
|
||||
export default class GameUIConstants {
|
||||
public static SidebarRect: PIXI.Rectangle;
|
||||
public static ChangeRoundButtonRect: PIXI.Rectangle;
|
||||
public static StandardDialogWidth: number;
|
||||
public static StandardDialogHeight: number;
|
||||
public static MaximumPlayerNameLength = 20;
|
||||
|
||||
public static init() {
|
||||
@ -15,7 +13,5 @@ export default class GameUIConstants {
|
||||
Engine.app.canvas.height
|
||||
);
|
||||
GameUIConstants.ChangeRoundButtonRect = new PIXI.Rectangle(50, Engine.app.canvas.height - 100, 310, 100);
|
||||
GameUIConstants.StandardDialogWidth = 600;
|
||||
GameUIConstants.StandardDialogHeight = 800;
|
||||
}
|
||||
}
|
||||
|
71
src/classes/game/HighScoreManager.ts
Normal file
71
src/classes/game/HighScoreManager.ts
Normal file
@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Handles the high score system.
|
||||
*/
|
||||
export class HighScoreManager {
|
||||
private static readonly STORAGE_KEY_PREFIX = 'highscore_';
|
||||
private static readonly MAX_SCORES = 10;
|
||||
|
||||
public readonly missionName: string;
|
||||
private scores: PlayerScore[];
|
||||
|
||||
constructor(missionName: string) {
|
||||
this.missionName = missionName;
|
||||
this.scores = this.loadScores();
|
||||
this.scores.sort((a, b) => b.score - a.score || a.timestamp - b.timestamp);
|
||||
}
|
||||
|
||||
private loadScores(): PlayerScore[] {
|
||||
const storedScores = localStorage.getItem(HighScoreManager.STORAGE_KEY_PREFIX + this.missionName);
|
||||
return HighScoreManager.parseStoredScores(storedScores);
|
||||
}
|
||||
|
||||
private saveScores(): void {
|
||||
localStorage.setItem(HighScoreManager.STORAGE_KEY_PREFIX + this.missionName, JSON.stringify(this.scores));
|
||||
}
|
||||
|
||||
public addScore(playerScore: PlayerScore): void {
|
||||
this.scores.push(playerScore);
|
||||
this.scores.sort((a, b) => b.score - a.score);
|
||||
if (this.scores.length > HighScoreManager.MAX_SCORES) {
|
||||
this.scores.length = HighScoreManager.MAX_SCORES;
|
||||
}
|
||||
this.saveScores();
|
||||
}
|
||||
|
||||
public getScores(): PlayerScore[] {
|
||||
return this.scores;
|
||||
}
|
||||
|
||||
private static parseStoredScores(storedScores: string | null): PlayerScore[] {
|
||||
if (!storedScores) {
|
||||
return [];
|
||||
}
|
||||
try {
|
||||
const parsedScores = JSON.parse(storedScores);
|
||||
if (
|
||||
Array.isArray(parsedScores) &&
|
||||
parsedScores.every(
|
||||
(score) =>
|
||||
typeof score.playerName === 'string' &&
|
||||
typeof score.score === 'number' &&
|
||||
typeof score.timestamp === 'number'
|
||||
)
|
||||
) {
|
||||
return parsedScores.map((score) => ({
|
||||
playerName: score.playerName,
|
||||
score: score.score,
|
||||
timestamp: score.timestamp,
|
||||
}));
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Failed to parse stored scores:', e);
|
||||
}
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
export type PlayerScore = {
|
||||
playerName: string;
|
||||
score: number;
|
||||
timestamp: number;
|
||||
};
|
@ -8,14 +8,16 @@ import Gem from './Gem';
|
||||
export default class MissionStats extends GameObject {
|
||||
private hp: number = 100;
|
||||
private gold: number = 0;
|
||||
private goldEarned: number = 0;
|
||||
private goldSpent: number = 0;
|
||||
private wavesSurvived: number = 0;
|
||||
private damageDealt: number = 0;
|
||||
private creepsKilled: number = 0;
|
||||
private goldText: PIXI.Text;
|
||||
private healthText: PIXI.Text;
|
||||
private waveText: PIXI.Text;
|
||||
private inventory: Gem[] = [];
|
||||
|
||||
// TODO: implement score keeping for leaderboards.
|
||||
private score: number = 0;
|
||||
|
||||
public getHP() {
|
||||
return this.hp;
|
||||
}
|
||||
@ -147,5 +149,32 @@ export default class MissionStats extends GameObject {
|
||||
});
|
||||
}
|
||||
|
||||
public getStats() {
|
||||
return {
|
||||
hp: this.hp,
|
||||
gold: this.gold,
|
||||
wavesSurvived: this.wavesSurvived,
|
||||
goldEarned: this.goldEarned,
|
||||
goldSpent: this.goldSpent,
|
||||
score: this.calculateScore(),
|
||||
};
|
||||
}
|
||||
|
||||
private calculateScore() {
|
||||
const uniqueGems = [];
|
||||
for (const gem of this.inventory) {
|
||||
if (!uniqueGems.includes(gem.definition.name)) {
|
||||
uniqueGems.push(gem.definition.name);
|
||||
}
|
||||
}
|
||||
return (
|
||||
this.damageDealt * 2 +
|
||||
this.hp * 10 +
|
||||
(this.goldEarned - this.goldSpent) * 3 +
|
||||
this.wavesSurvived * 100 +
|
||||
uniqueGems.length * 100
|
||||
);
|
||||
}
|
||||
|
||||
public update() {}
|
||||
}
|
||||
|
@ -4,6 +4,8 @@ import GameUIConstants from '../GameUIConstants';
|
||||
import ModalDialogBase from './ModalDialog';
|
||||
import TextInput from './TextInput';
|
||||
import MessageBox from './MessageBox';
|
||||
import { HighScoreManager } from '../game/HighScoreManager';
|
||||
import MissionStats from '../game/MissionStats';
|
||||
|
||||
export const EndGameDialogButtons = {
|
||||
Confirm: 'OK',
|
||||
@ -14,14 +16,18 @@ export default class EndGameDialog extends ModalDialogBase {
|
||||
private dialogCaption: PIXI.Text;
|
||||
private playerNameTextInput: TextInput;
|
||||
private lost: boolean;
|
||||
private highScore: HighScoreManager;
|
||||
private missionStats: MissionStats;
|
||||
|
||||
constructor(lost: boolean) {
|
||||
constructor(missionName: string, missionStats: MissionStats, lost: boolean) {
|
||||
super(
|
||||
[EndGameDialogButtons.Confirm, EndGameDialogButtons.Skip],
|
||||
EndGameDialogButtons.Confirm,
|
||||
EndGameDialogButtons.Skip
|
||||
);
|
||||
this.lost = lost;
|
||||
this.highScore = new HighScoreManager(missionName);
|
||||
this.missionStats = missionStats;
|
||||
}
|
||||
|
||||
protected override generate(): void {
|
||||
@ -31,61 +37,118 @@ export default class EndGameDialog extends ModalDialogBase {
|
||||
style: new PIXI.TextStyle({
|
||||
fill: 0xffffff,
|
||||
fontSize: 36,
|
||||
stroke: { color: 0x000000, width: 2 },
|
||||
dropShadow: {
|
||||
color: 0x000000,
|
||||
blur: 8,
|
||||
distance: 0,
|
||||
},
|
||||
}),
|
||||
});
|
||||
this.dialogContainer.addChild(this.dialogCaption);
|
||||
this.dialogCaption.anchor.set(0.5, 0.5);
|
||||
this.dialogCaption.x = this.dialogContainer.width / 2;
|
||||
this.dialogCaption.y = 50;
|
||||
this.dialogContainer.addChild(this.dialogCaption);
|
||||
}
|
||||
|
||||
protected override createDialogBackground(width: number, height: number): PIXI.Container {
|
||||
const background = new PIXI.NineSliceSprite({
|
||||
protected override createDialogBackground(): PIXI.NineSliceSprite {
|
||||
return new PIXI.NineSliceSprite({
|
||||
texture: GameAssets.EndScreenDialog,
|
||||
leftWidth: 50,
|
||||
topHeight: 100,
|
||||
rightWidth: 50,
|
||||
bottomHeight: 50,
|
||||
});
|
||||
background.x = 0;
|
||||
background.y = 0;
|
||||
background.width = width;
|
||||
background.height = height;
|
||||
return background;
|
||||
}
|
||||
|
||||
protected override createContent(): PIXI.Container {
|
||||
const container = new PIXI.Container();
|
||||
const caption = new PIXI.Text({
|
||||
text: 'Enter your name:',
|
||||
style: new PIXI.TextStyle({
|
||||
fill: 0xffffff,
|
||||
fontSize: 24,
|
||||
}),
|
||||
});
|
||||
container.addChild(caption);
|
||||
this.playerNameTextInput = new TextInput(
|
||||
GameUIConstants.MaximumPlayerNameLength * 20,
|
||||
GameUIConstants.MaximumPlayerNameLength
|
||||
);
|
||||
this.playerNameTextInput.container.y = caption.height + 10;
|
||||
const lineHeight = 35;
|
||||
const lblScore = this.createText('Mission details:', '#fee', true);
|
||||
container.addChild(lblScore);
|
||||
const stats = this.missionStats.getStats();
|
||||
const width = this.getWidth() - this.background.leftWidth - this.background.rightWidth - 20;
|
||||
const labels = [
|
||||
this.createText('HP:'),
|
||||
this.createText('Gold:'),
|
||||
this.createText('Waves Survived:'),
|
||||
this.createText('Gold Earned:'),
|
||||
this.createText('Gold Spent:'),
|
||||
this.createText('----'),
|
||||
this.createText('Score:'),
|
||||
];
|
||||
const values = [
|
||||
this.createText(stats.hp.toString(), 'yellow'),
|
||||
this.createText(stats.gold.toString(), 'yellow'),
|
||||
this.createText(stats.wavesSurvived.toString(), 'yellow'),
|
||||
this.createText(stats.goldEarned.toString(), 'yellow'),
|
||||
this.createText(stats.goldSpent.toString(), 'yellow'),
|
||||
this.createText('----', 'yellow'),
|
||||
this.createText(stats.score.toString(), 'yellow'),
|
||||
];
|
||||
const valueX = 300;
|
||||
for (let i = 0; i < labels.length; i++) {
|
||||
if (labels[i].text === '----') {
|
||||
const line = new PIXI.Graphics();
|
||||
const y = lblScore.y + lblScore.height + 10 + i * lineHeight + lineHeight / 2;
|
||||
line.moveTo(10, y);
|
||||
line.lineTo(width, y);
|
||||
line.stroke({ color: 'yellow', width: 2 });
|
||||
container.addChild(line);
|
||||
} else {
|
||||
labels[i].x = 10;
|
||||
labels[i].y = lblScore.y + lblScore.height + 10 + i * lineHeight;
|
||||
container.addChild(labels[i]);
|
||||
|
||||
values[i].x = valueX;
|
||||
values[i].y = lblScore.y + lblScore.height + 10 + i * lineHeight;
|
||||
container.addChild(values[i]);
|
||||
}
|
||||
}
|
||||
const offsetY = values[values.length - 1].y + lineHeight + 80;
|
||||
|
||||
const lblName = this.createText('Enter your name:');
|
||||
lblName.y = offsetY;
|
||||
container.addChild(lblName);
|
||||
this.playerNameTextInput = new TextInput(width, GameUIConstants.MaximumPlayerNameLength);
|
||||
this.playerNameTextInput.container.y = lblName.y + lblName.height + 10;
|
||||
container.addChild(this.playerNameTextInput.container);
|
||||
return container;
|
||||
}
|
||||
|
||||
override close(button?: string): void {
|
||||
if (button === EndGameDialogButtons.Confirm && this.playerNameTextInput.getText().length == 0) {
|
||||
MessageBox.show('Please enter your name.', ['OK']);
|
||||
if (button === EndGameDialogButtons.Confirm) {
|
||||
if (this.playerNameTextInput.getText().length == 0) {
|
||||
MessageBox.show('Please enter your name.', ['OK']);
|
||||
} else {
|
||||
this.highScore.addScore({
|
||||
playerName: this.playerNameTextInput.getText(),
|
||||
score: this.missionStats.getStats().score,
|
||||
timestamp: Date.now(),
|
||||
});
|
||||
super.close(button);
|
||||
}
|
||||
} else {
|
||||
super.close(button);
|
||||
}
|
||||
}
|
||||
|
||||
private createText(caption: string, color: string = '#fff', bold = false): PIXI.Text {
|
||||
return new PIXI.Text({
|
||||
text: caption,
|
||||
style: new PIXI.TextStyle({
|
||||
fill: color,
|
||||
fontSize: 24,
|
||||
fontWeight: bold ? 'bold' : 'normal',
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
protected override getWidth(): number | undefined {
|
||||
return GameUIConstants.StandardDialogWidth;
|
||||
return 600;
|
||||
}
|
||||
|
||||
protected override getHeight(): number | undefined {
|
||||
return GameUIConstants.StandardDialogHeight;
|
||||
return 800;
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,7 @@
|
||||
import * as PIXI from 'pixi.js';
|
||||
import GameAssets from '../Assets';
|
||||
import GameUIConstants from '../GameUIConstants';
|
||||
import ModalDialogBase from './ModalDialog';
|
||||
import TextInput from './TextInput';
|
||||
import { HighScoreManager } from '../game/HighScoreManager';
|
||||
|
||||
export const HighScoreDialogButtons = {
|
||||
Retry: 'Retry',
|
||||
@ -12,10 +11,9 @@ export const HighScoreDialogButtons = {
|
||||
|
||||
export default class HighScoreDialog extends ModalDialogBase {
|
||||
private dialogCaption: PIXI.Text;
|
||||
private playerNameTextInput: TextInput;
|
||||
private lost: boolean;
|
||||
private highScore: HighScoreManager;
|
||||
|
||||
constructor(nextMissionAvailable: boolean) {
|
||||
constructor(missionName: string, nextMissionAvailable: boolean) {
|
||||
super(
|
||||
nextMissionAvailable
|
||||
? [HighScoreDialogButtons.Retry, HighScoreDialogButtons.NextMission, HighScoreDialogButtons.MainMenu]
|
||||
@ -23,6 +21,7 @@ export default class HighScoreDialog extends ModalDialogBase {
|
||||
nextMissionAvailable ? HighScoreDialogButtons.NextMission : HighScoreDialogButtons.Retry,
|
||||
HighScoreDialogButtons.MainMenu
|
||||
);
|
||||
this.highScore = new HighScoreManager(missionName);
|
||||
}
|
||||
|
||||
protected override generate(): void {
|
||||
@ -32,47 +31,86 @@ export default class HighScoreDialog extends ModalDialogBase {
|
||||
style: new PIXI.TextStyle({
|
||||
fill: 0xffffff,
|
||||
fontSize: 36,
|
||||
stroke: { color: 0x000000, width: 2 },
|
||||
dropShadow: {
|
||||
color: 0x000000,
|
||||
blur: 8,
|
||||
distance: 0,
|
||||
},
|
||||
}),
|
||||
});
|
||||
this.dialogContainer.addChild(this.dialogCaption);
|
||||
this.dialogCaption.anchor.set(0.5, 0.5);
|
||||
this.dialogCaption.x = this.dialogContainer.width / 2;
|
||||
this.dialogCaption.y = 50;
|
||||
this.dialogContainer.addChild(this.dialogCaption);
|
||||
}
|
||||
|
||||
protected override createDialogBackground(width: number, height: number): PIXI.Container {
|
||||
const background = new PIXI.NineSliceSprite({
|
||||
protected override createDialogBackground(): PIXI.NineSliceSprite {
|
||||
return new PIXI.NineSliceSprite({
|
||||
texture: GameAssets.EndScreenDialog,
|
||||
leftWidth: 50,
|
||||
topHeight: 100,
|
||||
rightWidth: 50,
|
||||
bottomHeight: 50,
|
||||
});
|
||||
background.x = 0;
|
||||
background.y = 0;
|
||||
background.width = width;
|
||||
background.height = height;
|
||||
return background;
|
||||
}
|
||||
|
||||
protected override createContent(): PIXI.Container {
|
||||
const container = new PIXI.Container();
|
||||
const caption = new PIXI.Text({
|
||||
text: 'Leaderboard:',
|
||||
style: new PIXI.TextStyle({
|
||||
fill: 0xffffff,
|
||||
fontSize: 24,
|
||||
}),
|
||||
});
|
||||
const caption = this.createText('Mission: ' + this.highScore.missionName, '#fee', true);
|
||||
container.addChild(caption);
|
||||
const lineHeight = 35;
|
||||
const scores = this.highScore.getScores();
|
||||
while (scores.length < 10) {
|
||||
scores.push({ playerName: '---', score: 0, timestamp: 0 });
|
||||
}
|
||||
|
||||
const numberTexts = [
|
||||
this.createText('#', '#fee'),
|
||||
...scores.map((_, i) => this.createText((i + 1).toString())),
|
||||
];
|
||||
const playerTexts = [
|
||||
this.createText('Player', '#fee', true),
|
||||
...scores.map((score) => this.createText(score.playerName)),
|
||||
];
|
||||
const scoreTexts = [
|
||||
this.createText('Score', '#fee', true),
|
||||
...scores.map((score) => this.createText(score.score.toString())),
|
||||
];
|
||||
const playerX = numberTexts.reduce((maxX, text) => Math.max(maxX, text.width), 0) + 20;
|
||||
const scoreX = playerX + playerTexts.reduce((maxX, text) => Math.max(maxX, text.width), 0) + 20;
|
||||
for (let i = 0; i < playerTexts.length; i++) {
|
||||
numberTexts[i].x = 10;
|
||||
numberTexts[i].y = lineHeight + 10 + i * lineHeight;
|
||||
container.addChild(numberTexts[i]);
|
||||
|
||||
playerTexts[i].x = playerX;
|
||||
playerTexts[i].y = lineHeight + 10 + i * lineHeight;
|
||||
container.addChild(playerTexts[i]);
|
||||
|
||||
scoreTexts[i].x = scoreX;
|
||||
scoreTexts[i].y = lineHeight + 10 + i * lineHeight;
|
||||
container.addChild(scoreTexts[i]);
|
||||
}
|
||||
return container;
|
||||
}
|
||||
|
||||
private createText(caption: string, color: string = '#fff', bold = false): PIXI.Text {
|
||||
return new PIXI.Text({
|
||||
text: caption,
|
||||
style: new PIXI.TextStyle({
|
||||
fill: color,
|
||||
fontSize: 24,
|
||||
fontWeight: bold ? 'bold' : 'normal',
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
protected override getWidth(): number | undefined {
|
||||
return GameUIConstants.StandardDialogWidth;
|
||||
return 600;
|
||||
}
|
||||
|
||||
protected override getHeight(): number | undefined {
|
||||
return GameUIConstants.StandardDialogHeight;
|
||||
return 800;
|
||||
}
|
||||
}
|
||||
|
@ -8,15 +8,12 @@ import KeyboardManager from '../game/KeyboardManager';
|
||||
|
||||
export default abstract class ModalDialogBase extends GuiObject {
|
||||
protected overlay: PIXI.Graphics;
|
||||
protected dialogPadding = 40;
|
||||
protected contentPadding = 10;
|
||||
protected buttonPadding = 10;
|
||||
protected buttonAreaHeight = 40;
|
||||
protected buttonHeight = 60;
|
||||
protected buttonHeight = 65;
|
||||
protected buttonCaptions: string[];
|
||||
protected buttons: Button[] = [];
|
||||
protected dialogContent: PIXI.Container;
|
||||
protected dialogContainer: PIXI.Container;
|
||||
protected background: PIXI.NineSliceSprite;
|
||||
|
||||
private generated = false;
|
||||
private escapeKeyButton?: string | null;
|
||||
@ -43,8 +40,14 @@ export default abstract class ModalDialogBase extends GuiObject {
|
||||
*/
|
||||
public show(): Promise<string | null> {
|
||||
this.generate();
|
||||
const dialogBounds = `x: ${Math.round(this.dialogContainer.x)}, y: ${Math.round(
|
||||
this.dialogContainer.y
|
||||
)}, width: ${Math.round(this.dialogContainer.width)}, height: ${Math.round(this.dialogContainer.height)}`;
|
||||
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(content: ${this.dialogContainer.width}x${this.dialogContainer.height}, buttons: ${this.buttonCaptions})`
|
||||
`ModalDialogBase.show(dialog: ${dialogBounds}, content: ${contentBounds}, buttons: ${this.buttonCaptions})`
|
||||
);
|
||||
return new Promise((resolve, reject) => {
|
||||
Engine.app.stage.addChild(this.container);
|
||||
@ -69,19 +72,14 @@ export default abstract class ModalDialogBase extends GuiObject {
|
||||
/**
|
||||
* Creates dialog background.
|
||||
*/
|
||||
protected createDialogBackground(width: number, height: number): PIXI.Container {
|
||||
const background = new PIXI.NineSliceSprite({
|
||||
protected createDialogBackground(): PIXI.NineSliceSprite {
|
||||
return new PIXI.NineSliceSprite({
|
||||
texture: GameAssets.Frame04Texture,
|
||||
leftWidth: 60,
|
||||
topHeight: 60,
|
||||
rightWidth: 60,
|
||||
bottomHeight: 60,
|
||||
});
|
||||
background.x = 0;
|
||||
background.y = 0;
|
||||
background.width = width;
|
||||
background.height = height;
|
||||
return background;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -110,23 +108,31 @@ export default abstract class ModalDialogBase extends GuiObject {
|
||||
// Prevent interaction with the underlying scene
|
||||
this.overlay.interactive = true;
|
||||
this.container.addChild(this.overlay);
|
||||
|
||||
this.dialogContent = this.createContent();
|
||||
const buttonDefs = this.buttonCaptions.map((btnCaption) => ({
|
||||
caption: btnCaption,
|
||||
width: btnCaption.length * 16 + 40,
|
||||
width: btnCaption.length * 14 + 60,
|
||||
height: this.buttonHeight,
|
||||
click: () => this.close(btnCaption),
|
||||
}));
|
||||
|
||||
this.background = this.createDialogBackground();
|
||||
this.dialogContent = this.createContent();
|
||||
|
||||
let buttonTotalWidth = 0;
|
||||
for (const buttonDef of buttonDefs) {
|
||||
if (buttonTotalWidth > 0) buttonTotalWidth += this.buttonPadding;
|
||||
if (buttonTotalWidth > 0) buttonTotalWidth += 10;
|
||||
buttonTotalWidth += buttonDef.width;
|
||||
}
|
||||
const contentWidth = this.dialogContent.width + this.contentPadding * 2;
|
||||
const contentHeight = this.dialogContent.height + this.contentPadding * 2;
|
||||
let width = this.getWidth() || Math.max(buttonTotalWidth, contentWidth) + this.dialogPadding * 2;
|
||||
let height = this.getHeight() || contentHeight + this.buttonAreaHeight + this.dialogPadding * 2;
|
||||
const buttonAreaHeight = this.buttonCaptions.length > 0 ? this.buttonHeight + 10 : 0;
|
||||
|
||||
let width =
|
||||
this.getWidth() ||
|
||||
Math.max(buttonTotalWidth, this.dialogContent.width) +
|
||||
this.background.leftWidth +
|
||||
this.background.rightWidth;
|
||||
let height =
|
||||
this.getHeight() ||
|
||||
this.dialogContent.height + buttonAreaHeight + this.background.topHeight + this.background.bottomHeight;
|
||||
const modalBounds = new PIXI.Rectangle(
|
||||
Engine.app.canvas.width / 2 - width / 2,
|
||||
Engine.app.canvas.height / 2 - height / 2,
|
||||
@ -137,14 +143,24 @@ export default abstract class ModalDialogBase extends GuiObject {
|
||||
this.dialogContainer = new PIXI.Container();
|
||||
this.dialogContainer.x = modalBounds.x;
|
||||
this.dialogContainer.y = modalBounds.y;
|
||||
this.background.width = width;
|
||||
this.background.height = height;
|
||||
this.dialogContainer.addChild(this.background);
|
||||
|
||||
const background = this.createDialogBackground(modalBounds.width, modalBounds.height);
|
||||
this.dialogContainer.addChild(background);
|
||||
|
||||
if (this.dialogContent.width < modalBounds.width)
|
||||
if (this.dialogContent.width < modalBounds.width) {
|
||||
this.dialogContent.x = modalBounds.width / 2 - this.dialogContent.width / 2;
|
||||
if (this.dialogContent.height < modalBounds.height - this.buttonAreaHeight)
|
||||
this.dialogContent.y = (modalBounds.height - this.buttonAreaHeight) / 2 - this.dialogContent.height / 2;
|
||||
}
|
||||
if (
|
||||
this.dialogContent.height <
|
||||
modalBounds.height - buttonAreaHeight - this.background.topHeight - this.background.bottomHeight
|
||||
) {
|
||||
this.dialogContent.y =
|
||||
this.background.topHeight +
|
||||
(modalBounds.height - buttonAreaHeight - this.background.topHeight - this.background.bottomHeight) / 2 -
|
||||
this.dialogContent.height / 2;
|
||||
} else {
|
||||
this.dialogContent.y = this.background.topHeight;
|
||||
}
|
||||
this.dialogContainer.addChild(this.dialogContent);
|
||||
|
||||
let buttonXPos = modalBounds.width / 2 - buttonTotalWidth / 2;
|
||||
@ -152,7 +168,7 @@ export default abstract class ModalDialogBase extends GuiObject {
|
||||
const button = new Button(
|
||||
new PIXI.Rectangle(
|
||||
buttonXPos,
|
||||
modalBounds.height - this.buttonAreaHeight - this.dialogPadding,
|
||||
modalBounds.height - this.buttonHeight - this.background.bottomHeight,
|
||||
buttonDef.width,
|
||||
buttonDef.height
|
||||
),
|
||||
@ -162,7 +178,7 @@ export default abstract class ModalDialogBase extends GuiObject {
|
||||
button.onClick = buttonDef.click;
|
||||
this.buttons.push(button);
|
||||
this.dialogContainer.addChild(button.container);
|
||||
buttonXPos += buttonDef.width + this.buttonPadding;
|
||||
buttonXPos += buttonDef.width + 10;
|
||||
}
|
||||
this.container.addChild(this.dialogContainer);
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ export default class TextInput extends GuiObject {
|
||||
this.backgroundSprite.x = 0;
|
||||
this.backgroundSprite.y = 0;
|
||||
this.backgroundSprite.width = width;
|
||||
this.backgroundSprite.height = 60;
|
||||
this.backgroundSprite.height = 80;
|
||||
this.container.addChild(this.backgroundSprite);
|
||||
this.text = new PIXI.Text({
|
||||
text: '',
|
||||
@ -36,8 +36,8 @@ export default class TextInput extends GuiObject {
|
||||
fontSize: 24,
|
||||
}),
|
||||
});
|
||||
this.text.x = 20;
|
||||
this.text.y = 20;
|
||||
this.text.x = 30;
|
||||
this.text.y = 25;
|
||||
this.container.addChild(this.text);
|
||||
this.keyboardManagerUnsubscribe = KeyboardManager.onKeyPressed(this.onKeyPress.bind(this));
|
||||
}
|
||||
|
@ -245,15 +245,17 @@ export class GameScene extends Scene {
|
||||
}
|
||||
|
||||
private async ShowEndgameDialog(lost) {
|
||||
const endGameDialog = new EndGameDialog(lost);
|
||||
const endGameDialog = new EndGameDialog(this.mission.name, this.MissionStats, lost);
|
||||
await endGameDialog.show();
|
||||
const highScore = new HighScoreDialog(this.missionIndex + 1 < GameAssets.Missions.length);
|
||||
const highScore = new HighScoreDialog(this.mission.name, this.missionIndex + 1 < GameAssets.Missions.length);
|
||||
const result = await highScore.show();
|
||||
if (result === HighScoreDialogButtons.MainMenu) {
|
||||
this.ReturnToMain();
|
||||
} else if (result === HighScoreDialogButtons.NextMission) {
|
||||
this.destroy();
|
||||
Engine.GameMaster.changeScene(new GameScene(GameAssets.Missions[this.missionIndex + 1].name));
|
||||
} else if (result === HighScoreDialogButtons.Retry) {
|
||||
this.destroy();
|
||||
Engine.GameMaster.changeScene(new GameScene(this.mission.name));
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user