Browse Source

Miscellaneous refactors to hide complexity

- Added GameController facade class to hide complexity and provide a
single place to access all Fungus functionality
- Removed existing facade methods on Game (redundant)
- Removed Room.OnLeave (not necessary, and possibly dangerous)
- Renamed AnimationListener.OnAnimationEvent() to CallRoomMethod (more
descriptive).
- Button component will now use existing Collider2D if one exists.
- Game component now manages CameraController configuration
- Game now adds CameraController and CommandQueue at runtime instead of
in editor (less user configuration)
- CommandQueue now owns the methods for executing command methods
- Added StringTable class to manage key/string lookups
- Moved SubstituteStrings() and FormatLinkText() to new StringTable
class
- Room.Enter() method is now private to hide implementation details
- Updated example project to match changes
master
chrisgregan 11 years ago
parent
commit
3c422f234c
  1. 13
      Assets/Fungus/Scripts/AnimationListener.cs
  2. 20
      Assets/Fungus/Scripts/Button.cs
  3. 22
      Assets/Fungus/Scripts/CameraController.cs
  4. 40
      Assets/Fungus/Scripts/CommandQueue.cs
  5. 27
      Assets/Fungus/Scripts/Commands.cs
  6. 117
      Assets/Fungus/Scripts/Game.cs
  7. 267
      Assets/Fungus/Scripts/GameController.cs
  8. 8
      Assets/Fungus/Scripts/GameController.cs.meta
  9. 50
      Assets/Fungus/Scripts/Page.cs
  10. 288
      Assets/Fungus/Scripts/Room.cs
  11. 71
      Assets/Fungus/Scripts/StringTable.cs
  12. 8
      Assets/Fungus/Scripts/StringTable.cs.meta
  13. 4
      Assets/Fungus/Scripts/StringsParser.cs
  14. BIN
      Assets/FungusExample/Animations/GreenAlienWalk.anim
  15. BIN
      Assets/FungusExample/Scenes/Example.unity

13
Assets/Fungus/Scripts/AnimationListener.cs

@ -3,10 +3,16 @@ using System.Collections;
using Fungus;
// Listens for animation events
// The string parameter specifies a method name on the active room class
// Usage:
// 1. Attach this script to the animated sprite that you want to listen to for events.
// 2. Add an event on the animation timeline
// 3. Edit the event and choose the 'CallRoomMethod' function
// 4. In the string parameters box, enter the name of the method to call in the active Room's script.
public class AnimationListener : MonoBehaviour
{
void OnAnimationEvent(string methodName)
// Handler method for animation events
// The string event parameter is used to call a named method on the active room class
void CallRoomMethod(string methodName)
{
Room room = Game.GetInstance().activeRoom;
if (room == null)
@ -14,6 +20,7 @@ public class AnimationListener : MonoBehaviour
return;
}
room.AnimationEvent(methodName);
CommandQueue commandQueue = Game.GetInstance().commandQueue;
commandQueue.CallCommandMethod(room.gameObject, methodName);
}
}

20
Assets/Fungus/Scripts/Button.cs

@ -8,13 +8,13 @@ namespace Fungus
// Simple button handler class.
// When the user taps on the button, the named method is called on ancestor game objects (if it exists).
[RequireComponent (typeof (SpriteRenderer))]
[RequireComponent (typeof (BoxCollider2D))]
[RequireComponent (typeof (Collider2D))]
public class Button : MonoBehaviour
{
public Action buttonAction;
public SpriteRenderer spriteRenderer;
// Makes a sprite into a clickable button
// Makes a sprite clickable by attaching a Button component (and BoxCollider2D if required)
public static void MakeButton(SpriteRenderer _spriteRenderer, Action _buttonAction)
{
if (_spriteRenderer == null)
@ -30,7 +30,12 @@ namespace Fungus
Destroy(oldButton);
}
// This will automatically add a BoxCollider2d if none currently exists
// Add a BoxCollider2d if none currently exists
if (_spriteRenderer.gameObject.GetComponent<Collider2D>() == null)
{
_spriteRenderer.gameObject.AddComponent<BoxCollider2D>();
}
Button button = _spriteRenderer.gameObject.AddComponent<Button>();
button.buttonAction = _buttonAction;
button.spriteRenderer = _spriteRenderer;
@ -44,13 +49,8 @@ namespace Fungus
return;
}
Room room = Game.GetInstance().activeRoom;
if (room == null)
{
return;
}
room.ExecuteCommandMethod(buttonAction);
CommandQueue commandQueue = Game.GetInstance().commandQueue;
commandQueue.CallCommandMethod(buttonAction);
}
}
}

