Title Rework
This commit is contained in:
parent
fbf60877ef
commit
e83d3c8929
Binary file not shown.
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 243 KiB |
Binary file not shown.
After Width: | Height: | Size: 885 B |
Binary file not shown.
After Width: | Height: | Size: 918 B |
Binary file not shown.
After Width: | Height: | Size: 183 B |
|
@ -40,6 +40,8 @@ export class LoadingScene extends SceneBase {
|
||||||
this.loadImage("loading_bg", "arenas");
|
this.loadImage("loading_bg", "arenas");
|
||||||
this.loadImage("logo", "");
|
this.loadImage("logo", "");
|
||||||
this.loadImage("pride-update", "events");
|
this.loadImage("pride-update", "events");
|
||||||
|
this.loadImage("ivy-sprite", "");
|
||||||
|
this.loadImage("finn-sprite", "");
|
||||||
|
|
||||||
// Load menu images
|
// Load menu images
|
||||||
this.loadAtlas("bg", "ui");
|
this.loadAtlas("bg", "ui");
|
||||||
|
@ -53,6 +55,7 @@ export class LoadingScene extends SceneBase {
|
||||||
this.loadImage(`window_${w}${getWindowVariantSuffix(wv)}`, "ui/windows");
|
this.loadImage(`window_${w}${getWindowVariantSuffix(wv)}`, "ui/windows");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.loadImage("window_speech", "");
|
||||||
this.loadImage("discord", "ui");
|
this.loadImage("discord", "ui");
|
||||||
this.loadImage("reddit", "ui");
|
this.loadImage("reddit", "ui");
|
||||||
this.loadImage("github", "ui");
|
this.loadImage("github", "ui");
|
||||||
|
|
|
@ -32,8 +32,8 @@ export const settings: SimpleTranslationEntries = {
|
||||||
"language": "Language",
|
"language": "Language",
|
||||||
"change": "Change",
|
"change": "Change",
|
||||||
"uiTheme": "UI Theme",
|
"uiTheme": "UI Theme",
|
||||||
"default": "Default",
|
"default": "Gen V",
|
||||||
"legacy": "Legacy",
|
"legacy": "Gen III",
|
||||||
"windowType": "Window Type",
|
"windowType": "Window Type",
|
||||||
"moneyFormat": "Money Format",
|
"moneyFormat": "Money Format",
|
||||||
"damageNumbers": "Damage Numbers",
|
"damageNumbers": "Damage Numbers",
|
||||||
|
|
|
@ -199,15 +199,6 @@ export class TitlePhase extends Phase {
|
||||||
|
|
||||||
showOptions(): OptionSelectConfig {
|
showOptions(): OptionSelectConfig {
|
||||||
const options: OptionSelectItem[] = [];
|
const options: OptionSelectItem[] = [];
|
||||||
// if (loggedInUser.lastSessionSlot > -1) {
|
|
||||||
// options.push({
|
|
||||||
// label: i18next.t("menu:continue"),
|
|
||||||
// handler: () => {
|
|
||||||
// this.loadSaveSlot(this.lastSessionData ? -1 : loggedInUser.lastSessionSlot);
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
options.push({
|
options.push({
|
||||||
label: i18next.t("menu:loadGame"),
|
label: i18next.t("menu:loadGame"),
|
||||||
handler: () => this.loadGameHandler(),
|
handler: () => this.loadGameHandler(),
|
||||||
|
@ -232,9 +223,9 @@ export class TitlePhase extends Phase {
|
||||||
return {
|
return {
|
||||||
options: options,
|
options: options,
|
||||||
noCancel: true,
|
noCancel: true,
|
||||||
xOffset: 220,
|
xOffset: 216,
|
||||||
yOffset: 13,
|
yOffset: 1,
|
||||||
noBg: true,
|
noBg: true
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -389,7 +380,7 @@ export class TitlePhase extends Phase {
|
||||||
} else {
|
} else {
|
||||||
this.scene.playBgm();
|
this.scene.playBgm();
|
||||||
}
|
}
|
||||||
|
this.scene.ui.getMessageHandler().bg.setVisible(true);
|
||||||
this.scene.pushPhase(new EncounterPhase(this.scene, this.loaded));
|
this.scene.pushPhase(new EncounterPhase(this.scene, this.loaded));
|
||||||
|
|
||||||
if (this.loaded) {
|
if (this.loaded) {
|
||||||
|
|
|
@ -77,13 +77,14 @@ export class TimedEventDisplay extends Phaser.GameObjects.Container {
|
||||||
}
|
}
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
this.banner = new Phaser.GameObjects.Image(this.scene, 0, 0, this.event.bannerFilename);
|
this.banner = new Phaser.GameObjects.Image(this.scene, 3, -1, this.event.bannerFilename);
|
||||||
this.banner.setName("img-event-banner");
|
this.banner.setName("img-event-banner");
|
||||||
this.banner.setOrigin(0, 0);
|
this.banner.setOrigin(0, 0);
|
||||||
this.banner.setScale(0.05);
|
this.banner.setScale(0.10);
|
||||||
|
|
||||||
this.bannerShadow = new Phaser.GameObjects.Rectangle(
|
this.bannerShadow = new Phaser.GameObjects.Rectangle(
|
||||||
this.scene,
|
this.scene,
|
||||||
this.banner.x - 2,
|
this.banner.x + 2,
|
||||||
this.banner.y + 2,
|
this.banner.y + 2,
|
||||||
this.banner.width * this.banner.scaleX,
|
this.banner.width * this.banner.scaleX,
|
||||||
this.banner.height * this.banner.scaleY,
|
this.banner.height * this.banner.scaleY,
|
||||||
|
@ -92,15 +93,16 @@ export class TimedEventDisplay extends Phaser.GameObjects.Container {
|
||||||
this.bannerShadow.setName("rect-event-banner-shadow");
|
this.bannerShadow.setName("rect-event-banner-shadow");
|
||||||
this.bannerShadow.setAlpha(0.5);
|
this.bannerShadow.setAlpha(0.5);
|
||||||
this.bannerShadow.setOrigin(0,0);
|
this.bannerShadow.setOrigin(0,0);
|
||||||
|
|
||||||
this.eventTimerText = addTextObject(
|
this.eventTimerText = addTextObject(
|
||||||
this.scene,
|
this.scene,
|
||||||
this.banner.x + 3,
|
this.banner.x,
|
||||||
this.banner.y - 10,
|
this.banner.y + 49,
|
||||||
this.timeToGo(this.event.endDate),
|
this.timeToGo(this.event.endDate),
|
||||||
TextStyle.BATTLE_INFO
|
TextStyle.SUMMARY_ALT,
|
||||||
|
{ fontSize: 72 }
|
||||||
);
|
);
|
||||||
this.eventTimerText.setName("text-event-timer");
|
this.eventTimerText.setName("text-event-timer");
|
||||||
this.eventTimerText.setScale(0.15);
|
|
||||||
this.eventTimerText.setOrigin(0,0);
|
this.eventTimerText.setOrigin(0,0);
|
||||||
|
|
||||||
this.add([this.eventTimerText, this.bannerShadow, this.banner]);
|
this.add([this.eventTimerText, this.bannerShadow, this.banner]);
|
||||||
|
|
|
@ -16,6 +16,7 @@ export interface OptionSelectConfig {
|
||||||
supportHover?: boolean;
|
supportHover?: boolean;
|
||||||
noBg?: boolean;
|
noBg?: boolean;
|
||||||
textStyle?: TextStyle;
|
textStyle?: TextStyle;
|
||||||
|
extraStyleOptions?: Phaser.Types.GameObjects.Text.TextStyle;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OptionSelectItem {
|
export interface OptionSelectItem {
|
||||||
|
@ -81,12 +82,18 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler {
|
||||||
Phaser.Actions.Call(this.optionSelectText, (text) => text.destroy(), this);
|
Phaser.Actions.Call(this.optionSelectText, (text) => text.destroy(), this);
|
||||||
}
|
}
|
||||||
const optionText = this.config?.options.length > this.config?.maxOptions ? this.getOptionsWithScroll() : options;
|
const optionText = this.config?.options.length > this.config?.maxOptions ? this.getOptionsWithScroll() : options;
|
||||||
|
const optionTextStyle = {
|
||||||
|
maxLines: options.length, lineSpacing: 12
|
||||||
|
};
|
||||||
|
if (this.config.extraStyleOptions) {
|
||||||
|
Object.assign(optionTextStyle, this.config.extraStyleOptions);
|
||||||
|
}
|
||||||
this.optionSelectText = [];
|
this.optionSelectText = [];
|
||||||
this.optionSelectText = optionText.map(o => {
|
this.optionSelectText = optionText.map(o => {
|
||||||
const ret = addTextObject(this.scene, 0, 0,
|
const ret = addTextObject(this.scene, 0, 0,
|
||||||
o.item ? ` ${o.label}` : o.label,
|
o.item ? ` ${o.label}` : o.label,
|
||||||
( this.config?.textStyle ?? TextStyle.WINDOW),
|
( this.config?.textStyle ?? TextStyle.WINDOW),
|
||||||
{ maxLines: options.length, lineSpacing: 12 }
|
optionTextStyle
|
||||||
);
|
);
|
||||||
ret.setName(`text-${o.label}`);
|
ret.setName(`text-${o.label}`);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
export class SpeechBubble extends Phaser.GameObjects.Container {
|
||||||
|
private bubble: Phaser.GameObjects.NineSlice;
|
||||||
|
private trail: Phaser.GameObjects.Triangle;
|
||||||
|
private trailStrokes: Phaser.GameObjects.Line[];
|
||||||
|
private text: Phaser.GameObjects.Text;
|
||||||
|
|
||||||
|
constructor(scene, x, y, text?: Phaser.GameObjects.Text) {
|
||||||
|
super(scene, x, y);
|
||||||
|
|
||||||
|
this.text = text;
|
||||||
|
this.text.setPadding(0, 0);
|
||||||
|
this.text.setPosition(-(this.text.width / 12), -(this.text.height / 12));
|
||||||
|
|
||||||
|
this.bubble = new Phaser.GameObjects.NineSlice(
|
||||||
|
scene,
|
||||||
|
0, 0,
|
||||||
|
"window_speech", null,
|
||||||
|
(this.text.width / 6) + 18, 100);
|
||||||
|
this.bubble.setName("speech-bubble");
|
||||||
|
|
||||||
|
this.trail = new Phaser.GameObjects.Triangle(
|
||||||
|
scene,
|
||||||
|
0, 0,
|
||||||
|
-51, 21,
|
||||||
|
-51, 11,
|
||||||
|
-39, 13,
|
||||||
|
0xffffff,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
this.trail.setName("speech-bubble-trail");
|
||||||
|
|
||||||
|
this.trailStrokes = [];
|
||||||
|
this.trailStrokes.push(
|
||||||
|
new Phaser.GameObjects.Line(
|
||||||
|
scene,
|
||||||
|
0, 0,
|
||||||
|
-57, 19,
|
||||||
|
-57, 13,
|
||||||
|
0xa6a6a6, 1
|
||||||
|
),
|
||||||
|
new Phaser.GameObjects.Line(
|
||||||
|
scene,
|
||||||
|
0, 0,
|
||||||
|
-52, 19,
|
||||||
|
-41, 13,
|
||||||
|
0xa6a6a6, 1
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
this.add([this.bubble, this.trail, ...this.trailStrokes, this.text]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -27,10 +27,12 @@ export default class AbstractSettingsUiHandler extends UiHandler {
|
||||||
|
|
||||||
private settingLabels: Phaser.GameObjects.Text[];
|
private settingLabels: Phaser.GameObjects.Text[];
|
||||||
private optionValueLabels: Phaser.GameObjects.Text[][];
|
private optionValueLabels: Phaser.GameObjects.Text[][];
|
||||||
|
private reloadRequiredText: Phaser.GameObjects.Text;
|
||||||
|
|
||||||
protected navigationIcons: InputsIcons;
|
protected navigationIcons: InputsIcons;
|
||||||
|
|
||||||
private cursorObj: Phaser.GameObjects.NineSlice;
|
private cursorObj: Phaser.GameObjects.NineSlice;
|
||||||
|
private actionGroup: Phaser.GameObjects.Group;
|
||||||
|
|
||||||
private reloadSettings: Array<Setting>;
|
private reloadSettings: Array<Setting>;
|
||||||
private reloadRequired: boolean;
|
private reloadRequired: boolean;
|
||||||
|
@ -39,6 +41,7 @@ export default class AbstractSettingsUiHandler extends UiHandler {
|
||||||
protected title: string;
|
protected title: string;
|
||||||
protected settings: Array<Setting>;
|
protected settings: Array<Setting>;
|
||||||
protected localStorageKey: string;
|
protected localStorageKey: string;
|
||||||
|
protected actionButtons: boolean = true;
|
||||||
|
|
||||||
constructor(scene: BattleScene, mode?: Mode) {
|
constructor(scene: BattleScene, mode?: Mode) {
|
||||||
super(scene, mode);
|
super(scene, mode);
|
||||||
|
@ -53,6 +56,8 @@ export default class AbstractSettingsUiHandler extends UiHandler {
|
||||||
setup() {
|
setup() {
|
||||||
const ui = this.getUi();
|
const ui = this.getUi();
|
||||||
|
|
||||||
|
this.actionGroup = new Phaser.GameObjects.Group(this.scene);
|
||||||
|
|
||||||
this.settingsContainer = this.scene.add.container(1, -(this.scene.game.canvas.height / 6) + 1);
|
this.settingsContainer = this.scene.add.container(1, -(this.scene.game.canvas.height / 6) + 1);
|
||||||
this.settingsContainer.setName(`settings-${this.title}`);
|
this.settingsContainer.setName(`settings-${this.title}`);
|
||||||
this.settingsContainer.setInteractive(new Phaser.Geom.Rectangle(0, 0, this.scene.game.canvas.width / 6, this.scene.game.canvas.height / 6 - 20), Phaser.Geom.Rectangle.Contains);
|
this.settingsContainer.setInteractive(new Phaser.Geom.Rectangle(0, 0, this.scene.game.canvas.width / 6, this.scene.game.canvas.height / 6 - 20), Phaser.Geom.Rectangle.Contains);
|
||||||
|
@ -61,7 +66,12 @@ export default class AbstractSettingsUiHandler extends UiHandler {
|
||||||
|
|
||||||
this.navigationContainer = new NavigationMenu(this.scene, 0, 0);
|
this.navigationContainer = new NavigationMenu(this.scene, 0, 0);
|
||||||
|
|
||||||
this.optionsBg = addWindow(this.scene, 0, this.navigationContainer.height, (this.scene.game.canvas.width / 6) - 2, (this.scene.game.canvas.height / 6) - 16 - this.navigationContainer.height - 2);
|
this.optionsBg = addWindow(
|
||||||
|
this.scene, 0,
|
||||||
|
this.navigationContainer.height - 1,
|
||||||
|
(this.scene.game.canvas.width / 6) - 2,
|
||||||
|
(this.scene.game.canvas.height / 6) - 16 - this.navigationContainer.height - 2
|
||||||
|
);
|
||||||
this.optionsBg.setName("window-options-bg");
|
this.optionsBg.setName("window-options-bg");
|
||||||
this.optionsBg.setOrigin(0, 0);
|
this.optionsBg.setOrigin(0, 0);
|
||||||
|
|
||||||
|
@ -69,23 +79,35 @@ export default class AbstractSettingsUiHandler extends UiHandler {
|
||||||
actionsBg.setOrigin(0, 0);
|
actionsBg.setOrigin(0, 0);
|
||||||
|
|
||||||
const iconAction = this.scene.add.sprite(0, 0, "keyboard");
|
const iconAction = this.scene.add.sprite(0, 0, "keyboard");
|
||||||
|
iconAction.setName("icon-action");
|
||||||
iconAction.setOrigin(0, -0.1);
|
iconAction.setOrigin(0, -0.1);
|
||||||
iconAction.setPositionRelative(actionsBg, this.navigationContainer.width - 32, 4);
|
iconAction.setPositionRelative(actionsBg, this.navigationContainer.width - 32, 4);
|
||||||
this.navigationIcons["BUTTON_ACTION"] = iconAction;
|
this.navigationIcons["BUTTON_ACTION"] = iconAction;
|
||||||
|
|
||||||
const actionText = addTextObject(this.scene, 0, 0, i18next.t("settings:action"), TextStyle.SETTINGS_LABEL);
|
const actionText = addTextObject(this.scene, 0, 0, i18next.t("settings:action"), TextStyle.SETTINGS_LABEL);
|
||||||
|
actionText.setName("text-action");
|
||||||
actionText.setOrigin(0, 0.15);
|
actionText.setOrigin(0, 0.15);
|
||||||
actionText.setPositionRelative(iconAction, -actionText.width/6-2, 0);
|
actionText.setPositionRelative(iconAction, -actionText.width/6-2, 0);
|
||||||
|
|
||||||
const iconCancel = this.scene.add.sprite(0, 0, "keyboard");
|
const iconCancel = this.scene.add.sprite(0, 0, "keyboard");
|
||||||
|
iconCancel.setName("icon-cancel");
|
||||||
iconCancel.setOrigin(0, -0.1);
|
iconCancel.setOrigin(0, -0.1);
|
||||||
iconCancel.setPositionRelative(actionsBg, this.navigationContainer.width - 100, 4);
|
iconCancel.setPositionRelative(actionsBg, this.navigationContainer.width - 100, 4);
|
||||||
this.navigationIcons["BUTTON_CANCEL"] = iconCancel;
|
this.navigationIcons["BUTTON_CANCEL"] = iconCancel;
|
||||||
|
|
||||||
const cancelText = addTextObject(this.scene, 0, 0, i18next.t("settings:back"), TextStyle.SETTINGS_LABEL);
|
const cancelText = addTextObject(this.scene, 0, 0, i18next.t("settings:back"), TextStyle.SETTINGS_LABEL);
|
||||||
|
cancelText.setName("text-cancel");
|
||||||
cancelText.setOrigin(0, 0.15);
|
cancelText.setOrigin(0, 0.15);
|
||||||
cancelText.setPositionRelative(iconCancel, -cancelText.width/6-2, 0);
|
cancelText.setPositionRelative(iconCancel, -cancelText.width/6-2, 0);
|
||||||
|
|
||||||
|
this.reloadRequiredText = addTextObject(
|
||||||
|
this.scene,
|
||||||
|
8, 159,
|
||||||
|
`* ${i18next.t("settings:requireReload")}`,
|
||||||
|
TextStyle.SETTINGS_LABEL
|
||||||
|
);
|
||||||
|
this.reloadRequiredText.setName("reload-required");
|
||||||
|
|
||||||
this.optionsContainer = this.scene.add.container(0, 0);
|
this.optionsContainer = this.scene.add.container(0, 0);
|
||||||
|
|
||||||
this.settingLabels = [];
|
this.settingLabels = [];
|
||||||
|
@ -97,7 +119,7 @@ export default class AbstractSettingsUiHandler extends UiHandler {
|
||||||
.forEach((setting, s) => {
|
.forEach((setting, s) => {
|
||||||
let settingName = setting.label;
|
let settingName = setting.label;
|
||||||
if (setting?.requireReload) {
|
if (setting?.requireReload) {
|
||||||
settingName += ` (${i18next.t("settings:requireReload")})`;
|
settingName += " *";
|
||||||
}
|
}
|
||||||
|
|
||||||
this.settingLabels[s] = addTextObject(this.scene, 8, 28 + s * 16, settingName, TextStyle.SETTINGS_LABEL);
|
this.settingLabels[s] = addTextObject(this.scene, 8, 28 + s * 16, settingName, TextStyle.SETTINGS_LABEL);
|
||||||
|
@ -138,6 +160,11 @@ export default class AbstractSettingsUiHandler extends UiHandler {
|
||||||
this.settingsContainer.add(iconCancel);
|
this.settingsContainer.add(iconCancel);
|
||||||
this.settingsContainer.add(actionText);
|
this.settingsContainer.add(actionText);
|
||||||
this.settingsContainer.add(cancelText);
|
this.settingsContainer.add(cancelText);
|
||||||
|
this.settingsContainer.add(this.reloadRequiredText);
|
||||||
|
|
||||||
|
this.actionGroup.addMultiple([
|
||||||
|
iconAction, iconCancel, actionText, cancelText
|
||||||
|
]);
|
||||||
|
|
||||||
ui.add(this.settingsContainer);
|
ui.add(this.settingsContainer);
|
||||||
|
|
||||||
|
@ -185,6 +212,8 @@ export default class AbstractSettingsUiHandler extends UiHandler {
|
||||||
this.settings.forEach((setting, s) => this.setOptionCursor(s, settings.hasOwnProperty(setting.key) ? settings[setting.key] : this.settings[s].default));
|
this.settings.forEach((setting, s) => this.setOptionCursor(s, settings.hasOwnProperty(setting.key) ? settings[setting.key] : this.settings[s].default));
|
||||||
|
|
||||||
this.settingsContainer.setVisible(true);
|
this.settingsContainer.setVisible(true);
|
||||||
|
Phaser.Actions.SetVisible(this.actionGroup.getChildren(), this.actionButtons);
|
||||||
|
this.reloadRequiredText.setVisible(!this.actionButtons);
|
||||||
this.setCursor(0);
|
this.setCursor(0);
|
||||||
|
|
||||||
this.getUi().moveTo(this.settingsContainer, this.getUi().length - 1);
|
this.getUi().moveTo(this.settingsContainer, this.getUi().length - 1);
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { Mode } from "../ui";
|
||||||
"#app/inputs-controller.js";
|
"#app/inputs-controller.js";
|
||||||
import AbstractSettingsUiHandler from "./abstract-settings-ui-handler";
|
import AbstractSettingsUiHandler from "./abstract-settings-ui-handler";
|
||||||
import { Setting, SettingKeys, SettingType } from "#app/system/settings/settings";
|
import { Setting, SettingKeys, SettingType } from "#app/system/settings/settings";
|
||||||
|
import TitleUiHandler from "#app/ui/title-ui-handler.js";
|
||||||
|
|
||||||
export default class SettingsDisplayUiHandler extends AbstractSettingsUiHandler {
|
export default class SettingsDisplayUiHandler extends AbstractSettingsUiHandler {
|
||||||
/**
|
/**
|
||||||
|
@ -15,6 +16,7 @@ export default class SettingsDisplayUiHandler extends AbstractSettingsUiHandler
|
||||||
super(scene, mode);
|
super(scene, mode);
|
||||||
this.title = "Display";
|
this.title = "Display";
|
||||||
this.settings = Setting.filter(s => s.type === SettingType.DISPLAY);
|
this.settings = Setting.filter(s => s.type === SettingType.DISPLAY);
|
||||||
|
this.actionButtons = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update to current language from default value.
|
* Update to current language from default value.
|
||||||
|
@ -90,4 +92,9 @@ export default class SettingsDisplayUiHandler extends AbstractSettingsUiHandler
|
||||||
|
|
||||||
this.localStorageKey = "settings";
|
this.localStorageKey = "settings";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clear() {
|
||||||
|
super.clear();
|
||||||
|
(this.getUi().handlers[Mode.TITLE] as TitleUiHandler).update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,5 +15,6 @@ export default class SettingsUiHandler extends AbstractSettingsUiHandler {
|
||||||
this.title = "General";
|
this.title = "General";
|
||||||
this.settings = Setting.filter(s => s.type === SettingType.GENERAL);
|
this.settings = Setting.filter(s => s.type === SettingType.GENERAL);
|
||||||
this.localStorageKey = "settings";
|
this.localStorageKey = "settings";
|
||||||
|
this.actionButtons = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,8 +122,8 @@ function getTextStyleOptions(style: TextStyle, uiTheme: UiTheme, extraStyleOptio
|
||||||
case TextStyle.MONEY:
|
case TextStyle.MONEY:
|
||||||
case TextStyle.TOOLTIP_TITLE:
|
case TextStyle.TOOLTIP_TITLE:
|
||||||
styleOptions.fontSize = defaultFontSize - 24;
|
styleOptions.fontSize = defaultFontSize - 24;
|
||||||
shadowXpos = 3.5;
|
shadowXpos = 3;
|
||||||
shadowYpos = 3.5;
|
shadowYpos = 3;
|
||||||
break;
|
break;
|
||||||
case TextStyle.PARTY:
|
case TextStyle.PARTY:
|
||||||
case TextStyle.PARTY_RED:
|
case TextStyle.PARTY_RED:
|
||||||
|
@ -146,8 +146,11 @@ function getTextStyleOptions(style: TextStyle, uiTheme: UiTheme, extraStyleOptio
|
||||||
|
|
||||||
if (extraStyleOptions) {
|
if (extraStyleOptions) {
|
||||||
if (extraStyleOptions.fontSize) {
|
if (extraStyleOptions.fontSize) {
|
||||||
const sizeRatio = parseInt(extraStyleOptions.fontSize.toString().slice(0, -2)) / parseInt(styleOptions.fontSize.toString().slice(0, -2));
|
const currentSize = typeof styleOptions.fontSize === "string" ? Number(styleOptions.fontSize.slice(0, -2)) : styleOptions.fontSize;
|
||||||
|
const newSize = typeof extraStyleOptions.fontSize === "string" ? Number(extraStyleOptions.fontSize.slice(0, -2)) : extraStyleOptions.fontSize;
|
||||||
|
const sizeRatio = newSize / currentSize;
|
||||||
shadowXpos *= sizeRatio;
|
shadowXpos *= sizeRatio;
|
||||||
|
shadowYpos *= sizeRatio;
|
||||||
}
|
}
|
||||||
styleOptions = Object.assign(styleOptions, extraStyleOptions);
|
styleOptions = Object.assign(styleOptions, extraStyleOptions);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,15 +6,24 @@ import { TextStyle, addTextObject } from "./text";
|
||||||
import { getSplashMessages } from "../data/splash-messages";
|
import { getSplashMessages } from "../data/splash-messages";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import { TimedEventDisplay } from "#app/timed-event-manager.js";
|
import { TimedEventDisplay } from "#app/timed-event-manager.js";
|
||||||
|
import { Color } from "#app/enums/color.js";
|
||||||
|
import { PlayerGender } from "#app/enums/player-gender.js";
|
||||||
|
import { SpeechBubble } from "#app/ui/components/speech-bubble.js";
|
||||||
|
|
||||||
export default class TitleUiHandler extends OptionSelectUiHandler {
|
export default class TitleUiHandler extends OptionSelectUiHandler {
|
||||||
private titleContainer: Phaser.GameObjects.Container;
|
private titleContainer: Phaser.GameObjects.Container;
|
||||||
private logo: Phaser.GameObjects.Image;
|
private logo: Phaser.GameObjects.Image;
|
||||||
private playerCountLabel: Phaser.GameObjects.Text;
|
private playerCountLabel: Phaser.GameObjects.Text;
|
||||||
|
private playerCountWidth: number;
|
||||||
private splashMessage: string;
|
private splashMessage: string;
|
||||||
private splashMessageText: Phaser.GameObjects.Text;
|
private splashMessageText: Phaser.GameObjects.Text;
|
||||||
private eventDisplay: TimedEventDisplay;
|
private eventDisplay: TimedEventDisplay;
|
||||||
private iconContainer: TitleIcons;
|
private iconContainer: TitleIcons;
|
||||||
|
private menuOverlay: Phaser.GameObjects.Rectangle;
|
||||||
|
private rivalSprite: Phaser.GameObjects.Sprite;
|
||||||
|
private spriteShadow: Phaser.GameObjects.Ellipse;
|
||||||
|
private bubble: SpeechBubble;
|
||||||
|
private rivalText: Phaser.GameObjects.Text;
|
||||||
|
|
||||||
private titleStatsTimer: NodeJS.Timeout;
|
private titleStatsTimer: NodeJS.Timeout;
|
||||||
|
|
||||||
|
@ -27,30 +36,93 @@ export default class TitleUiHandler extends OptionSelectUiHandler {
|
||||||
|
|
||||||
const ui = this.getUi();
|
const ui = this.getUi();
|
||||||
|
|
||||||
|
const overlayColor = this.scene.uiTheme ? Color.OFF_WHITE : Color.DARK_GREY;
|
||||||
|
|
||||||
this.titleContainer = this.scene.add.container(0, -(this.scene.game.canvas.height / 6));
|
this.titleContainer = this.scene.add.container(0, -(this.scene.game.canvas.height / 6));
|
||||||
this.titleContainer.setName("title");
|
this.titleContainer.setName("title");
|
||||||
this.titleContainer.setAlpha(0);
|
this.titleContainer.setAlpha(0);
|
||||||
ui.add(this.titleContainer);
|
ui.add(this.titleContainer);
|
||||||
|
|
||||||
this.logo = this.scene.add.image((this.scene.scaledCanvas.width / 4) + 3, 8, "logo");
|
this.logo = this.scene.add.image(
|
||||||
|
(this.scene.scaledCanvas.width / 4) + 3,
|
||||||
|
8,
|
||||||
|
"logo"
|
||||||
|
);
|
||||||
this.logo.setName("logo");
|
this.logo.setName("logo");
|
||||||
this.logo.setOrigin(0.5, 0);
|
this.logo.setOrigin(0.5, 0);
|
||||||
this.titleContainer.add(this.logo);
|
this.titleContainer.add(this.logo);
|
||||||
|
|
||||||
this.iconContainer = new TitleIcons(this.scene, 15, this.scene.scaledCanvas.height - 15);
|
this.menuOverlay = this.scene.add.rectangle(
|
||||||
|
8, 59,
|
||||||
|
92, 71,
|
||||||
|
Number(`0x${overlayColor.slice(1)}`),
|
||||||
|
0.5
|
||||||
|
);
|
||||||
|
this.menuOverlay.setName("title-options-bg");
|
||||||
|
this.menuOverlay.setOrigin(0);
|
||||||
|
this.menuOverlay.setBlendMode(Phaser.BlendModes.OVERLAY);
|
||||||
|
this.titleContainer.add(this.menuOverlay);
|
||||||
|
|
||||||
|
this.iconContainer = new TitleIcons(
|
||||||
|
this.scene,
|
||||||
|
15, this.scene.scaledCanvas.height - 15
|
||||||
|
);
|
||||||
this.iconContainer.setup();
|
this.iconContainer.setup();
|
||||||
this.titleContainer.add(this.iconContainer);
|
this.titleContainer.add(this.iconContainer);
|
||||||
|
|
||||||
|
|
||||||
|
this.rivalSprite = new Phaser.GameObjects.Sprite(
|
||||||
|
this.scene,
|
||||||
|
176, 127,
|
||||||
|
`${this.scene.gameData.gender === PlayerGender.MALE ? "ivy" : "finn" }-sprite`
|
||||||
|
);
|
||||||
|
this.rivalSprite.setName("rival");
|
||||||
|
|
||||||
|
this.spriteShadow = new Phaser.GameObjects.Ellipse(
|
||||||
|
this.scene,
|
||||||
|
this.rivalSprite.x, (this.rivalSprite.y + this.rivalSprite.height / 2) - 1,
|
||||||
|
this.rivalSprite.width / 2, this.rivalSprite.height / 10,
|
||||||
|
Number(`0x${Color.DARK_GREY}`), 0.5
|
||||||
|
);
|
||||||
|
this.spriteShadow.setName("sprite-shadow");
|
||||||
|
this.spriteShadow.setBlendMode(Phaser.BlendModes.OVERLAY);
|
||||||
|
this.titleContainer.add([this.rivalSprite, this.spriteShadow]);
|
||||||
|
|
||||||
if (this.scene.eventManager.isEventActive()) {
|
if (this.scene.eventManager.isEventActive()) {
|
||||||
this.eventDisplay = new TimedEventDisplay(this.scene, 170, 66, this.scene.eventManager.activeEvent());
|
this.eventDisplay = new TimedEventDisplay(this.scene, 189, 49, this.scene.eventManager.activeEvent());
|
||||||
this.eventDisplay.setup();
|
this.eventDisplay.setup();
|
||||||
this.titleContainer.add(this.eventDisplay);
|
this.titleContainer.add(this.eventDisplay);
|
||||||
|
} else {
|
||||||
|
this.rivalText = addTextObject(
|
||||||
|
this.scene,
|
||||||
|
190,
|
||||||
|
98,
|
||||||
|
"Check the Discord for the latest changes!",
|
||||||
|
TextStyle.WINDOW_ALT,
|
||||||
|
{ fontSize: 49 }
|
||||||
|
);
|
||||||
|
this.rivalText.setOrigin(0);
|
||||||
|
this.rivalText.setName("text-rival-changelog");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.playerCountLabel = addTextObject(this.scene, 8, this.scene.scaledCanvas.height - 132, i18next.t("menu:playersOnline", { count: 0 }), TextStyle.MESSAGE, { fontSize: "54px" });
|
this.bubble = new SpeechBubble(this.scene, 244, 102, (this.eventDisplay?.getByName("text-event-timer") ?? this.rivalText) as Phaser.GameObjects.Text);
|
||||||
console.log(this.playerCountLabel);
|
this.titleContainer.add(this.bubble);
|
||||||
|
|
||||||
|
this.playerCountLabel = addTextObject(
|
||||||
|
this.scene,
|
||||||
|
this.scene.scaledCanvas.width - 60,
|
||||||
|
this.scene.scaledCanvas.height - 20,
|
||||||
|
i18next.t("menu:playersOnline", { count: 0 }),
|
||||||
|
TextStyle.MESSAGE,
|
||||||
|
{
|
||||||
|
fontSize: "60px",
|
||||||
|
align: "right",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
this.playerCountLabel.setName("player-count");
|
this.playerCountLabel.setName("player-count");
|
||||||
this.playerCountLabel.setOrigin(0);
|
this.playerCountLabel.setOrigin(0);
|
||||||
|
this.playerCountWidth = this.playerCountLabel.width;
|
||||||
this.titleContainer.add(this.playerCountLabel);
|
this.titleContainer.add(this.playerCountLabel);
|
||||||
|
|
||||||
this.splashMessageText = addTextObject(this.scene, this.logo.x + 64, this.logo.y + this.logo.displayHeight - 8, "", TextStyle.MONEY, { fontSize: "54px" });
|
this.splashMessageText = addTextObject(this.scene, this.logo.x + 64, this.logo.y + this.logo.displayHeight - 8, "", TextStyle.MONEY, { fontSize: "54px" });
|
||||||
|
@ -75,6 +147,8 @@ export default class TitleUiHandler extends OptionSelectUiHandler {
|
||||||
.then(request => request.json())
|
.then(request => request.json())
|
||||||
.then((stats: { playerCount: number, battleCount: number }) => {
|
.then((stats: { playerCount: number, battleCount: number }) => {
|
||||||
this.playerCountLabel.setText(i18next.t("menu:playersOnline", { count: stats.playerCount }));
|
this.playerCountLabel.setText(i18next.t("menu:playersOnline", { count: stats.playerCount }));
|
||||||
|
this.playerCountLabel.setX(this.playerCountLabel.x - ((this.playerCountLabel.width - this.playerCountWidth) / 6));
|
||||||
|
this.playerCountWidth = this.playerCountLabel.width;
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
console.error("Failed to fetch title stats:\n", err);
|
console.error("Failed to fetch title stats:\n", err);
|
||||||
|
@ -86,7 +160,7 @@ export default class TitleUiHandler extends OptionSelectUiHandler {
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
this.splashMessage = Utils.randItem(getSplashMessages());
|
this.splashMessage = Utils.randItem(getSplashMessages());
|
||||||
this.splashMessageText.setText(this.splashMessage.replace("{COUNT}", "?"));
|
this.splashMessageText.setText(this.splashMessage);
|
||||||
|
|
||||||
const ui = this.getUi();
|
const ui = this.getUi();
|
||||||
|
|
||||||
|
@ -94,7 +168,9 @@ export default class TitleUiHandler extends OptionSelectUiHandler {
|
||||||
this.eventDisplay.show();
|
this.eventDisplay.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.bubble.setVisible(true);
|
||||||
this.iconContainer.setVisible(true);
|
this.iconContainer.setVisible(true);
|
||||||
|
this.update();
|
||||||
|
|
||||||
this.updateTitleStats();
|
this.updateTitleStats();
|
||||||
|
|
||||||
|
@ -113,6 +189,12 @@ export default class TitleUiHandler extends OptionSelectUiHandler {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
|
const playerMale = this.scene.gameData.gender === PlayerGender.MALE;
|
||||||
|
this.rivalSprite.setTexture(`${playerMale ? "ivy" : "finn" }-sprite`);
|
||||||
|
this.spriteShadow.setY((this.rivalSprite.y + this.rivalSprite.height / 2) - (playerMale ? 2 : 3));
|
||||||
|
}
|
||||||
|
|
||||||
clear(): void {
|
clear(): void {
|
||||||
super.clear();
|
super.clear();
|
||||||
|
|
||||||
|
@ -120,6 +202,7 @@ export default class TitleUiHandler extends OptionSelectUiHandler {
|
||||||
|
|
||||||
this.eventDisplay?.setVisible(false);
|
this.eventDisplay?.setVisible(false);
|
||||||
this.iconContainer?.setVisible(false);
|
this.iconContainer?.setVisible(false);
|
||||||
|
this.bubble.setVisible(false);
|
||||||
|
|
||||||
clearInterval(this.titleStatsTimer);
|
clearInterval(this.titleStatsTimer);
|
||||||
this.titleStatsTimer = null;
|
this.titleStatsTimer = null;
|
||||||
|
@ -192,9 +275,11 @@ class Icon extends Phaser.GameObjects.Sprite {
|
||||||
this.setAlpha(this.DEFAULT_ALPHA);
|
this.setAlpha(this.DEFAULT_ALPHA);
|
||||||
this.on(Phaser.Input.Events.GAMEOBJECT_POINTER_OVER, () => {
|
this.on(Phaser.Input.Events.GAMEOBJECT_POINTER_OVER, () => {
|
||||||
this.setAlpha(1);
|
this.setAlpha(1);
|
||||||
|
scene.ui.showTooltip("", texture, true);
|
||||||
});
|
});
|
||||||
this.on(Phaser.Input.Events.GAMEOBJECT_POINTER_OUT, () => {
|
this.on(Phaser.Input.Events.GAMEOBJECT_POINTER_OUT, () => {
|
||||||
this.setAlpha(this.DEFAULT_ALPHA);
|
this.setAlpha(this.DEFAULT_ALPHA);
|
||||||
|
scene.ui.hideTooltip();
|
||||||
});
|
});
|
||||||
this.on(Phaser.Input.Events.GAMEOBJECT_POINTER_DOWN, () => {
|
this.on(Phaser.Input.Events.GAMEOBJECT_POINTER_DOWN, () => {
|
||||||
window.open(link, "_blank").focus();
|
window.open(link, "_blank").focus();
|
||||||
|
|
10
src/ui/ui.ts
10
src/ui/ui.ts
|
@ -220,6 +220,7 @@ export default class UI extends Phaser.GameObjects.Container {
|
||||||
|
|
||||||
this.tooltipContent = addTextObject(this.scene, 6, 16, "", TextStyle.TOOLTIP_CONTENT);
|
this.tooltipContent = addTextObject(this.scene, 6, 16, "", TextStyle.TOOLTIP_CONTENT);
|
||||||
this.tooltipContent.setName("text-tooltip-content");
|
this.tooltipContent.setName("text-tooltip-content");
|
||||||
|
this.tooltipContent.setAlign("center");
|
||||||
this.tooltipContent.setWordWrapWidth(696);
|
this.tooltipContent.setWordWrapWidth(696);
|
||||||
|
|
||||||
this.tooltipContainer.add(this.tooltipBg);
|
this.tooltipContainer.add(this.tooltipBg);
|
||||||
|
@ -365,8 +366,13 @@ export default class UI extends Phaser.GameObjects.Container {
|
||||||
|
|
||||||
update(): void {
|
update(): void {
|
||||||
if (this.tooltipContainer.visible) {
|
if (this.tooltipContainer.visible) {
|
||||||
const reverse = this.scene.game.input.mousePointer.x >= this.scene.game.canvas.width - this.tooltipBg.width * 6 - 12;
|
const reverseX = this.scene.game.input.mousePointer.x >= this.scene.game.canvas.width - this.tooltipBg.width * 6 - 12;
|
||||||
this.tooltipContainer.setPosition(!reverse ? this.scene.game.input.mousePointer.x / 6 + 2 : this.scene.game.input.mousePointer.x / 6 - this.tooltipBg.width - 2, this.scene.game.input.mousePointer.y / 6 + 2);
|
const reverseY = this.scene.game.input.mousePointer.y >= this.scene.game.canvas.height - this.tooltipBg.height * 6 - 12;
|
||||||
|
this.tooltipContainer.setPosition(
|
||||||
|
!reverseX ? this.scene.game.input.mousePointer.x / 6 + 2 : this.scene.game.input.mousePointer.x / 6 - this.tooltipBg.width - 2,
|
||||||
|
!reverseY ? this.scene.game.input.mousePointer.y / 6 + 2 : this.scene.game.input.mousePointer.y / 6 - this.tooltipBg.height - 2
|
||||||
|
);
|
||||||
|
this.tooltipTitle.setX(this.tooltipBg.width / 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
10
src/utils.ts
10
src/utils.ts
|
@ -433,13 +433,19 @@ export function deltaRgb(rgb1: integer[], rgb2: integer[]): integer {
|
||||||
return Math.ceil(Math.sqrt(2 * drp2 + 4 * dgp2 + 3 * dbp2 + t * (drp2 - dbp2) / 256));
|
return Math.ceil(Math.sqrt(2 * drp2 + 4 * dgp2 + 3 * dbp2 + t * (drp2 - dbp2) / 256));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function rgbHexToRgba(hex: string) {
|
/**
|
||||||
|
* Converts a hex code for a color to rgba
|
||||||
|
* @param {string} hex hex code
|
||||||
|
* @param {number} alpha transparency between 0 and 1
|
||||||
|
* @returns rgba object
|
||||||
|
*/
|
||||||
|
export function rgbHexToRgba(hex: string, alpha?: number): { r: number, g: number, b: number, a: number } {
|
||||||
const color = hex.match(/^([\da-f]{2})([\da-f]{2})([\da-f]{2})$/i);
|
const color = hex.match(/^([\da-f]{2})([\da-f]{2})([\da-f]{2})$/i);
|
||||||
return {
|
return {
|
||||||
r: parseInt(color[1], 16),
|
r: parseInt(color[1], 16),
|
||||||
g: parseInt(color[2], 16),
|
g: parseInt(color[2], 16),
|
||||||
b: parseInt(color[3], 16),
|
b: parseInt(color[3], 16),
|
||||||
a: 255
|
a: 255 * (alpha ?? 1)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue