diff --git a/src/endgamemodal.ts b/src/endgamemodal.ts new file mode 100644 index 0000000..53e7918 --- /dev/null +++ b/src/endgamemodal.ts @@ -0,0 +1,78 @@ +import {withCamera} from "./layout.ts"; +import {D} from "./engine/public.ts"; +import {FG_BOLD, FG_TEXT} from "./colors.ts"; +import {AlignX, Point, Rect, Size} from "./engine/datatypes.ts"; +import {DrawPile} from "./drawpile.ts"; +import {addButton} from "./button.ts"; + +const WIDTH = 384; +const HEIGHT = 384; + +export class EndgameModal { + #isShown: boolean; + #drawpile: DrawPile; + + constructor() { + this.#isShown = false; + this.#drawpile = new DrawPile(); + + // debug + } + + get isShown(): boolean { + return this.#isShown; + } + + show() { + this.#isShown = true; + } + + update() { + withCamera("FullscreenPopover", () => this.#update()) + } + + draw() { + withCamera("FullscreenPopover", () => this.#draw()) + } + + #update() { + this.#drawpile.clear(); + addButton( + this.#drawpile, + "Appoint a Successor", + new Rect( + new Point(0, HEIGHT - 32), new Size(WIDTH, 32) + ), + true, + () => { + alert("beep"); + } + ) + this.#drawpile.executeOnClick(); + } + + #draw() { + D.drawText("It is time to announce the sentence of fate.", new Point(0, 0), FG_TEXT) + D.drawText("You are no longer a fledgling. Your new rank:", new Point(0, 32), FG_TEXT) + D.drawText("Progenitor", new Point(WIDTH/2, 64), FG_BOLD, {alignX: AlignX.Center}) + D.drawText("You have achieved a DOMICILE STATUS of:", new Point(0, 96), FG_TEXT) + D.drawText("Guest House", new Point(WIDTH/2, 128), FG_BOLD, {alignX: AlignX.Center}) + D.drawText("where you live with many friends.", new Point(0, 160), FG_TEXT) + D.drawText("You have achieved:", new Point(0, 192), FG_TEXT) + D.drawText("48 items purloined\n96 vampiric skills\n50 mortal servants", new Point(WIDTH/2, 224), FG_TEXT, {alignX: AlignX.Center}) + D.drawText("48 \n96 \n50 ", new Point(WIDTH/2, 224), FG_BOLD, {alignX: AlignX.Center}) + D.drawText("That feels like a lot!", new Point(0, 288), FG_TEXT) + D.drawText("Your reign continues unimpeded from the shadows. It is now time to", new Point(0, 320), FG_TEXT, {forceWidth: WIDTH}) + + this.#drawpile.draw(); + } + + get blocksHud(): boolean { + return true; + } +} + +let active = new EndgameModal(); +export function getEndgameModal() { + return active; +} \ No newline at end of file diff --git a/src/game.ts b/src/game.ts index 105bf2e..e737064 100644 --- a/src/game.ts +++ b/src/game.ts @@ -1,13 +1,13 @@ import {BG_OUTER} from "./colors.ts"; import {D, I} from "./engine/public.ts"; import {IGame, Point, Size} from "./engine/datatypes.ts"; -import {getHuntMode} from "./huntmode.ts"; -import {getPageLocation, Page, withCamera} from "./layout.ts"; -import {getHud} from "./hud.ts"; +import {getPageLocation, Page} from "./layout.ts"; import {getHotbar, Hotbar} from "./hotbar.ts"; import {getSkillsModal, SkillsModal} from "./skillsmodal.ts"; import {getSleepModal, SleepModal} from "./sleepmodal.ts"; -import {getEndgameModal} from "./vnmodal.ts"; +import {getVNModal, VNModal} from "./vnmodal.ts"; +import {Gameplay, getGameplay} from "./gameplay.ts"; +import {getEndgameModal} from "./endgamemodal.ts"; class MenuCamera { // measured in whole screens @@ -33,6 +33,7 @@ class MenuCamera { export class Game implements IGame { camera: MenuCamera; page: Page; + #mainThing: Gameplay | VNModal | null; #bottomThing: SkillsModal | SleepModal | Hotbar | null; constructor() { @@ -42,16 +43,13 @@ export class Game implements IGame { }); this.page = "Gameplay"; + this.#mainThing = null; this.#bottomThing = null; } update() { - if (I.isKeyPressed("w")) { - this.page = "Gameplay" - } - if (I.isKeyPressed("s")) { - this.page = "Thralls" - } + if (I.isKeyPressed("w")) { this.page = "Gameplay" } + if (I.isKeyPressed("s")) { this.page = "Thralls" } this.camera.target = getPageLocation(this.page); D.camera = new Point( @@ -82,23 +80,22 @@ export class Game implements IGame { } updateGameplay() { + this.#chooseMainThing(); this.#chooseBottomThing(); - withCamera("Gameplay", () => { - getHuntMode().update(); - }); - withCamera("HUD", () => { getHud().update() }) - this.#bottomThing?.update(); - getEndgameModal().update(); + this.#mainThing?.update(); + + if (!this.#mainThing?.blocksHud) { + this.#bottomThing?.update(); + } } drawGameplay() { - withCamera("Gameplay", () => { - getHuntMode().draw(); - }); - withCamera("HUD", () => { getHud().draw() }) - this.#bottomThing?.draw() - getEndgameModal().draw(); + this.#mainThing?.draw(); + + if (!this.#mainThing?.blocksHud) { + this.#bottomThing?.draw() + } } #chooseBottomThing() { @@ -126,8 +123,21 @@ export class Game implements IGame { this.#bottomThing = getHotbar(); } - // withCamera("Hotbar", () => { getHotbar().draw() }) + #chooseMainThing() { + let vnModal = getVNModal(); + if (vnModal.isShown) { + this.#mainThing = vnModal; + return; + } + + let endgameModal = getEndgameModal(); + if (endgameModal.isShown) { + this.#mainThing = endgameModal; + return; + } + + this.#mainThing = getGameplay(); + } } - export let game = new Game(); \ No newline at end of file diff --git a/src/gameplay.ts b/src/gameplay.ts new file mode 100644 index 0000000..15f8f4e --- /dev/null +++ b/src/gameplay.ts @@ -0,0 +1,29 @@ +import {withCamera} from "./layout.ts"; +import {getHuntMode} from "./huntmode.ts"; +import {getHud} from "./hud.ts"; + +export class Gameplay { + update() { + withCamera("Gameplay", () => { + getHuntMode().update(); + }); + withCamera("HUD", () => { getHud().update() }) + } + + draw() { + withCamera("Gameplay", () => { + getHuntMode().draw(); + }); + withCamera("HUD", () => { getHud().draw() }) + } + + get blocksHud(): boolean { + return false; + } +} + +let active = new Gameplay(); +export function getGameplay(): Gameplay { + return active; +} + diff --git a/src/statemanager.ts b/src/statemanager.ts index 9dc597b..15e97af 100644 --- a/src/statemanager.ts +++ b/src/statemanager.ts @@ -1,8 +1,9 @@ import {getPlayerProgress} from "./playerprogress.ts"; import {getHuntMode} from "./huntmode.ts"; import {getSleepModal} from "./sleepmodal.ts"; -import {getEndgameModal} from "./vnmodal.ts"; +import {getVNModal} from "./vnmodal.ts"; import {getScorer} from "./scorer.ts"; +import {getEndgameModal} from "./endgamemodal.ts"; const N_TURNS: number = 9; @@ -18,16 +19,17 @@ export class StateManager { } advance() { - this.#turn += 1; + getSleepModal().setShown(false); - if (this.#turn <= N_TURNS) { + if (this.#turn + 1 <= N_TURNS) { + this.#turn += 1; getPlayerProgress().refill(); getHuntMode().replaceMap(); - getSleepModal().setShown(false); } else { // TODO: Play a specific scene let ending = getScorer().pickEnding(); - getEndgameModal().play(ending.scene); + getVNModal().play(ending.scene); + getEndgameModal().show(); } } diff --git a/src/vnmodal.ts b/src/vnmodal.ts index ffc4ec9..c217744 100644 --- a/src/vnmodal.ts +++ b/src/vnmodal.ts @@ -1,13 +1,13 @@ import {D, I} from "./engine/public.ts"; -import {AlignX, AlignY, Color, Point} from "./engine/datatypes.ts"; -import {BG_OUTER, FG_BOLD} from "./colors.ts"; +import {AlignX, AlignY, Point} from "./engine/datatypes.ts"; +import {FG_BOLD} from "./colors.ts"; import {withCamera} from "./layout.ts"; import {VNScene, VNSceneMessage, VNScenePart} from "./vnscene.ts"; const WIDTH = 384; const HEIGHT = 384; -class VNModal { +export class VNModal { #scene: VNScene | null; #nextIndex = 0; #cathexis: SceneCathexis | null; @@ -18,6 +18,10 @@ class VNModal { this.#cathexis = null; } + get blocksHud(): boolean { + return true; + } + get isShown(): boolean { return this.#scene != null; } @@ -26,37 +30,40 @@ class VNModal { this.#scene = scene this.#nextIndex = 0; this.#cathexis = null; + + this.#fixCathexis(); } #fixCathexis() { - if (this.#cathexis?.isDone()) { - this.#cathexis = null; - } - if (this.#scene == null) { - return; - } - if (this.#cathexis == null) { - let ix = this.#nextIndex - if (ix < this.#scene?.length) { - this.#cathexis = createCathexis(this.#scene[ix]) - this.#nextIndex += 1; - } else { - this.#scene = null; + while (true) { + if (this.#cathexis?.isDone()) { + this.#cathexis = null; + } + if (this.#cathexis != null) { + return; + } + + if (this.#scene == null) { + return; + } + if (this.#cathexis == null) { + let ix = this.#nextIndex + if (ix < this.#scene?.length) { + this.#cathexis = createCathexis(this.#scene[ix]) + this.#nextIndex += 1; + } else { + this.#scene = null; + } } } } update() { this.#fixCathexis() - if (!this.isShown) { return } - withCamera("FullscreenPopover", () => this.#update()) } draw() { - if (!this.isShown) { return } - - D.fillRect(new Point(0, 0), D.size, new Color(BG_OUTER.r, BG_OUTER.g, BG_OUTER.b, 255)); withCamera("FullscreenPopover", () => this.#draw()) } @@ -86,10 +93,12 @@ function createCathexis(part: VNScenePart): SceneCathexis { class SceneMessageCathexis { #message: VNSceneMessage; #done: boolean; + #gotOneFrame: boolean; constructor (message: VNSceneMessage) { this.#message = message; this.#done = false; + this.#gotOneFrame = false; } isDone() { @@ -97,8 +106,11 @@ class SceneMessageCathexis { } update() { + let firstFrame = !this.#gotOneFrame; + this.#gotOneFrame = true; + // TODO: SFX - if (I.isAnythingPressed()) { + if (!firstFrame && I.isAnythingPressed()) { this.#done = true; } } @@ -113,6 +125,6 @@ class SceneMessageCathexis { } let active: VNModal = new VNModal(); -export function getEndgameModal() { +export function getVNModal() { return active; } \ No newline at end of file