22
Assets/Fungus/Scripts/CameraController.cs

@ -10,13 +10,15 @@ namespace Fungus
// Supports several types of camera transition including snap, pan & fade.
public class CameraController : MonoBehaviour
{
// Fixed Z coordinate of camera
public float cameraZ = - 10f;
Game game;
Camera mainCamera;
float fadeAlpha = 0f;
void Start()
{
game = Game.GetInstance();
GameObject cameraObject = GameObject.FindGameObjectWithTag("MainCamera");
if (cameraObject == null)
{
@ -31,10 +33,6 @@ namespace Fungus
}
}
public Texture2D fadeTexture;
public float fadeAlpha = 1f;
void OnGUI()
{
int drawDepth = -1000;
@ -45,7 +43,7 @@ namespace Fungus
// 0 = scene fully obscured
GUI.color = new Color(1,1,1, 1f - fadeAlpha);
GUI.depth = drawDepth;
GUI.DrawTexture(new Rect(0, 0, Screen.width, Screen.height), fadeTexture);
GUI.DrawTexture(new Rect(0, 0, Screen.width, Screen.height), game.fadeTexture);
}
}
@ -114,6 +112,7 @@ namespace Fungus
PanToView(view, 0, null);
}
// Moves camera from current position to a target View over a period of time
public void PanToView(View view, float duration, Action arriveAction)
{
if (duration == 0f)
@ -151,6 +150,7 @@ namespace Fungus
timer = duration;
}
// Apply smoothed lerp to camera position and orthographic size
float t = timer / duration;
mainCamera.orthographicSize = Mathf.Lerp(startSize, endSize, Mathf.SmoothStep(0f, 1f, t));
mainCamera.transform.position = Vector3.Lerp(startPos, endPos, Mathf.SmoothStep(0f, 1f, t));
@ -166,13 +166,13 @@ namespace Fungus
}
}
// Moves camera smoothly through a sequence of Views over a period of time
public void PanToPath(View[] viewList, float duration, Action arriveAction)
{
List<Vector3> pathList = new List<Vector3>();
// Note: We use the z coord to tween the camera orthographic size
// Add current camera position as first point in path
// Note: We use the z coord to tween the camera orthographic size
Vector3 startPos = new Vector3(mainCamera.transform.position.x,
mainCamera.transform.position.y,
mainCamera.orthographicSize);
@ -218,7 +218,7 @@ namespace Fungus
void SetCameraZ()
{
mainCamera.transform.position = new Vector3(mainCamera.transform.position.x, mainCamera.transform.position.y, cameraZ);
mainCamera.transform.position = new Vector3(mainCamera.transform.position.x, mainCamera.transform.position.y, game.cameraZ);
}
}
}

40
Assets/Fungus/Scripts/CommandQueue.cs

@ -9,14 +9,6 @@ namespace Fungus
// When a command completes, the next command is popped from the queue and exectuted.
public class CommandQueue : MonoBehaviour
{
[HideInInspector]
public CameraController cameraController;
public void Start()
{
cameraController = Game.GetInstance().GetComponent<CameraController>();
}
// Base class for commands used with the CommandQueue
public abstract class Command
{
@ -25,18 +17,21 @@ namespace Fungus
List<Command> commandList = new List<Command>();
public void AddCommand(Command command)
// Adds a command to the queue for later execution
public virtual void AddCommand(Command command)
{
commandList.Add(command);
}
public void Reset()
// Clears all queued commands from the list
public virtual void Reset()
{
StopAllCoroutines();
commandList.Clear();
}
public void Execute()
// Executes the first command in the queue.
// When this command completes, the next command in the queue is executed.
public virtual void Execute()
{
if (commandList.Count == 0)
{
@ -50,5 +45,26 @@ namespace Fungus
Execute();
});
}
// Calls a named method on a game object to populate the command queue.
// The command queue is then executed.
public void CallCommandMethod(GameObject target, string methodName)
{
Reset();
target.SendMessage(methodName, SendMessageOptions.DontRequireReceiver);
Execute();
}
// Calls an Action delegate method to populate the command queue.
// The command queue is then executed.
public void CallCommandMethod(Action method)
{
Reset();
if (method != null)
{
method();
}
Execute();
}
}
}

27
Assets/Fungus/Scripts/Commands.cs

