Browse Source

Multiple scene support

- Added Game.MoveToScene, Game.Load and Game.Save commands
- Game values and string table now persist between scene loads
master
chrisgregan 11 years ago
parent
commit
8858fc24b7
  1. 85
      Assets/Fungus/Scripts/Commands/GameCommands.cs
  2. 93
      Assets/Fungus/Scripts/Game.cs
  3. 37
      Assets/Fungus/Scripts/GameController.cs
  4. 9
      Assets/Fungus/Scripts/PageController.cs
  5. 10
      Assets/Fungus/Scripts/StringTable.cs
  6. 4
      Assets/Fungus/Scripts/StringsParser.cs
  7. BIN
      ProjectSettings/EditorBuildSettings.asset

85
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();

93
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<string, int> values = new Dictionary<string, int>();
static public Dictionary<string, int> values = new Dictionary<string, int>();
[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<string, int>)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, string>;
}
}
string sceneName = GetString("Fungus.Scene");
if (sceneName.Length > 0)
{
LoadScene(sceneName, true);
}
}
}
}

37
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

9
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);
}

10
Assets/Fungus/Scripts/StringTable.cs

@ -11,14 +11,14 @@ namespace Fungus
*/
public class StringTable
{
Dictionary<string, string> stringTable = new Dictionary<string, string>();
public Dictionary<string, string> stringDict = new Dictionary<string, string>();
/**
* 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;
}
/**

4
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

BIN
ProjectSettings/EditorBuildSettings.asset

Binary file not shown.
Loading…
Cancel
Save