Skip to content

Instantly share code, notes, and snippets.

@jesterswilde
Created December 18, 2018 20:25
Show Gist options
  • Save jesterswilde/a3e4a0fa430eb2cfd775246c80075c2f to your computer and use it in GitHub Desktop.
Save jesterswilde/a3e4a0fa430eb2cfd775246c80075c2f to your computer and use it in GitHub Desktop.
public class GameManager : MonoBehaviour
{
[SerializeField]
Player playerPrefab;
Timeline timeline;
static GameManager t;
List<ITimed> timedThings = new List<ITimed>();
IInput currentInput;
Vector3 spawnPoint;
Transform spawner;
[SerializeField]
Transform spawnPrefab;
public static event System.Action<Player> ChangedPlayer;
[SerializeField]
int totalFrames = 0;
public static int TotalFrames { get { return t.totalFrames; } }
bool isFastForwarding = false;
int targetFrame;
public static int CurrentFrame { get { return t.timeline.CurrentFrame; } }
Player currentPlayer;
public static Player CurrentPlayer { get { return t.currentPlayer; } }
List<Player> players = new List<Player>();
int _playerIndex = 0;
int playerIndex
{
get { return _playerIndex; }
set
{
_playerIndex = value;
if (_playerIndex >= players.Count)
{
_playerIndex = _playerIndex % players.Count;
}
if (_playerIndex < 0)
{
_playerIndex = players.Count - 1;
}
}
}
void Awake()
{
t = this;
timeline = new Timeline();
currentInput = new InputPlayer();
players = FindObjectsOfType<Player>().ToList();
Player currentPlayer = players.FirstOrDefault((player) => player.IsStartingPlayer);
Vector3 spawnPos = (currentPlayer != null) ? currentPlayer.transform.position : Vector3.zero;
spawner = Instantiate(spawnPrefab, spawnPos, Quaternion.identity);
}
void FixedUpdate()
{
if (isFastForwarding)
{
if (CurrentFrame == targetFrame)
{
isFastForwarding = false;
Time.fixedDeltaTime = GameSettings.PhysStep;
}
RunFrame();
}
else
{
if (currentInput.ShouldPlay)
{
RunFrame();
totalFrames++;
}
}
}
void Update()
{
currentInput.GetInput();
}
void RunFrame()
{
int frame = timeline.CurrentFrame;
if (timeline.HasStateAtFrame(frame))
{
if (timeline.CurrentFrame == 0 || IsCurrentFrameAFuturePoint(frame))
{
SerializeTimedAtCurrentFrame();
}
else
{
timeline.RemoveStateAtFrame(frame);
}
}
ProcessFrame();
PassTime();
timeline.CurrentFrame++;
}
void SerializeTimedAtCurrentFrame()
{
timeline.RecordCurrentState(
timedThings.Select((timed) => timed.Serialize())
.ToList()
);
}
public static void AddSerielizedState(TimedState state)
{
t.timeline.AddSerielizedState(state);
}
public static void SelectPlayer(Player player)
{
t.currentPlayer = player;
}
void SetFrame(int frame)
{
if (frame < timeline.CurrentFrame)
{
timeline.SetStateToClosestFrame(frame);
}
if (timeline.CurrentFrame < frame)
{
BeginFastFowarding(frame);
}
}
void BeginFastFowarding(int _targetFrame)
{
isFastForwarding = true;
targetFrame = _targetFrame;
int frameDiff = _targetFrame - CurrentFrame;
Time.fixedDeltaTime = GameSettings.CameraLerpDuration / frameDiff;
}
bool IsCurrentFrameAFuturePoint(int frame)
{
return players.Any((player) =>
{
return player.FuturistFrame == frame && player != currentPlayer;
});
}
public static void SetSpawnPoint(Vector3 pos)
{
t.spawnPoint = pos;
t.spawner.transform.position = pos;
}
public static void SwitchPlayer(int indexMod)
{
if (t.players.Count > 1)
{
t.currentPlayer.Deselect();
t.SerializeTimedAtCurrentFrame();
t.playerIndex += indexMod;
t.currentPlayer = t.players[t.playerIndex];
t.currentPlayer.Select();
t.SetFrame(t.currentPlayer.FuturistFrame);
ChangedPlayer(t.currentPlayer);
SwitchInputType(InputTypes.TapPause);
}
}
public static void MakeNewPlayer()
{
t.currentInput.EndInput();
t.currentPlayer.Deselect();
t.SetFrame(0);
t.currentPlayer = Instantiate(t.playerPrefab, t.spawnPoint, Quaternion.identity);
t.players.Add(t.currentPlayer);
t.playerIndex = t.players.Count - 1;
t.currentInput.StartInput();
ChangedPlayer(t.currentPlayer);
SwitchInputType(InputTypes.TapPause);
}
public static void SwitchInputType(InputTypes nextInput)
{
t.currentInput.EndInput();
switch (nextInput)
{
case InputTypes.Player:
t.currentInput = new InputPlayer();
break;
case InputTypes.TapPause:
t.currentInput = new InputTapPause();
break;
}
t.currentInput.StartInput();
}
public static void AddActionToTimeline(Action action)
{
t.timeline.AddAction(action);
}
public static void RegisterTimedThing(ITimed timed)
{
t.timedThings.Add(timed);
}
public static void RegisterPlayer(Player player)
{
t.players.Add(player);
}
void ProcessFrame()
{
timeline.ProcessFrame();
}
void PassTime()
{
timedThings.ForEach((timed) => timed.Play(GameSettings.PhysStep));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment