diff --git a/src/MarbleGame.hx b/src/MarbleGame.hx index 8439642d..54ad3e9c 100644 --- a/src/MarbleGame.hx +++ b/src/MarbleGame.hx @@ -1,5 +1,6 @@ package src; +import gui.ReplayNameDlg; import gui.ConsoleDlg; import src.Replay; import touch.TouchInput; @@ -218,7 +219,11 @@ class MarbleGame { world.setCursorLock(false); exitGameDlg = new ExitGameDlg((sender) -> { canvas.popDialog(exitGameDlg); - quitMission(); + if (world.isRecording) { + MarbleGame.canvas.pushDialog(new ReplayNameDlg(() -> {quitMission();})); + } else { + quitMission(); + } }, (sender) -> { canvas.popDialog(exitGameDlg); paused = !paused; @@ -247,9 +252,6 @@ class MarbleGame { var pmg = new PlayMissionGui(); PlayMissionGui.currentSelectionStatic = world.mission.index; PlayMissionGui.currentGameStatic = world.mission.game; - if (world.isRecording) { - world.saveReplay(); - } world.dispose(); world = null; canvas.setContent(pmg); @@ -263,7 +265,6 @@ class MarbleGame { world.dispose(); } world = new MarbleWorld(scene, scene2d, mission, toRecord); - toRecord = false; world.init(); } diff --git a/src/MarbleWorld.hx b/src/MarbleWorld.hx index 2c846613..00d12d56 100644 --- a/src/MarbleWorld.hx +++ b/src/MarbleWorld.hx @@ -1,5 +1,7 @@ package src; +import gui.ReplayCenterGui; +import gui.ReplayNameDlg; import collision.Collision; import shapes.MegaMarble; import shapes.Blast; @@ -1162,9 +1164,7 @@ class MarbleWorld extends Scheduler { } this.setCursorLock(false); this.dispose(); - var pmg = new PlayMissionGui(); - PlayMissionGui.currentSelectionStatic = mission.index + 1; - MarbleGame.canvas.setContent(pmg); + MarbleGame.canvas.setContent(new ReplayCenterGui()); #if js var pointercontainer = js.Browser.document.querySelector("#pointercontainer"); pointercontainer.hidden = false; @@ -1636,7 +1636,8 @@ class MarbleWorld extends Scheduler { this.finishYaw = this.marble.camera.CameraYaw; this.finishPitch = this.marble.camera.CameraPitch; displayAlert("Congratulations! You've finished!"); - this.schedule(this.timeState.currentAttemptTime + 2, () -> cast showFinishScreen()); + if (!this.isWatching) + this.schedule(this.timeState.currentAttemptTime + 2, () -> cast showFinishScreen()); // Stop the ongoing sounds if (timeTravelSound != null) { timeTravelSound.stop(); @@ -1650,16 +1651,17 @@ class MarbleWorld extends Scheduler { } function showFinishScreen() { + if (this.isWatching) + return 0; Console.log("State End"); var egg:EndGameGui = null; #if js var pointercontainer = js.Browser.document.querySelector("#pointercontainer"); pointercontainer.hidden = false; #end - if (this.isRecording) { + this.schedule(this.timeState.currentAttemptTime + 3, () -> { this.isRecording = false; // Stop recording here - this.saveReplay(); - } + }, "stopRecordingTimeout"); if (Util.isTouchDevice()) { MarbleGame.instance.touchInput.setControlsEnabled(false); } @@ -1667,24 +1669,53 @@ class MarbleWorld extends Scheduler { if (Util.isTouchDevice()) { MarbleGame.instance.touchInput.hideControls(@:privateAccess this.playGui.playGuiCtrl); } - this.dispose(); - var pmg = new PlayMissionGui(); - PlayMissionGui.currentSelectionStatic = mission.index + 1; - MarbleGame.canvas.setContent(pmg); - #if js - pointercontainer.hidden = false; - #end - }, (sender) -> { - MarbleGame.canvas.popDialog(egg); - this.setCursorLock(true); - this.restart(true); - #if js - pointercontainer.hidden = true; - #end - if (Util.isTouchDevice()) { - MarbleGame.instance.touchInput.setControlsEnabled(true); + var endGameCode = () -> { + this.dispose(); + var pmg = new PlayMissionGui(); + PlayMissionGui.currentSelectionStatic = mission.index + 1; + MarbleGame.canvas.setContent(pmg); + #if js + pointercontainer.hidden = false; + #end + } + if (MarbleGame.instance.toRecord) { + MarbleGame.canvas.pushDialog(new ReplayNameDlg(endGameCode)); + } else { + endGameCode(); + } + }, (sender) -> { + var restartGameCode = () -> { + MarbleGame.canvas.popDialog(egg); + this.setCursorLock(true); + this.restart(true); + #if js + pointercontainer.hidden = true; + #end + if (Util.isTouchDevice()) { + MarbleGame.instance.touchInput.setControlsEnabled(true); + } + // @:privateAccess playGui.playGuiCtrl.render(scene2d); + } + if (MarbleGame.instance.toRecord) { + MarbleGame.canvas.pushDialog(new ReplayNameDlg(() -> { + this.isRecording = true; + restartGameCode(); + })); + } else { + restartGameCode(); + } + }, (sender) -> { + var nextLevelCode = () -> { + var nextMission = mission.getNextMission(); + if (nextMission != null) { + MarbleGame.instance.playMission(nextMission); + } + } + if (MarbleGame.instance.toRecord) { + MarbleGame.canvas.pushDialog(new ReplayNameDlg(nextLevelCode)); + } else { + nextLevelCode(); } - // @:privateAccess playGui.playGuiCtrl.render(scene2d); }, mission, finishTime); MarbleGame.canvas.pushDialog(egg); this.setCursorLock(false); @@ -1962,33 +1993,42 @@ class MarbleWorld extends Scheduler { public function saveReplay() { this.replay.name = MarbleGame.instance.recordingName; - var replayBytes = this.replay.write(); #if hl - // hxd.File.saveAs(replayBytes, { - // title: 'Save Replay', - // fileTypes: [ - // { - // name: "Replay (*.mbr)", - // extensions: ["mbr"] - // } - // ], - // defaultPath: 'data/replay/${this.mission.title}${this.timeState.gameplayClock}.mbr' - // }); sys.FileSystem.createDirectory(haxe.io.Path.join([Settings.settingsDir, "data", "replays"])); var replayPath = haxe.io.Path.join([ Settings.settingsDir, "data", "replays", - '${this.mission.title}${this.timeState.gameplayClock}.mbr' + '${this.replay.name}.mbr' ]); + if (sys.FileSystem.exists(replayPath)) { + var count = 1; + var found = false; + while (!found) { + replayPath = haxe.io.Path.join([ + Settings.settingsDir, + "data", + "replays", + '${this.replay.name} (${count}).mbr' + ]); + if (!sys.FileSystem.exists(replayPath)) { + this.replay.name += ' (${count})'; + found = true; + } else { + count++; + } + } + } + var replayBytes = this.replay.write(); sys.io.File.saveBytes(replayPath, replayBytes); #end #if js + var replayBytes = this.replay.write(); var blob = new js.html.Blob([replayBytes.getData()], { type: 'application/octet-stream' }); var url = js.html.URL.createObjectURL(blob); - var fname = '${this.mission.title}${this.timeState.gameplayClock}.mbr'; + var fname = '${this.replay.name}.mbr'; var element = js.Browser.document.createElement('a'); element.setAttribute('href', url); element.setAttribute('download', fname); diff --git a/src/gui/EndGameGui.hx b/src/gui/EndGameGui.hx index 4e82a844..67591c51 100644 --- a/src/gui/EndGameGui.hx +++ b/src/gui/EndGameGui.hx @@ -18,7 +18,7 @@ class EndGameGui extends GuiControl { var scoreSubmitted:Bool = false; - public function new(continueFunc:GuiControl->Void, restartFunc:GuiControl->Void, mission:Mission, timeState:TimeState) { + public function new(continueFunc:GuiControl->Void, restartFunc:GuiControl->Void, nextLevelFunc:GuiControl->Void, mission:Mission, timeState:TimeState) { super(); this.horizSizing = Width; this.vertSizing = Height; @@ -77,12 +77,7 @@ class EndGameGui extends GuiControl { nextLevelBtn.vertSizing = Height; nextLevelBtn.position = new Vector(0, 0); nextLevelBtn.extent = new Vector(130, 110); - nextLevelBtn.pressedAction = (e) -> { - var nextMission = mission.getNextMission(); - if (nextMission != null) { - cast(this.parent, Canvas).marbleGame.playMission(nextMission); - } - }; + nextLevelBtn.pressedAction = (e) -> nextLevelFunc(nextLevelBtn); nextLevel.addChild(nextLevelBtn); function setButtonStates(enabled:Bool) { diff --git a/src/gui/PlayMissionGui.hx b/src/gui/PlayMissionGui.hx index b6deb686..1bee2026 100644 --- a/src/gui/PlayMissionGui.hx +++ b/src/gui/PlayMissionGui.hx @@ -65,6 +65,8 @@ class PlayMissionGui extends GuiImage { currentCategory = PlayMissionGui.currentCategoryStatic; currentGame = PlayMissionGui.currentGameStatic; + MarbleGame.instance.toRecord = false; + function chooseBg() { if (currentGame == "gold") return ResourceLoader.getImage('data/ui/backgrounds/gold/${cast (Math.floor(Util.lerp(1, 12, Math.random())), Int)}.jpg'); @@ -667,7 +669,8 @@ class PlayMissionGui extends GuiImage { pmRecord.position = new Vector(247, 46); pmRecord.extent = new Vector(43, 43); pmRecord.pressedAction = (sender) -> { - cast(this.parent, Canvas).pushDialog(new ReplayNameDlg()); + MarbleGame.instance.toRecord = true; + MarbleGame.canvas.pushDialog(new MessageBoxOkDlg("The next mission you play will be recorded.")); }; pmMorePopDlg.addChild(pmRecord); diff --git a/src/gui/ReplayNameDlg.hx b/src/gui/ReplayNameDlg.hx index 49c421db..84beea3b 100644 --- a/src/gui/ReplayNameDlg.hx +++ b/src/gui/ReplayNameDlg.hx @@ -7,7 +7,7 @@ import src.ResourceLoader; import src.Settings; class ReplayNameDlg extends GuiControl { - public function new() { + public function new(callback:Void->Void) { super(); var text = "Enter a name for the recording"; this.horizSizing = Width; @@ -59,6 +59,13 @@ class ReplayNameDlg extends GuiControl { textInput.text.selectionTile = h2d.Tile.fromColor(0x808080, 0, hxd.Math.ceil(textInput.text.font.lineHeight)); textFrame.addChild(textInput); + textInput.text.text = MarbleGame.instance.world.mission.title; + if (MarbleGame.instance.world.finishTime == null) { + textInput.text.text += " Unfinished Run"; + } else { + textInput.text.text += " " + MarbleGame.instance.world.finishTime.gameplayClock; + } + var yesButton = new GuiButton(loadButtonImages("data/ui/common/ok")); yesButton.position = new Vector(171, 124); yesButton.extent = new Vector(95, 45); @@ -66,9 +73,10 @@ class ReplayNameDlg extends GuiControl { yesButton.accelerator = hxd.Key.ENTER; yesButton.pressedAction = (sender) -> { if (StringTools.trim(textInput.text.text) != "") { - MarbleGame.instance.toRecord = true; MarbleGame.instance.recordingName = textInput.text.text; MarbleGame.canvas.popDialog(this); + MarbleGame.instance.world.saveReplay(); + callback(); } } yesNoFrame.addChild(yesButton); @@ -80,6 +88,7 @@ class ReplayNameDlg extends GuiControl { noButton.accelerator = hxd.Key.ESCAPE; noButton.pressedAction = (sender) -> { MarbleGame.canvas.popDialog(this); + callback(); } yesNoFrame.addChild(noButton);