From 8858fc24b7b922363b5c9cf44b7e30dc81a3d51b Mon Sep 17 00:00:00 2001 From: chrisgregan Date: Thu, 8 May 2014 15:05:27 +0100 Subject: [PATCH] Multiple scene support - Added Game.MoveToScene, Game.Load and Game.Save commands - Game values and string table now persist between scene loads --- .../Fungus/Scripts/Commands/GameCommands.cs | 85 +++++++++++++++- Assets/Fungus/Scripts/Game.cs | 93 +++++++++++++++++- Assets/Fungus/Scripts/GameController.cs | 37 ++++++- Assets/Fungus/Scripts/PageController.cs | 9 +- Assets/Fungus/Scripts/StringTable.cs | 10 +- Assets/Fungus/Scripts/StringsParser.cs | 4 +- ProjectSettings/EditorBuildSettings.asset | Bin 4104 -> 4208 bytes 7 files changed, 217 insertions(+), 21 deletions(-) diff --git a/Assets/Fungus/Scripts/Commands/GameCommands.cs b/Assets/Fungus/Scripts/Commands/GameCommands.cs index 693e97dd..ea078dcf 100644 --- a/Assets/Fungus/Scripts/Commands/GameCommands.cs +++ b/Assets/Fungus/Scripts/Commands/GameCommands.cs @@ -140,7 +140,38 @@ namespace Fungus // MoveToRoom always resets the command queue so no need to call onComplete } } - + + /** + * Switches to a different scene. + */ + public class MoveToScene : CommandQueue.Command + { + string sceneName; + + public MoveToScene(string _sceneName) + { + if (_sceneName == "") + { + Debug.LogError("Scene name must not be empty"); + return; + } + + sceneName = _sceneName; + } + + public override void Execute(CommandQueue commandQueue, Action onComplete) + { + Game game = Game.GetInstance(); + + game.waiting = true; + + // Fade out screen + game.cameraController.Fade(0f, game.roomFadeDuration / 2f, delegate { + Game.GetInstance().LoadScene(sceneName, true); + }); + } + } + /** * Sets a globally accessible integer value */ @@ -181,7 +212,57 @@ namespace Fungus public override void Execute(CommandQueue commandQueue, Action onComplete) { - Game.GetInstance().stringTable.SetString(key, value); + Game.stringTable.SetString(key, value); + if (onComplete != null) + { + onComplete(); + } + } + } + + /** + * Save the current game state to persistant storage. + */ + public class Save : CommandQueue.Command + { + Action commandAction; + + public Save(string saveName) + { + commandAction = delegate { + Game.GetInstance().SaveGame(saveName); + }; + } + + public override void Execute(CommandQueue commandQueue, Action onComplete) + { + commandAction(); + + if (onComplete != null) + { + onComplete(); + } + } + } + + /** + * Load the game state from persistant storage. + */ + public class Load : CommandQueue.Command + { + Action commandAction; + + public Load(string saveName) + { + commandAction = delegate { + Game.GetInstance().LoadGame(saveName); + }; + } + + public override void Execute(CommandQueue commandQueue, Action onComplete) + { + commandAction(); + if (onComplete != null) { onComplete(); diff --git a/Assets/Fungus/Scripts/Game.cs b/Assets/Fungus/Scripts/Game.cs index 59f39981..4bc6910b 100644 --- a/Assets/Fungus/Scripts/Game.cs +++ b/Assets/Fungus/Scripts/Game.cs @@ -1,6 +1,10 @@ using UnityEngine; using System.Collections; using System.Collections.Generic; +using System.Linq; +using System; +using System.Runtime.Serialization.Formatters.Binary; +using System.IO; /** * @package Fungus An open source library for Unity 3D for creating graphic interactive fiction games. @@ -104,10 +108,10 @@ namespace Fungus * Global dictionary of integer values for storing game state. */ [HideInInspector] - public Dictionary values = new Dictionary(); + static public Dictionary values = new Dictionary(); [HideInInspector] - public StringTable stringTable = new StringTable(); + static public StringTable stringTable = new StringTable(); [HideInInspector] public CommandQueue commandQueue; @@ -323,5 +327,90 @@ namespace Fungus return offset; } + + /** + * Loads a new scene. + * This is useful for splitting a large Fungus game across multiple scene files to reduce peak memory usage. + * All previously loaded assets (including textures) will be released. + * @param sceneName The filename of the scene to load. + * @param saveGame Automatically save the current game state as a checkpoint. + */ + public void LoadScene(string sceneName, bool saveGame) + { + Application.LoadLevel(sceneName); + + if (saveGame) + { + SaveGame("Fungus.Save"); + } + + // Free up memory used by textures in previous scene + Resources.UnloadUnusedAssets(); + } + + /** + * Save the current game state to persistant storage. + * Only the values, string table and current scene are stored. + * @param saveName The name of the saved game data. + */ + public void SaveGame(string saveName) + { + // Store loaded scene name in save data + SetString("Fungus.Scene", Application.loadedLevelName); + + var b = new BinaryFormatter(); + var m = new MemoryStream(); + + // Save values + { + b.Serialize(m, values); + string s = Convert.ToBase64String(m.GetBuffer()); + PlayerPrefs.SetString(saveName + ".values", s); + } + + // Save string table + { + b.Serialize(m, stringTable.stringDict); + string s = Convert.ToBase64String(m.GetBuffer()); + PlayerPrefs.SetString(saveName + ".stringTable", s); + } + } + + /** + * Loads the current game state from persistant storage. + * This will cause the scene specified in the "Fungus.Scene" string to be loaded. + * Each scene in your game should contain the necessary code to restore the current game state based on saved data. + * @param saveName The name of the saved game data. + */ + public void LoadGame(string saveName) + { + // Load values + { + var data = PlayerPrefs.GetString(saveName + ".values"); + if (!string.IsNullOrEmpty(data)) + { + var b = new BinaryFormatter(); + var m = new MemoryStream(Convert.FromBase64String(data)); + values = (Dictionary)b.Deserialize(m); + } + } + + // Load string table + { + var data = PlayerPrefs.GetString(saveName + ".stringTable"); + if (!string.IsNullOrEmpty(data)) + { + var b = new BinaryFormatter(); + var m = new MemoryStream(Convert.FromBase64String(data)); + stringTable.stringDict = b.Deserialize(m) as Dictionary; + } + } + + string sceneName = GetString("Fungus.Scene"); + if (sceneName.Length > 0) + { + LoadScene(sceneName, true); + } + } } } \ No newline at end of file diff --git a/Assets/Fungus/Scripts/GameController.cs b/Assets/Fungus/Scripts/GameController.cs index d80ca9b4..fe93a139 100644 --- a/Assets/Fungus/Scripts/GameController.cs +++ b/Assets/Fungus/Scripts/GameController.cs @@ -39,7 +39,18 @@ namespace Fungus CommandQueue commandQueue = Game.GetInstance().commandQueue; commandQueue.AddCommand(new Command.MoveToRoom(room)); } - + + /** + * Transitions to a different scene. + * This method returns immediately but it queues an asynchronous command for later execution. + * @param sceneName The name of the scene to transition to. + */ + public static void MoveToScene(string sceneName) + { + CommandQueue commandQueue = Game.GetInstance().commandQueue; + commandQueue.AddCommand(new Command.MoveToScene(sceneName)); + } + /** * Wait for a period of time before executing the next command. * This method returns immediately but it queues an asynchronous command for later execution. @@ -72,7 +83,27 @@ namespace Fungus CommandQueue commandQueue = Game.GetInstance().commandQueue; commandQueue.AddCommand(new Command.Call(callAction)); } - + + /** + * Save the current game state to persistant storage. + * @param saveName The name of the saved game data. + */ + public static void Save(string saveName = "Fungus.Save") + { + CommandQueue commandQueue = Game.GetInstance().commandQueue; + commandQueue.AddCommand(new Command.Save(saveName)); + } + + /** + * Load the current game state from persistant storage. + * @param saveName The name of the saved game data. + */ + public static void Load(string saveName = "Fungus.Save") + { + CommandQueue commandQueue = Game.GetInstance().commandQueue; + commandQueue.AddCommand(new Command.Load(saveName)); + } + #endregion #region View Methods @@ -483,7 +514,7 @@ namespace Fungus */ public static string GetString(string key) { - return Game.GetInstance().stringTable.GetString(key); + return Game.stringTable.GetString(key); } #endregion diff --git a/Assets/Fungus/Scripts/PageController.cs b/Assets/Fungus/Scripts/PageController.cs index f2ed0272..992b47d8 100644 --- a/Assets/Fungus/Scripts/PageController.cs +++ b/Assets/Fungus/Scripts/PageController.cs @@ -194,24 +194,21 @@ namespace Fungus public void Say(string sayText, Action sayAction) { mode = Mode.Say; - StringTable stringTable = Game.GetInstance().stringTable; - string subbedText = stringTable.SubstituteStrings(sayText); + string subbedText = Game.stringTable.SubstituteStrings(sayText); continueAction = sayAction; WriteStory(subbedText); } public void AddOption(string optionText, Action optionAction) { - StringTable stringTable = Game.GetInstance().stringTable; - string subbedText = stringTable.FormatLinkText(stringTable.SubstituteStrings(optionText)); + string subbedText = Game.stringTable.FormatLinkText(Game.stringTable.SubstituteStrings(optionText)); options.Add(new Option(subbedText, optionAction)); } public void Choose(string _chooseText) { mode = Mode.Choose; - StringTable stringTable = Game.GetInstance().stringTable; - string subbedText = stringTable.SubstituteStrings(_chooseText); + string subbedText = Game.stringTable.SubstituteStrings(_chooseText); WriteStory(subbedText); } diff --git a/Assets/Fungus/Scripts/StringTable.cs b/Assets/Fungus/Scripts/StringTable.cs index 4b2dad64..29f035d9 100644 --- a/Assets/Fungus/Scripts/StringTable.cs +++ b/Assets/Fungus/Scripts/StringTable.cs @@ -11,14 +11,14 @@ namespace Fungus */ public class StringTable { - Dictionary stringTable = new Dictionary(); + public Dictionary stringDict = new Dictionary(); /** * Removes all strings from the string table. */ public void ClearStringTable() { - stringTable.Clear(); + stringDict.Clear(); } /** @@ -26,9 +26,9 @@ namespace Fungus */ public string GetString(string key) { - if (stringTable.ContainsKey(key)) + if (stringDict.ContainsKey(key)) { - return stringTable[key]; + return stringDict[key]; } return ""; } @@ -38,7 +38,7 @@ namespace Fungus */ public void SetString(string key, string value) { - stringTable[key] = value; + stringDict[key] = value; } /** diff --git a/Assets/Fungus/Scripts/StringsParser.cs b/Assets/Fungus/Scripts/StringsParser.cs index 4785b324..df812dc8 100644 --- a/Assets/Fungus/Scripts/StringsParser.cs +++ b/Assets/Fungus/Scripts/StringsParser.cs @@ -31,8 +31,6 @@ namespace Fungus void ProcessText(string text) { - StringTable stringTable = Game.GetInstance().stringTable; - // Split text into lines. Add a newline at end to ensure last command is always parsed string[] lines = Regex.Split(text + "\n", "(?<=\n)"); @@ -90,7 +88,7 @@ namespace Fungus // Trim off last newline blockBuffer = blockBuffer.TrimEnd( '\r', '\n', ' ', '\t'); - stringTable.SetString(blockTag, blockBuffer); + Game.stringTable.SetString(blockTag, blockBuffer); } // Prepare to parse next block diff --git a/ProjectSettings/EditorBuildSettings.asset b/ProjectSettings/EditorBuildSettings.asset index c6035908987134f1a83fa3caac297772973c8a60..318a513d0cccf80cd7e8d4a64a43f6f1fdb86184 100644 GIT binary patch delta 133 zcmeBB_@KbSz`%HyfkB{PBgYL!#)8cc8I}2Rm>7VfK&%7Aj>W~PCB^z~rFrS4#jX{J oxdl0?`oYPmd8x(v{v{cyMPRmGX