[QoL] Add Time of Day Widget to Arena Flyout (#1846)
* Time of Day Sample * Add Proper Time of Day Tracking * Add Settings
Before Width: | Height: | Size: 581 B |
BIN
public/images/ui/dawn_icon_bg.png
Normal file
After Width: | Height: | Size: 186 B |
BIN
public/images/ui/dawn_icon_fg.png
Normal file
After Width: | Height: | Size: 347 B |
BIN
public/images/ui/dawn_icon_mg.png
Normal file
After Width: | Height: | Size: 273 B |
Before Width: | Height: | Size: 593 B |
BIN
public/images/ui/day_icon_bg.png
Normal file
After Width: | Height: | Size: 186 B |
BIN
public/images/ui/day_icon_fg.png
Normal file
After Width: | Height: | Size: 398 B |
BIN
public/images/ui/day_icon_mg.png
Normal file
After Width: | Height: | Size: 245 B |
Before Width: | Height: | Size: 534 B |
BIN
public/images/ui/dusk_icon_bg.png
Normal file
After Width: | Height: | Size: 186 B |
BIN
public/images/ui/dusk_icon_fg.png
Normal file
After Width: | Height: | Size: 388 B |
BIN
public/images/ui/dusk_icon_mg.png
Normal file
After Width: | Height: | Size: 235 B |
Before Width: | Height: | Size: 327 B |
BIN
public/images/ui/legacy/dawn_icon_bg.png
Normal file
After Width: | Height: | Size: 150 B |
BIN
public/images/ui/legacy/dawn_icon_fg.png
Normal file
After Width: | Height: | Size: 249 B |
BIN
public/images/ui/legacy/dawn_icon_mg.png
Normal file
After Width: | Height: | Size: 239 B |
Before Width: | Height: | Size: 285 B |
BIN
public/images/ui/legacy/day_icon_bg.png
Normal file
After Width: | Height: | Size: 186 B |
BIN
public/images/ui/legacy/day_icon_fg.png
Normal file
After Width: | Height: | Size: 255 B |
BIN
public/images/ui/legacy/day_icon_mg.png
Normal file
After Width: | Height: | Size: 151 B |
Before Width: | Height: | Size: 300 B |
BIN
public/images/ui/legacy/dusk_icon_bg.png
Normal file
After Width: | Height: | Size: 150 B |
BIN
public/images/ui/legacy/dusk_icon_fg.png
Normal file
After Width: | Height: | Size: 252 B |
BIN
public/images/ui/legacy/dusk_icon_mg.png
Normal file
After Width: | Height: | Size: 219 B |
Before Width: | Height: | Size: 288 B |
BIN
public/images/ui/legacy/night_icon_bg.png
Normal file
After Width: | Height: | Size: 150 B |
BIN
public/images/ui/legacy/night_icon_fg.png
Normal file
After Width: | Height: | Size: 240 B |
BIN
public/images/ui/legacy/night_icon_mg.png
Normal file
After Width: | Height: | Size: 120 B |
Before Width: | Height: | Size: 686 B |
BIN
public/images/ui/night_icon_bg.png
Normal file
After Width: | Height: | Size: 186 B |
BIN
public/images/ui/night_icon_fg.png
Normal file
After Width: | Height: | Size: 440 B |
BIN
public/images/ui/night_icon_mg.png
Normal file
After Width: | Height: | Size: 271 B |
@ -20,6 +20,11 @@ export enum BattleSceneEventType {
|
|||||||
*/
|
*/
|
||||||
BERRY_USED = "onBerryUsed",
|
BERRY_USED = "onBerryUsed",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers at the start of each new encounter
|
||||||
|
* @see {@linkcode EncounterPhaseEvent}
|
||||||
|
*/
|
||||||
|
ENCOUNTER_PHASE = "onEncounterPhase",
|
||||||
/**
|
/**
|
||||||
* Triggers on the first turn of a new battle
|
* Triggers on the first turn of a new battle
|
||||||
* @see {@linkcode TurnInitEvent}
|
* @see {@linkcode TurnInitEvent}
|
||||||
@ -85,6 +90,15 @@ export class BerryUsedEvent extends Event {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Container class for {@linkcode BattleSceneEventType.ENCOUNTER_PHASE} events
|
||||||
|
* @extends Event
|
||||||
|
*/
|
||||||
|
export class EncounterPhaseEvent extends Event {
|
||||||
|
constructor() {
|
||||||
|
super(BattleSceneEventType.ENCOUNTER_PHASE);
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Container class for {@linkcode BattleSceneEventType.TURN_INIT} events
|
* Container class for {@linkcode BattleSceneEventType.TURN_INIT} events
|
||||||
* @extends Event
|
* @extends Event
|
||||||
|
@ -60,6 +60,7 @@ import {UiInputs} from "./ui-inputs";
|
|||||||
import { MoneyFormat } from "./enums/money-format";
|
import { MoneyFormat } from "./enums/money-format";
|
||||||
import { NewArenaEvent } from "./battle-scene-events";
|
import { NewArenaEvent } from "./battle-scene-events";
|
||||||
import ArenaFlyout from "./ui/arena-flyout";
|
import ArenaFlyout from "./ui/arena-flyout";
|
||||||
|
import { EaseType } from "./ui/enums/ease-type";
|
||||||
|
|
||||||
export const bypassLogin = import.meta.env.VITE_BYPASS_LOGIN === "1";
|
export const bypassLogin = import.meta.env.VITE_BYPASS_LOGIN === "1";
|
||||||
|
|
||||||
@ -100,6 +101,8 @@ export default class BattleScene extends SceneBase {
|
|||||||
public reroll: boolean = false;
|
public reroll: boolean = false;
|
||||||
public showMovesetFlyout: boolean = true;
|
public showMovesetFlyout: boolean = true;
|
||||||
public showArenaFlyout: boolean = true;
|
public showArenaFlyout: boolean = true;
|
||||||
|
public showTimeOfDayWidget: boolean = true;
|
||||||
|
public timeOfDayAnimation: EaseType = EaseType.NONE;
|
||||||
public showLevelUpStats: boolean = true;
|
public showLevelUpStats: boolean = true;
|
||||||
public enableTutorials: boolean = import.meta.env.VITE_BYPASS_TUTORIAL === "1";
|
public enableTutorials: boolean = import.meta.env.VITE_BYPASS_TUTORIAL === "1";
|
||||||
public enableMoveInfo: boolean = true;
|
public enableMoveInfo: boolean = true;
|
||||||
|
@ -96,10 +96,18 @@ export class LoadingScene extends SceneBase {
|
|||||||
this.loadImage("type_tera", "ui");
|
this.loadImage("type_tera", "ui");
|
||||||
this.loadAtlas("type_bgs", "ui");
|
this.loadAtlas("type_bgs", "ui");
|
||||||
|
|
||||||
this.loadImage("dawn_icon", "ui");
|
this.loadImage("dawn_icon_fg", "ui");
|
||||||
this.loadImage("day_icon", "ui");
|
this.loadImage("dawn_icon_mg", "ui");
|
||||||
this.loadImage("dusk_icon", "ui");
|
this.loadImage("dawn_icon_bg", "ui");
|
||||||
this.loadImage("night_icon", "ui");
|
this.loadImage("day_icon_fg", "ui");
|
||||||
|
this.loadImage("day_icon_mg", "ui");
|
||||||
|
this.loadImage("day_icon_bg", "ui");
|
||||||
|
this.loadImage("dusk_icon_fg", "ui");
|
||||||
|
this.loadImage("dusk_icon_mg", "ui");
|
||||||
|
this.loadImage("dusk_icon_bg", "ui");
|
||||||
|
this.loadImage("night_icon_fg", "ui");
|
||||||
|
this.loadImage("night_icon_mg", "ui");
|
||||||
|
this.loadImage("night_icon_bg", "ui");
|
||||||
|
|
||||||
this.loadImage("pb_tray_overlay_player", "ui");
|
this.loadImage("pb_tray_overlay_player", "ui");
|
||||||
this.loadImage("pb_tray_overlay_enemy", "ui");
|
this.loadImage("pb_tray_overlay_enemy", "ui");
|
||||||
|
@ -62,7 +62,7 @@ import { Abilities } from "./data/enums/abilities";
|
|||||||
import * as Overrides from "./overrides";
|
import * as Overrides from "./overrides";
|
||||||
import { TextStyle, addTextObject } from "./ui/text";
|
import { TextStyle, addTextObject } from "./ui/text";
|
||||||
import { Type } from "./data/type";
|
import { Type } from "./data/type";
|
||||||
import { BerryUsedEvent, MoveUsedEvent, TurnEndEvent, TurnInitEvent } from "./battle-scene-events";
|
import { BerryUsedEvent, EncounterPhaseEvent, MoveUsedEvent, TurnEndEvent, TurnInitEvent } from "./battle-scene-events";
|
||||||
|
|
||||||
|
|
||||||
export class LoginPhase extends Phase {
|
export class LoginPhase extends Phase {
|
||||||
@ -741,6 +741,8 @@ export class EncounterPhase extends BattlePhase {
|
|||||||
|
|
||||||
this.scene.initSession();
|
this.scene.initSession();
|
||||||
|
|
||||||
|
this.scene.eventTarget.dispatchEvent(new EncounterPhaseEvent());
|
||||||
|
|
||||||
// Failsafe if players somehow skip floor 200 in classic mode
|
// Failsafe if players somehow skip floor 200 in classic mode
|
||||||
if (this.scene.gameMode.isClassic && this.scene.currentBattle.waveIndex > 200) {
|
if (this.scene.gameMode.isClassic && this.scene.currentBattle.waveIndex > 200) {
|
||||||
this.scene.unshiftPhase(new GameOverPhase(this.scene));
|
this.scene.unshiftPhase(new GameOverPhase(this.scene));
|
||||||
|
@ -7,6 +7,7 @@ import { PlayerGender } from "#app/data/enums/player-gender";
|
|||||||
import { CandyUpgradeNotificationChangedEvent } from "#app/battle-scene-events.js";
|
import { CandyUpgradeNotificationChangedEvent } from "#app/battle-scene-events.js";
|
||||||
import { MoneyFormat } from "../../enums/money-format";
|
import { MoneyFormat } from "../../enums/money-format";
|
||||||
import SettingsUiHandler from "#app/ui/settings/settings-ui-handler";
|
import SettingsUiHandler from "#app/ui/settings/settings-ui-handler";
|
||||||
|
import { EaseType } from "#app/ui/enums/ease-type.js";
|
||||||
|
|
||||||
const MUTE = "Mute";
|
const MUTE = "Mute";
|
||||||
const VOLUME_OPTIONS = new Array(11).fill(null).map((_, i) => i ? (i * 10).toString() : MUTE);
|
const VOLUME_OPTIONS = new Array(11).fill(null).map((_, i) => i ? (i * 10).toString() : MUTE);
|
||||||
@ -54,6 +55,8 @@ export const SettingKeys = {
|
|||||||
Move_Animations: "MOVE_ANIMATIONS",
|
Move_Animations: "MOVE_ANIMATIONS",
|
||||||
Show_Moveset_Flyout: "SHOW_MOVESET_FLYOUT",
|
Show_Moveset_Flyout: "SHOW_MOVESET_FLYOUT",
|
||||||
Show_Arena_Flyout: "SHOW_ARENA_FLYOUT",
|
Show_Arena_Flyout: "SHOW_ARENA_FLYOUT",
|
||||||
|
Show_Time_Of_Day_Widget: "SHOW_TIME_OF_DAY_WIDGET",
|
||||||
|
Time_Of_Day_Animation: "TIME_OF_DAY_ANIMATION",
|
||||||
Show_Stats_on_Level_Up: "SHOW_LEVEL_UP_STATS",
|
Show_Stats_on_Level_Up: "SHOW_LEVEL_UP_STATS",
|
||||||
EXP_Gains_Speed: "EXP_GAINS_SPEED",
|
EXP_Gains_Speed: "EXP_GAINS_SPEED",
|
||||||
EXP_Party_Display: "EXP_PARTY_DISPLAY",
|
EXP_Party_Display: "EXP_PARTY_DISPLAY",
|
||||||
@ -205,6 +208,21 @@ export const Setting: Array<Setting> = [
|
|||||||
default: 1,
|
default: 1,
|
||||||
type: SettingType.ACCESSIBILITY
|
type: SettingType.ACCESSIBILITY
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: SettingKeys.Show_Time_Of_Day_Widget,
|
||||||
|
label: "Show Time of Day Widget",
|
||||||
|
options: OFF_ON,
|
||||||
|
default: 1,
|
||||||
|
type: SettingType.ACCESSIBILITY,
|
||||||
|
requireReload: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: SettingKeys.Time_Of_Day_Animation,
|
||||||
|
label: "Time of Day Animation",
|
||||||
|
options: ["Bounce", "Back"],
|
||||||
|
default: 0,
|
||||||
|
type: SettingType.ACCESSIBILITY
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: SettingKeys.Show_Stats_on_Level_Up,
|
key: SettingKeys.Show_Stats_on_Level_Up,
|
||||||
label: "Show Stats on Level Up",
|
label: "Show Stats on Level Up",
|
||||||
@ -365,6 +383,12 @@ export function setSetting(scene: BattleScene, setting: string, value: integer):
|
|||||||
case SettingKeys.Show_Arena_Flyout:
|
case SettingKeys.Show_Arena_Flyout:
|
||||||
scene.showArenaFlyout = Setting[index].options[value] === "On";
|
scene.showArenaFlyout = Setting[index].options[value] === "On";
|
||||||
break;
|
break;
|
||||||
|
case SettingKeys.Show_Time_Of_Day_Widget:
|
||||||
|
scene.showTimeOfDayWidget = Setting[index].options[value] === "On";
|
||||||
|
break;
|
||||||
|
case SettingKeys.Time_Of_Day_Animation:
|
||||||
|
scene.timeOfDayAnimation = Setting[index].options[value] === "Bounce" ? EaseType.BOUNCE : EaseType.BACK;
|
||||||
|
break;
|
||||||
case SettingKeys.Show_Stats_on_Level_Up:
|
case SettingKeys.Show_Stats_on_Level_Up:
|
||||||
scene.showLevelUpStats = Setting[index].options[value] === "On";
|
scene.showLevelUpStats = Setting[index].options[value] === "On";
|
||||||
break;
|
break;
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import * as Utils from "../utils";
|
|
||||||
import { addTextObject, TextStyle } from "./text";
|
import { addTextObject, TextStyle } from "./text";
|
||||||
import BattleScene from "#app/battle-scene.js";
|
import BattleScene from "#app/battle-scene.js";
|
||||||
import { ArenaTagSide } from "#app/data/arena-tag.js";
|
import { ArenaTagSide } from "#app/data/arena-tag.js";
|
||||||
@ -8,7 +7,8 @@ import { addWindow, WindowVariant } from "./ui-theme";
|
|||||||
import { ArenaEvent, ArenaEventType, TagAddedEvent, TagRemovedEvent, TerrainChangedEvent, WeatherChangedEvent } from "#app/field/arena-events.js";
|
import { ArenaEvent, ArenaEventType, TagAddedEvent, TagRemovedEvent, TerrainChangedEvent, WeatherChangedEvent } from "#app/field/arena-events.js";
|
||||||
import { BattleSceneEventType, TurnEndEvent } from "#app/battle-scene-events.js";
|
import { BattleSceneEventType, TurnEndEvent } from "#app/battle-scene-events.js";
|
||||||
import { ArenaTagType } from "#app/data/enums/arena-tag-type.js";
|
import { ArenaTagType } from "#app/data/enums/arena-tag-type.js";
|
||||||
import { TimeOfDay } from "#app/data/enums/time-of-day.js";
|
import TimeOfDayWidget from "./time-of-day-widget";
|
||||||
|
import * as Utils from "../utils";
|
||||||
|
|
||||||
/** Enum used to differentiate {@linkcode Arena} effects */
|
/** Enum used to differentiate {@linkcode Arena} effects */
|
||||||
enum ArenaEffectType {
|
enum ArenaEffectType {
|
||||||
@ -60,8 +60,7 @@ export default class ArenaFlyout extends Phaser.GameObjects.Container {
|
|||||||
/** The {@linkcode Phaser.GameObjects.Text} that goes inside of the header */
|
/** The {@linkcode Phaser.GameObjects.Text} that goes inside of the header */
|
||||||
private flyoutTextHeader: Phaser.GameObjects.Text;
|
private flyoutTextHeader: Phaser.GameObjects.Text;
|
||||||
|
|
||||||
/** The {@linkcode Phaser.GameObjects.Sprite} that represents the current time of day */
|
private timeOfDayWidget: TimeOfDayWidget;
|
||||||
private timeOfDayIcon: Phaser.GameObjects.Sprite;
|
|
||||||
|
|
||||||
/** The {@linkcode Phaser.GameObjects.Text} header used to indicate the player's effects */
|
/** The {@linkcode Phaser.GameObjects.Text} header used to indicate the player's effects */
|
||||||
private flyoutTextHeaderPlayer: Phaser.GameObjects.Text;
|
private flyoutTextHeaderPlayer: Phaser.GameObjects.Text;
|
||||||
@ -82,7 +81,6 @@ export default class ArenaFlyout extends Phaser.GameObjects.Container {
|
|||||||
|
|
||||||
// Stores callbacks in a variable so they can be unsubscribed from when destroyed
|
// Stores callbacks in a variable so they can be unsubscribed from when destroyed
|
||||||
private readonly onNewArenaEvent = (event: Event) => this.onNewArena(event);
|
private readonly onNewArenaEvent = (event: Event) => this.onNewArena(event);
|
||||||
private readonly onTurnInitEvent = (event: Event) => this.onTurnInit(event);
|
|
||||||
private readonly onTurnEndEvent = (event: Event) => this.onTurnEnd(event);
|
private readonly onTurnEndEvent = (event: Event) => this.onTurnEnd(event);
|
||||||
|
|
||||||
private readonly onFieldEffectChangedEvent = (event: Event) => this.onFieldEffectChanged(event);
|
private readonly onFieldEffectChangedEvent = (event: Event) => this.onFieldEffectChanged(event);
|
||||||
@ -117,10 +115,8 @@ export default class ArenaFlyout extends Phaser.GameObjects.Container {
|
|||||||
|
|
||||||
this.flyoutContainer.add(this.flyoutTextHeader);
|
this.flyoutContainer.add(this.flyoutTextHeader);
|
||||||
|
|
||||||
this.timeOfDayIcon = this.scene.add.sprite((this.flyoutWidth / 2) + (this.flyoutWindowHeader.displayWidth / 2), 0, "dawn_icon").setOrigin();
|
this.timeOfDayWidget = new TimeOfDayWidget(this.scene, (this.flyoutWidth / 2) + (this.flyoutWindowHeader.displayWidth / 2));
|
||||||
this.timeOfDayIcon.setVisible(false);
|
this.flyoutContainer.add(this.timeOfDayWidget);
|
||||||
|
|
||||||
this.flyoutContainer.add(this.timeOfDayIcon);
|
|
||||||
|
|
||||||
this.flyoutTextHeaderPlayer = addTextObject(this.scene, 6, 5, "Player", TextStyle.SUMMARY_BLUE);
|
this.flyoutTextHeaderPlayer = addTextObject(this.scene, 6, 5, "Player", TextStyle.SUMMARY_BLUE);
|
||||||
this.flyoutTextHeaderPlayer.setFontSize(54);
|
this.flyoutTextHeaderPlayer.setFontSize(54);
|
||||||
@ -172,18 +168,9 @@ export default class ArenaFlyout extends Phaser.GameObjects.Container {
|
|||||||
|
|
||||||
// Subscribes to required events available on game start
|
// Subscribes to required events available on game start
|
||||||
this.battleScene.eventTarget.addEventListener(BattleSceneEventType.NEW_ARENA, this.onNewArenaEvent);
|
this.battleScene.eventTarget.addEventListener(BattleSceneEventType.NEW_ARENA, this.onNewArenaEvent);
|
||||||
this.battleScene.eventTarget.addEventListener(BattleSceneEventType.TURN_INIT, this.onTurnInitEvent);
|
|
||||||
this.battleScene.eventTarget.addEventListener(BattleSceneEventType.TURN_END, this.onTurnEndEvent);
|
this.battleScene.eventTarget.addEventListener(BattleSceneEventType.TURN_END, this.onTurnEndEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private setTimeOfDayIcon() {
|
|
||||||
this.timeOfDayIcon.setTexture(TimeOfDay[this.battleScene.arena.getTimeOfDay()].toLowerCase() + "_icon");
|
|
||||||
}
|
|
||||||
|
|
||||||
private onTurnInit(event: Event) {
|
|
||||||
this.setTimeOfDayIcon();
|
|
||||||
}
|
|
||||||
|
|
||||||
private onNewArena(event: Event) {
|
private onNewArena(event: Event) {
|
||||||
this.fieldEffectInfo.length = 0;
|
this.fieldEffectInfo.length = 0;
|
||||||
|
|
||||||
@ -192,8 +179,6 @@ export default class ArenaFlyout extends Phaser.GameObjects.Container {
|
|||||||
this.battleScene.arena.eventTarget.addEventListener(ArenaEventType.TERRAIN_CHANGED, this.onFieldEffectChangedEvent);
|
this.battleScene.arena.eventTarget.addEventListener(ArenaEventType.TERRAIN_CHANGED, this.onFieldEffectChangedEvent);
|
||||||
this.battleScene.arena.eventTarget.addEventListener(ArenaEventType.TAG_ADDED, this.onFieldEffectChangedEvent);
|
this.battleScene.arena.eventTarget.addEventListener(ArenaEventType.TAG_ADDED, this.onFieldEffectChangedEvent);
|
||||||
this.battleScene.arena.eventTarget.addEventListener(ArenaEventType.TAG_REMOVED, this.onFieldEffectChangedEvent);
|
this.battleScene.arena.eventTarget.addEventListener(ArenaEventType.TAG_REMOVED, this.onFieldEffectChangedEvent);
|
||||||
|
|
||||||
this.setTimeOfDayIcon();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -360,17 +345,18 @@ export default class ArenaFlyout extends Phaser.GameObjects.Container {
|
|||||||
* Animates the flyout to either show or hide it by applying a fade and translation
|
* Animates the flyout to either show or hide it by applying a fade and translation
|
||||||
* @param visible Should the flyout be shown?
|
* @param visible Should the flyout be shown?
|
||||||
*/
|
*/
|
||||||
toggleFlyout(visible: boolean): void {
|
public toggleFlyout(visible: boolean): void {
|
||||||
this.scene.tweens.add({
|
this.scene.tweens.add({
|
||||||
targets: this.flyoutParent,
|
targets: this.flyoutParent,
|
||||||
x: visible ? this.anchorX : this.anchorX - this.translationX,
|
x: visible ? this.anchorX : this.anchorX - this.translationX,
|
||||||
duration: Utils.fixedInt(125),
|
duration: Utils.fixedInt(125),
|
||||||
ease: "Sine.easeInOut",
|
ease: "Sine.easeInOut",
|
||||||
alpha: visible ? 1 : 0,
|
alpha: visible ? 1 : 0,
|
||||||
|
onComplete: () => this.timeOfDayWidget.parentVisible = visible,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy(fromScene?: boolean): void {
|
public destroy(fromScene?: boolean): void {
|
||||||
this.battleScene.eventTarget.removeEventListener(BattleSceneEventType.NEW_ARENA, this.onNewArenaEvent);
|
this.battleScene.eventTarget.removeEventListener(BattleSceneEventType.NEW_ARENA, this.onNewArenaEvent);
|
||||||
this.battleScene.eventTarget.removeEventListener(BattleSceneEventType.TURN_END, this.onTurnEndEvent);
|
this.battleScene.eventTarget.removeEventListener(BattleSceneEventType.TURN_END, this.onTurnEndEvent);
|
||||||
|
|
||||||
|
15
src/ui/enums/ease-type.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
export enum EaseType {
|
||||||
|
NONE,
|
||||||
|
LINEAR = "Linear",
|
||||||
|
QUADRATIC = "Quad",
|
||||||
|
CUBIC = "Cubic",
|
||||||
|
QUARTIC = "Quart",
|
||||||
|
QUINTIC = "Quint",
|
||||||
|
SINUSOIDAL = "Sine",
|
||||||
|
EXPONENTIAL = "Expo",
|
||||||
|
CIRCULAR = "Circ",
|
||||||
|
ELASTIC = "Elastic",
|
||||||
|
BACK = "Back",
|
||||||
|
BOUNCE = "Bounce",
|
||||||
|
STEPPED = "Stepped",
|
||||||
|
}
|
172
src/ui/time-of-day-widget.ts
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
import * as Utils from "../utils";
|
||||||
|
import BattleScene from "#app/battle-scene.js";
|
||||||
|
import { TimeOfDay } from "#app/data/enums/time-of-day.js";
|
||||||
|
import { BattleSceneEventType } from "#app/battle-scene-events.js";
|
||||||
|
import { EaseType } from "./enums/ease-type";
|
||||||
|
|
||||||
|
/** A small self contained UI element that displays the time of day as an icon */
|
||||||
|
export default class TimeOfDayWidget extends Phaser.GameObjects.Container {
|
||||||
|
/** An alias for the scene typecast to a {@linkcode BattleScene} */
|
||||||
|
private battleScene: BattleScene;
|
||||||
|
|
||||||
|
/** The {@linkcode Phaser.GameObjects.Sprite} that represents the foreground of the current time of day */
|
||||||
|
private readonly timeOfDayIconFgs: Phaser.GameObjects.Sprite[] = new Array(2);
|
||||||
|
/** The {@linkcode Phaser.GameObjects.Sprite} that represents the middle-ground of the current time of day */
|
||||||
|
private readonly timeOfDayIconMgs: Phaser.GameObjects.Sprite[] = new Array(2);
|
||||||
|
/** The {@linkcode Phaser.GameObjects.Sprite} that represents the background of the current time of day */
|
||||||
|
private readonly timeOfDayIconBgs: Phaser.GameObjects.Sprite[] = new Array(2);
|
||||||
|
|
||||||
|
/** An array containing all timeOfDayIcon objects for easier iteration */
|
||||||
|
private timeOfDayIcons: Phaser.GameObjects.Sprite[];
|
||||||
|
|
||||||
|
/** A map containing all timeOfDayIcon arrays with a matching string key for easier iteration */
|
||||||
|
private timeOfDayIconPairs: Map<string, Phaser.GameObjects.Sprite[]> = new Map([
|
||||||
|
["bg", this.timeOfDayIconBgs],
|
||||||
|
["mg", this.timeOfDayIconMgs],
|
||||||
|
["fg", this.timeOfDayIconFgs],]);
|
||||||
|
|
||||||
|
/** The current time of day */
|
||||||
|
private currentTime: TimeOfDay = TimeOfDay.ALL;
|
||||||
|
/** The previous time of day */
|
||||||
|
private previousTime: TimeOfDay = TimeOfDay.ALL;
|
||||||
|
|
||||||
|
// Subscribes to required events available on game start
|
||||||
|
private readonly onEncounterPhaseEvent = (event: Event) => this.onEncounterPhase(event);
|
||||||
|
|
||||||
|
private _parentVisible: boolean;
|
||||||
|
/** Is the parent object visible? */
|
||||||
|
public get parentVisible(): boolean {
|
||||||
|
return this._parentVisible;
|
||||||
|
}
|
||||||
|
/** On set, resumes any paused tweens if true */
|
||||||
|
public set parentVisible(visible: boolean) {
|
||||||
|
if (visible && !this._parentVisible) { // Only resume the tweens if parent is newly visible
|
||||||
|
this.timeOfDayIcons?.forEach(
|
||||||
|
icon => this.scene.tweens.getTweensOf(icon).forEach(
|
||||||
|
tween => tween.resume()));
|
||||||
|
}
|
||||||
|
|
||||||
|
this._parentVisible = visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(scene: Phaser.Scene, x: number = 0, y: number = 0) {
|
||||||
|
super(scene, x, y);
|
||||||
|
this.battleScene = this.scene as BattleScene;
|
||||||
|
|
||||||
|
this.setVisible(this.battleScene.showTimeOfDayWidget);
|
||||||
|
if (!this.battleScene.showTimeOfDayWidget) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize all sprites
|
||||||
|
this.timeOfDayIconPairs.forEach(
|
||||||
|
(icons, key) => {
|
||||||
|
for (let i = 0; i < icons.length; i++) {
|
||||||
|
icons[i] = this.scene.add.sprite(0, 0, "dawn_icon_" + key).setOrigin();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Store a flat array of all icons for later
|
||||||
|
this.timeOfDayIcons = [this.timeOfDayIconBgs, this.timeOfDayIconMgs, this.timeOfDayIconFgs].flat();
|
||||||
|
this.add(this.timeOfDayIcons);
|
||||||
|
|
||||||
|
this.battleScene.eventTarget.addEventListener(BattleSceneEventType.ENCOUNTER_PHASE, this.onEncounterPhaseEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a tween animation based on the 'Back' ease algorithm
|
||||||
|
* @returns an array of all tweens in the animation
|
||||||
|
*/
|
||||||
|
private getBackTween(): Phaser.Types.Tweens.TweenBuilderConfig[] {
|
||||||
|
const rotate = {
|
||||||
|
targets: [this.timeOfDayIconMgs[0], this.timeOfDayIconMgs[1]],
|
||||||
|
angle: "+=90",
|
||||||
|
duration: Utils.fixedInt(1500),
|
||||||
|
ease: "Back.easeOut",
|
||||||
|
paused: !this.parentVisible,
|
||||||
|
};
|
||||||
|
const fade = {
|
||||||
|
targets: [this.timeOfDayIconBgs[1], this.timeOfDayIconMgs[1], this.timeOfDayIconFgs[1]],
|
||||||
|
alpha: 0,
|
||||||
|
duration: Utils.fixedInt(500),
|
||||||
|
ease: "Linear",
|
||||||
|
paused: !this.parentVisible,
|
||||||
|
};
|
||||||
|
|
||||||
|
return [rotate, fade];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a tween animation based on the 'Bounce' ease algorithm
|
||||||
|
* @returns an array of all tweens in the animation
|
||||||
|
*/
|
||||||
|
private getBounceTween(): Phaser.Types.Tweens.TweenBuilderConfig[] {
|
||||||
|
const bounce = {
|
||||||
|
targets: [this.timeOfDayIconMgs[0], this.timeOfDayIconMgs[1]],
|
||||||
|
angle: "+=90",
|
||||||
|
duration: Utils.fixedInt(2000),
|
||||||
|
ease: "Bounce.easeOut",
|
||||||
|
paused: !this.parentVisible,
|
||||||
|
};
|
||||||
|
const fade = {
|
||||||
|
targets: [this.timeOfDayIconBgs[1], this.timeOfDayIconMgs[1], this.timeOfDayIconFgs[1]],
|
||||||
|
alpha: 0,
|
||||||
|
duration: Utils.fixedInt(800),
|
||||||
|
ease: "Linear",
|
||||||
|
paused: !this.parentVisible,
|
||||||
|
};
|
||||||
|
|
||||||
|
return [bounce, fade];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Resets all icons to the proper depth, texture, and alpha so they are ready to tween */
|
||||||
|
private resetIcons() {
|
||||||
|
this.moveBelow(this.timeOfDayIconBgs[0], this.timeOfDayIconBgs[1]);
|
||||||
|
this.moveBelow(this.timeOfDayIconMgs[0], this.timeOfDayIconBgs[1]);
|
||||||
|
this.moveBelow(this.timeOfDayIconFgs[0], this.timeOfDayIconFgs[1]);
|
||||||
|
|
||||||
|
this.timeOfDayIconPairs.forEach(
|
||||||
|
(icons, key) => {
|
||||||
|
icons[0].setTexture(TimeOfDay[this.currentTime].toLowerCase() + "_icon_" + key);
|
||||||
|
icons[1].setTexture(TimeOfDay[this.previousTime].toLowerCase() + "_icon_" + key);
|
||||||
|
});
|
||||||
|
this.timeOfDayIconMgs[0].setRotation(-90 * (3.14/180));
|
||||||
|
|
||||||
|
this.timeOfDayIcons.forEach(icon => icon.setAlpha(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Adds the proper tween for all icons */
|
||||||
|
private tweenTimeOfDayIcon() {
|
||||||
|
this.scene.tweens.killTweensOf(this.timeOfDayIcons);
|
||||||
|
|
||||||
|
this.resetIcons();
|
||||||
|
|
||||||
|
// Tween based on the player setting
|
||||||
|
(this.battleScene.timeOfDayAnimation === EaseType.BACK ? this.getBackTween() : this.getBounceTween())
|
||||||
|
.forEach(tween => this.scene.tweens.add(tween));
|
||||||
|
|
||||||
|
// Swaps all elements of the icon arrays by shifting the first element onto the end of the array
|
||||||
|
// This ensures index[0] is always the new time of day icon and index[1] is always the current one
|
||||||
|
this.timeOfDayIconPairs.forEach(
|
||||||
|
icons => icons.push(icons.shift()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Grabs the current time of day from the arena and calls {@linkcode tweenTimeOfDayIcon}
|
||||||
|
* @param event {@linkcode Event} being sent
|
||||||
|
*/
|
||||||
|
private onEncounterPhase(event: Event) {
|
||||||
|
const newTime = this.battleScene.arena.getTimeOfDay();
|
||||||
|
|
||||||
|
if (this.currentTime === newTime) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.currentTime = newTime;
|
||||||
|
this.previousTime = this.currentTime - 1;
|
||||||
|
if (this.previousTime < TimeOfDay.DAWN) {
|
||||||
|
this.previousTime = TimeOfDay.NIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.tweenTimeOfDayIcon();
|
||||||
|
}
|
||||||
|
}
|