@ -77,8 +77,10 @@ namespace Fungus
public override void Execute(CommandQueue commandQueue, Action onComplete)
{
commandQueue.cameraController.SnapToView(view);
Game.GetInstance().activeView = view;
Game game = Game.GetInstance();
game.cameraController.SnapToView(view);
game.activeView = view;
// Set the first page component found (if any) as the active page
Page page = view.gameObject.GetComponentInChildren<Page>();
@ -261,7 +263,7 @@ namespace Fungus
public override void Execute(CommandQueue commandQueue, Action onComplete)
{
Game.GetInstance().SetFlag(key, value);
Game.GetInstance().state.SetFlag(key, value);
if (onComplete != null)
{
onComplete();
@ -283,7 +285,7 @@ namespace Fungus
public override void Execute(CommandQueue commandQueue, Action onComplete)
{
Game.GetInstance().SetCounter(key, value);
Game.GetInstance().state.SetCounter(key, value);
if (onComplete != null)
{
onComplete();
@ -305,7 +307,7 @@ namespace Fungus
public override void Execute(CommandQueue commandQueue, Action onComplete)
{
Game.GetInstance().SetInventory(key, value);
Game.GetInstance().state.SetInventory(key, value);
if (onComplete != null)
{
onComplete();
@ -460,9 +462,10 @@ namespace Fungus
public override void Execute(CommandQueue commandQueue, Action onComplete)
{
commandQueue.cameraController.PanToView(view, duration, delegate {
Game game = Game.GetInstance();
game.cameraController.PanToView(view, duration, delegate {
game.activeView = view;
// Try to find a page that is a child of the active view.
@ -503,11 +506,12 @@ namespace Fungus
public override void Execute(CommandQueue commandQueue, Action onComplete)
{
commandQueue.cameraController.PanToPath(views, duration, delegate {
Game game = Game.GetInstance();
game.cameraController.PanToPath(views, duration, delegate {
if (views.Length > 0)
{
Game game = Game.GetInstance();
game.activeView = views[views.Length - 1];
// Try to find a page that is a child of the active view.
@ -549,9 +553,10 @@ namespace Fungus
public override void Execute(CommandQueue commandQueue, Action onComplete)
{
commandQueue.cameraController.FadeToView(view, duration, delegate {
Game game = Game.GetInstance();
game.cameraController.FadeToView(view, duration, delegate {
game.activeView = view;
// Try to find a page that is a child of the active view.

117
Assets/Fungus/Scripts/Game.cs

@ -4,34 +4,43 @@ using System.Collections.Generic;
namespace Fungus
{
// Manages movement between rooms and global game state
[RequireComponent (typeof (CommandQueue))]
[RequireComponent (typeof (CameraController))]
// Manages global game state and movement between rooms
public class Game : MonoBehaviour
{
public bool showLinks = true;
public Room activeRoom;
public string continueText = "Continue";
public int charactersPerSecond = 60;
// Fixed Z coordinate of camera
public float cameraZ = - 10f;
public float fadeDuration = 1f;
public Texture2D fadeTexture;
[HideInInspector]
public View activeView;
[HideInInspector]
public Page activePage;
[HideInInspector]
public GameState state = new GameState();
protected Dictionary<string, string> stringTable = new Dictionary<string, string>();
private static Game instance;
CameraController cameraController;
[HideInInspector]
public StringTable stringTable = new StringTable();
public float fadeDuration = 1f;
[HideInInspector]
public CommandQueue commandQueue;
public string continueText = "Continue";
[HideInInspector]
public CameraController cameraController;
public int charactersPerSecond = 60;
static Game instance;
public static Game GetInstance()
{
@ -49,7 +58,8 @@ namespace Fungus
public virtual void Start()
{
cameraController = GetComponent<CameraController>();
commandQueue = gameObject.AddComponent<CommandQueue>();
cameraController = gameObject.AddComponent<CameraController>();
if (activeRoom == null)
{
@ -63,11 +73,6 @@ namespace Fungus
}
}
public Room GetCurrentRoom()
{
return GetInstance().activeRoom;
}
public void MoveToRoom(Room room)
{
if (room == null)
@ -79,87 +84,15 @@ namespace Fungus
// Fade out screen
cameraController.Fade(0f, fadeDuration / 2f, delegate {
if (activeRoom != null)
{
activeRoom.Leave();
}
activeRoom = room;
activeRoom.Enter();
// Notify room script that the Room is being entered
// Calling private method on Room to hide implementation
activeRoom.gameObject.SendMessage("Enter");
// Fade in screen
cameraController.Fade(1f, fadeDuration / 2f, null);
});
}
public void Restart()
{
// TODO: Reload scene
}
public void ClearFlags()
{
state.ClearFlags();
}
public bool GetFlag(string key)
{
return state.GetFlag(key);
}
public void SetFlag(string key, bool value)
{
state.SetFlag(key, value);
}
public void ClearCounters()
{
state.ClearCounters();
}
public int GetCounter(string key)
{
return state.GetCounter(key);
}
public void SetCounter(string key, int value)
{
state.SetCounter(key, value);
}
public void ClearInventory()
{
state.ClearInventory();
}
public int GetInventory(string key)
{
return state.GetInventory(key);
}
public void SetInventory(string key, int value)
{
state.SetInventory(key, value);
}
public void ClearStringTable()
{
stringTable.Clear();
}
public string GetString(string key)
{
if (stringTable.ContainsKey(key))
{
return stringTable[key];
}
return "";
}
public void SetString(string key, string value)
{
stringTable[key] = value;
}
}
}

267
Assets/Fungus/Scripts/GameController.cs

@ -0,0 +1,267 @@
using UnityEngine;
using System;
using System.Collections;
using Fungus;
// This facade class gives easy access to all game control
// functionality available in Fungus
public class GameController : MonoBehaviour
{
//
// Synchronous methods
// The following methods all execute immediately
//
// Return true if the boolean flag for the key has been set to true
public bool GetFlag(string key)
{
GameState state = Game.GetInstance().state;
return state.GetFlag(key);
}
// Returns the count value for the key
// Returns zero if no value has been set.
public int GetCounter(string key)
{
GameState state = Game.GetInstance().state;
return state.GetCounter(key);
}
// Returns the inventory count value for the key
// Returns zero if no inventory count has been set.
public int GetInventory(string key)
{
GameState state = Game.GetInstance().state;
return state.GetInventory(key);
}
// Returns true if the inventory count for the key is greater than zero
public bool HasInventory(string key)
{
GameState state = Game.GetInstance().state;
return (state.GetInventory(key) > 0);
}
//
// Asynchronous methods
// The following methods all queue commands for later execution in strict serial order
//
// Wait for a period of time before executing the next command
public void Wait(float duration)
{
CommandQueue commandQueue = Game.GetInstance().commandQueue;
commandQueue.AddCommand(new WaitCommand(duration));
}
// Call a delegate method provided by the client
// Used to queue the execution of arbitrary code.
public void Call(Action callAction)
{
CommandQueue commandQueue = Game.GetInstance().commandQueue;
commandQueue.AddCommand(new CallCommand(callAction));
}
// Sets the currently active view immediately.
// The main camera snaps to the active view.
public void SetView(View view)
{
CommandQueue commandQueue = Game.GetInstance().commandQueue;
commandQueue.AddCommand(new SetViewCommand(view));
}
// Sets the currently active page for text rendering
public void SetPage(Page page)
{
CommandQueue commandQueue = Game.GetInstance().commandQueue;
commandQueue.AddCommand(new SetPageCommand(page));
}
// Sets the title text displayed at the top of the active page
public void Title(string titleText)
{
CommandQueue commandQueue = Game.GetInstance().commandQueue;
commandQueue.AddCommand(new TitleCommand(titleText));
}
// Writes story text to the currently active page.
// A 'continue' button is displayed when the text has fully appeared.
public void Say(string storyText)
{
CommandQueue commandQueue = Game.GetInstance().commandQueue;
commandQueue.AddCommand(new SayCommand(storyText));
}
// Adds an option button to the current list of options.
// Use the Choose command to display added options.
public void AddOption(string optionText, Action optionAction)
{
CommandQueue commandQueue = Game.GetInstance().commandQueue;
commandQueue.AddCommand(new AddOptionCommand(optionText, optionAction));
}
// Display all previously added options as buttons, with no text prompt
public void Choose()
{
Choose("");
}
// Displays a text prompt, followed by all previously added options as buttons.
public void Choose(string chooseText)
{
CommandQueue commandQueue = Game.GetInstance().commandQueue;
commandQueue.AddCommand(new ChooseCommand(chooseText));
}
// Changes the active room to a different room
public void MoveToRoom(Room room)
{
CommandQueue commandQueue = Game.GetInstance().commandQueue;
commandQueue.AddCommand(new MoveToRoomCommand(room));
}
// Sets a global boolean flag value
public void SetFlag(string key, bool value)
{
CommandQueue commandQueue = Game.GetInstance().commandQueue;
commandQueue.AddCommand(new SetFlagCommand(key, value));
}
// Sets a global integer counter value
public void SetCounter(string key, int value)
{
CommandQueue commandQueue = Game.GetInstance().commandQueue;
commandQueue.AddCommand(new SetCounterCommand(key, value));
}
// Sets a global inventory count value
// Assumes that the count value is 1 (common case)
public void SetInventory(string key)
{
CommandQueue commandQueue = Game.GetInstance().commandQueue;
commandQueue.AddCommand(new SetInventoryCommand(key, 1));
}
// Sets a global inventory count value
public void SetInventory(string key, int value)
{
CommandQueue commandQueue = Game.GetInstance().commandQueue;
commandQueue.AddCommand(new SetInventoryCommand(key, value));
}
// Sets sprite alpha to 0 immediately
public void HideSprite(SpriteRenderer spriteRenderer)
{
FadeSprite(spriteRenderer, 0, 0, Vector2.zero);
}
// Sets sprite alpha to 1 immediately
public void ShowSprite(SpriteRenderer spriteRenderer)
{
FadeSprite(spriteRenderer, 1, 0, Vector2.zero);
}
// Fades a sprite to a given alpha value over a period of time
public void FadeSprite(SpriteRenderer spriteRenderer, float targetAlpha, float duration)
{
FadeSprite(spriteRenderer, targetAlpha, duration, Vector2.zero);
}
// Fades a sprite to a given alpha value over a period of time, and applies a sliding motion to the sprite transform
public void FadeSprite(SpriteRenderer spriteRenderer, float targetAlpha, float duration, Vector2 slideOffset)
{
CommandQueue commandQueue = Game.GetInstance().commandQueue;
Color color = spriteRenderer.color;
color.a = targetAlpha;
commandQueue.AddCommand(new FadeSpriteCommand(spriteRenderer, color, duration, slideOffset));
}
// Makes a sprite behave as a clickable button
public void AddButton(SpriteRenderer buttonSprite, Action buttonAction)
{
CommandQueue commandQueue = Game.GetInstance().commandQueue;
commandQueue.AddCommand(new AddButtonCommand(buttonSprite, buttonAction));
}
// Makes a sprite stop behaving as a clickable button
public void RemoveButton(SpriteRenderer buttonSprite)
{
CommandQueue commandQueue = Game.GetInstance().commandQueue;
commandQueue.AddCommand(new RemoveButtonCommand(buttonSprite));
}
// Sets an animator trigger to change the animation state for an animated sprite
public void SetAnimatorTrigger(Animator animator, string triggerName)
{
CommandQueue commandQueue = Game.GetInstance().commandQueue;
commandQueue.AddCommand(new SetAnimatorTriggerCommand(animator, triggerName));
}
// Pans the camera to the target view over a period of time
public void PanToView(View targetView, float duration)
{
CommandQueue commandQueue = Game.GetInstance().commandQueue;
commandQueue.AddCommand(new PanToViewCommand(targetView, duration));
}
// Pans the camera through a sequence of target views over a period of time
public void PanToPath(float duration, params View[] targetViews)
{
CommandQueue commandQueue = Game.GetInstance().commandQueue;
commandQueue.AddCommand(new PanToPathCommand(targetViews, duration));
}
// Snaps the camera to the target view immediately
public void SnapToView(View targetView)
{
CommandQueue commandQueue = Game.GetInstance().commandQueue;
commandQueue.AddCommand(new PanToViewCommand(targetView, 0f));
}
// Fades out the current camera view, and fades in again using the target view.
public void FadeToView(View targetView, float duration)
{
CommandQueue commandQueue = Game.GetInstance().commandQueue;
commandQueue.AddCommand(new FadeToViewCommand(targetView, duration));
}
// Plays game music using an audio clip
public void PlayGameMusic(AudioClip audioClip)
{
CommandQueue commandQueue = Game.GetInstance().commandQueue;
commandQueue.AddCommand(new PlayMusicCommand(audioClip));
}
// Stops playing game music
public void StopGameMusic()
{
CommandQueue commandQueue = Game.GetInstance().commandQueue;
commandQueue.AddCommand(new StopMusicCommand());
}
// Sets music volume immediately
public void SetMusicVolume(float musicVolume)
{
SetMusicVolume(musicVolume, 0f);
}
// Fades music volume to required level over a period of time
public void SetMusicVolume(float musicVolume, float duration)
{
CommandQueue commandQueue = Game.GetInstance().commandQueue;
commandQueue.AddCommand(new SetMusicVolumeCommand(musicVolume, duration));
}
// Plays a sound effect once
public void PlaySound(AudioClip audioClip)
{
PlaySound(audioClip, 1f);
}
// Plays a sound effect once, at the specified volume
public void PlaySound(AudioClip audioClip, float volume)
{
CommandQueue commandQueue = Game.GetInstance().commandQueue;
commandQueue.AddCommand(new PlaySoundCommand(audioClip, volume));
}
}

8
Assets/Fungus/Scripts/GameController.cs.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4341f88125d5c4fe1b941bd614ae342d
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

50
Assets/Fungus/Scripts/Page.cs

@ -2,7 +2,6 @@ using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace Fungus
{
@ -64,20 +63,23 @@ namespace Fungus
public void Say(string sayText, Action sayAction)
{
mode = Mode.Say;
string subbedText = SubstituteStrings(sayText);
StringTable stringTable = Game.GetInstance().stringTable;
string subbedText = stringTable.SubstituteStrings(sayText);
WriteStory(subbedText, sayAction);
}
public void AddOption(string optionText, Action optionAction)
{
string subbedText = FormatLinkText(SubstituteStrings(optionText));
StringTable stringTable = Game.GetInstance().stringTable;
string subbedText = stringTable.FormatLinkText(stringTable.SubstituteStrings(optionText));
options.Add(new Option(subbedText, optionAction));
}
public void Choose(string _chooseText)
{
mode = Mode.Choose;
string subbedText = SubstituteStrings(_chooseText);
StringTable stringTable = Game.GetInstance().stringTable;
string subbedText = stringTable.SubstituteStrings(_chooseText);
WriteStory(subbedText, null);
}
@ -206,9 +208,8 @@ namespace Fungus
// Reset to idle, but calling action may set this again
mode = Mode.Idle;
Room room = Game.GetInstance().activeRoom;
room.ExecuteCommandMethod(tempAction);
CommandQueue commandQueue = Game.GetInstance().commandQueue;
commandQueue.CallCommandMethod(tempAction);
}
else if (mode == Mode.Say)
{
@ -274,41 +275,6 @@ namespace Fungus
outerRect.height - (boxStyle.padding.top + boxStyle.padding.bottom));
}
private string SubstituteStrings(string text)
{
string subbedText = text;
// Instantiate the regular expression object.
Regex r = new Regex("{.*?}");
// Match the regular expression pattern against a text string.
var results = r.Matches(text);
foreach (Match match in results)
{
string stringKey = match.Value.Substring(1, match.Value.Length - 2);
string stringValue = Game.GetInstance().GetString(stringKey);
subbedText = subbedText.Replace(match.Value, stringValue);
}
return subbedText;
}
private string FormatLinkText(string text)
{
string trimmed;
if (text.Contains("\n"))
{
trimmed = text.Substring(0, text.IndexOf("\n"));
}
else
{
trimmed = text;
}
return trimmed;
}
Rect GetScreenRect()
{
// Y decreases up the screen in GUI space, so top left is rect origin

288
Assets/Fungus/Scripts/Room.cs

@ -10,23 +10,18 @@ namespace Fungus
// This is the main scripting interface for Fungus games.
// Each room in your game should have a script which inherits from Room.
// The OnEnter() method is called when the player enters the room.
// The OnLeave() method is called when the player moves to a different room.
// Convenience methods are provided for accessing all features of the library.
public abstract class Room : MonoBehaviour
// The GameController base class provides easy access to all story control commands
public abstract class Room : GameController
{
public int visitCount;
Game game;
CommandQueue commandQueue;
CameraController cameraController;
void Awake()
// Returns true if this is the first time the player has visited this room
public bool IsFirstVisit()
{
game = Game.GetInstance();
cameraController = game.gameObject.GetComponent<CameraController>();
commandQueue = game.gameObject.GetComponent<CommandQueue>();
return (visitCount == 0);
}
// Automatically draws arrows to other Rooms referenced in public properties
void OnDrawGizmos()
{
const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
@ -100,9 +95,13 @@ namespace Fungus
Gizmos.DrawLine(arrowPosA, arrowPosC);
}
// Internal use only! Called by Game when changing room
public void Enter()
// Called by Game when player enters the room
void Enter()
{
Game game = Game.GetInstance();
CameraController cameraController = game.gameObject.GetComponent<CameraController>();
// Pick first view found in the room and snap to camera to this view.
// It is allowed for a room to not have any views.
// In this case game.activeView will be null, and the camera will attempt
@ -135,270 +134,9 @@ namespace Fungus
// Rooms may have multiple child views and page. It is the responsibility of the client
// room script to set the appropriate view & page in its OnEnter method.
commandQueue.Reset();
SendMessage("OnEnter", SendMessageOptions.DontRequireReceiver);
commandQueue.Execute();
game.commandQueue.CallCommandMethod(game.activeRoom.gameObject, "OnEnter");
visitCount++;
}
// Internal use only! Called by Game when changing room
public void Leave()
{
SendMessage("OnLeave", SendMessageOptions.DontRequireReceiver);
}
// Internal use only! Called by AnimationEventListener
public void AnimationEvent(string methodName)
{
ExecuteCommandMethod(methodName);
}
// Internal use only!
public void ExecuteCommandMethod(string methodName)
{
commandQueue.Reset();
SendMessage(methodName, SendMessageOptions.DontRequireReceiver);
commandQueue.Execute();
}
// Internal use only!
public void ExecuteCommandMethod(Action method)
{
commandQueue.Reset();
method();
commandQueue.Execute();
}
// Public convenience methods
// These methods all execute immediately
// Returns true if this is the first time the player has visited this room
public bool IsFirstVisit()
{
return (visitCount == 0);
}
// Return true if the boolean flag for the key has been set to true
public bool GetFlag(string key)
{
return game.GetFlag(key);
}
// Returns the count value for the key
// Returns zero if no value has been set.
public int GetCounter(string key)
{
return game.GetCounter(key);
}
// Returns the inventory count value for the key
// Returns zero if no inventory count has been set.
public int GetInventory(string key)
{
return game.GetInventory(key);
}
// Returns true if the inventory count for the key is greater than zero
public bool HasInventory(string key)
{
return (game.GetInventory(key) > 0);
}
// Public command methods
// These methods all queue commands for later execution in serial order
// Wait for a period of time before executing the next command
public void Wait(float duration)
{
commandQueue.AddCommand(new WaitCommand(duration));
}
// Call a delegate method provided by the client
// Used to queue the execution of arbitrary code.
public void Call(Action callAction)
{
commandQueue.AddCommand(new CallCommand(callAction));
}
// Sets the currently active view immediately.
// The main camera snaps to the active view.
public void SetView(View view)
{
commandQueue.AddCommand(new SetViewCommand(view));
}
// Sets the currently active page for text rendering
public void SetPage(Page page)
{
commandQueue.AddCommand(new SetPageCommand(page));
}
// Sets the title text displayed at the top of the active page
public void Title(string titleText)
{
commandQueue.AddCommand(new TitleCommand(titleText));
}
// Writes story text to the currently active page.
// A 'continue' button is displayed when the text has fully appeared.
public void Say(string storyText)
{
commandQueue.AddCommand(new SayCommand(storyText));
}
// Adds an option button to the current list of options.
// Use the Choose command to display added options.
public void AddOption(string optionText, Action optionAction)
{
commandQueue.AddCommand(new AddOptionCommand(optionText, optionAction));
}
// Displays a text prompt, followed by all previously added options as buttons.
public void Choose(string chooseText)
{
commandQueue.AddCommand(new ChooseCommand(chooseText));
}
// Changes the active room to a different room
public void MoveToRoom(Room room)
{
commandQueue.AddCommand(new MoveToRoomCommand(room));
}
// Sets a global boolean flag value
public void SetFlag(string key, bool value)
{
commandQueue.AddCommand(new SetFlagCommand(key, value));
}
// Sets a global integer counter value
public void SetCounter(string key, int value)
{
commandQueue.AddCommand(new SetCounterCommand(key, value));
}
// Sets a global inventory count value
// Assumes that the count value is 1 (common case)
public void SetInventory(string key)
{
commandQueue.AddCommand(new SetInventoryCommand(key, 1));
}
// Sets a global inventory count value
public void SetInventory(string key, int value)
{
commandQueue.AddCommand(new SetInventoryCommand(key, value));
}
// Sets sprite alpha to 0 immediately
public void HideSprite(SpriteRenderer spriteRenderer)
{
Color color = spriteRenderer.color;
color.a = 0f;
commandQueue.AddCommand(new FadeSpriteCommand(spriteRenderer, color, 0f, Vector2.zero));
}
// Sets sprite alpha to 1 immediately
public void ShowSprite(SpriteRenderer spriteRenderer)
{
Color color = spriteRenderer.color;
color.a = 1f;
commandQueue.AddCommand(new FadeSpriteCommand(spriteRenderer, color, 0f, Vector2.zero));
}
// Fades a sprite to a given alpha value over a period of time
public void FadeSprite(SpriteRenderer spriteRenderer, float targetAlpha, float duration)
{
Color color = spriteRenderer.color;
color.a = targetAlpha;
commandQueue.AddCommand(new FadeSpriteCommand(spriteRenderer, color, duration, Vector2.zero));
}
// Fades a sprite to a given alpha value over a period of time, and applies a sliding motion to the sprite transform
public void FadeSprite(SpriteRenderer spriteRenderer, float targetAlpha, float duration, Vector2 slideOffset)
{
Color color = spriteRenderer.color;
color.a = targetAlpha;
commandQueue.AddCommand(new FadeSpriteCommand(spriteRenderer, color, duration, slideOffset));
}
// Makes a sprite behave as a clickable button
public void AddButton(SpriteRenderer buttonSprite, Action buttonAction)
{
commandQueue.AddCommand(new AddButtonCommand(buttonSprite, buttonAction));
}
// Makes a sprite stop behaving as a clickable button
public void RemoveButton(SpriteRenderer buttonSprite)
{
commandQueue.AddCommand(new RemoveButtonCommand(buttonSprite));
}
// Sets an animator trigger to change the animation state for an animated sprite
public void SetAnimatorTrigger(Animator animator, string triggerName)
{
commandQueue.AddCommand(new SetAnimatorTriggerCommand(animator, triggerName));
}
// Pans the camera to the target view over a period of time
public void PanToView(View targetView, float duration)
{
commandQueue.AddCommand(new PanToViewCommand(targetView, duration));
}
// Pans the camera through a sequence of target views over a period of time
public void PanToPath(float duration, params View[] targetViews)
{
commandQueue.AddCommand(new PanToPathCommand(targetViews, duration));
}
// Snaps the camera to the target view immediately
public void SnapToView(View targetView)
{
commandQueue.AddCommand(new PanToViewCommand(targetView, 0f));
}
// Fades out the current camera view, and fades in again using the target view.
public void FadeToView(View targetView, float duration)
{
commandQueue.AddCommand(new FadeToViewCommand(targetView, duration));
}
// Plays game music using an audio clip
public void PlayGameMusic(AudioClip audioClip)
{
commandQueue.AddCommand(new PlayMusicCommand(audioClip));
}
// Stops playing game music
public void StopGameMusic()
{
commandQueue.AddCommand(new StopMusicCommand());
}
// Sets music volume immediately
public void SetMusicVolume(float musicVolume)
{
commandQueue.AddCommand(new SetMusicVolumeCommand(musicVolume, 0f));
}
// Fades music volume to required level over a period of time
public void SetMusicVolume(float musicVolume, float duration)
{
commandQueue.AddCommand(new SetMusicVolumeCommand(musicVolume, duration));
}
// Plays a sound effect once
public void PlaySound(AudioClip audioClip)
{
commandQueue.AddCommand(new PlaySoundCommand(audioClip, 1f));
}
// Plays a sound effect once, at the specified volume
public void PlaySound(AudioClip audioClip, float volume)
{
commandQueue.AddCommand(new PlaySoundCommand(audioClip, volume));
}
}
}

71
Assets/Fungus/Scripts/StringTable.cs

@ -0,0 +1,71 @@
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
// Stores long or frequently repeated strings in a dictionary.
// Strings can then be retrieved using a short key string.
public class StringTable
{
Dictionary<string, string> stringTable = new Dictionary<string, string>();
public void ClearStringTable()
{
stringTable.Clear();
}
// Retrieves a string from the table
public string GetString(string key)
{
if (stringTable.ContainsKey(key))
{
return stringTable[key];
}
return "";
}
// Adds or updates a string in the table
public void SetString(string key, string value)
{
stringTable[key] = value;
}
// Replace keys in the input string with the string table entry
// Example format: "This {string_key} string"
public string SubstituteStrings(string text)
{
string subbedText = text;
// Instantiate the regular expression object.
Regex r = new Regex("{.*?}");
// Match the regular expression pattern against a text string.
var results = r.Matches(text);
foreach (Match match in results)
{
string stringKey = match.Value.Substring(1, match.Value.Length - 2);
string stringValue = GetString(stringKey);
subbedText = subbedText.Replace(match.Value, stringValue);
}
return subbedText;
}
// Chops a string at the first new line character
// Useful for link / button strings that must fit on a single line
public string FormatLinkText(string text)
{
string trimmed;
if (text.Contains("\n"))
{
trimmed = text.Substring(0, text.IndexOf("\n"));
}
else
{
trimmed = text;
}
return trimmed;
}
}

8
Assets/Fungus/Scripts/StringTable.cs.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 43c44334e66c44af1a071056e4fde1f9
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

4
Assets/Fungus/Scripts/StringsParser.cs

@ -29,6 +29,8 @@ namespace Fungus
static public 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)");
@ -86,7 +88,7 @@ namespace Fungus
// Trim off last newline
blockBuffer = blockBuffer.TrimEnd( '\r', '\n', ' ', '\t');
Game.GetInstance().SetString(blockTag, blockBuffer);
stringTable.SetString(blockTag, blockBuffer);
}
// Prepare to parse next block

BIN
Assets/FungusExample/Animations/GreenAlienWalk.anim

Binary file not shown.

BIN
Assets/FungusExample/Scenes/Example.unity

Binary file not shown.
Loading…
Cancel
Save