400 lines
16 KiB
C#
400 lines
16 KiB
C#
using UdonSharp;
|
|
using UnityEngine;
|
|
using VRC.SDKBase;
|
|
using VRC.SDK3.Data;
|
|
|
|
namespace Marro.PacManUdon
|
|
{
|
|
public partial class GameManager
|
|
{
|
|
// A note about the quality of the code here:
|
|
// I intended to write this using proper classes, right until I realized Udon does not support instantiating classes.
|
|
// While I'm not a big fan of the partial class solution that I ended up doing (static classes would still be neater, or perhaps separate UdonSharpBehaviour instances),
|
|
// I'm not redoing this unless I get instantiatable classes before I wrap up this project.
|
|
bool currentlyInTimeSequence;
|
|
bool waitingForTimeSequenceFinish;
|
|
bool jumpingToTimeSequence;
|
|
PacManTimeSequence currentTimeSequence;
|
|
[UdonSynced] float timeSequenceSecondsPassed;
|
|
int timeSequenceProgress;
|
|
float[] timeSequenceKeyframeTimes;
|
|
|
|
private void StartTimeSequence(PacManTimeSequence timeSequence)
|
|
{
|
|
Debug.Log($"StartTimeSequence: {timeSequence}");
|
|
|
|
if (currentlyInTimeSequence)
|
|
{
|
|
PrepareToStartTimeSequence(timeSequence);
|
|
}
|
|
|
|
currentlyInTimeSequence = true;
|
|
currentTimeSequence = timeSequence;
|
|
timeSequenceProgress = 0;
|
|
timeSequenceSecondsPassed = 0;
|
|
timeSequenceKeyframeTimes = GetTimeSequenceKeyframeTimes(timeSequence);
|
|
TimeSequenceProgressToTime(timeSequenceSecondsPassed);
|
|
}
|
|
|
|
private void PrepareToStartTimeSequence(PacManTimeSequence timeSequence)
|
|
{
|
|
jumpingToTimeSequence = true;
|
|
TimeSequenceProgressToTime(100000f);
|
|
jumpingToTimeSequence = false;
|
|
}
|
|
|
|
private void TimeSequenceUpdate(float deltaSeconds)
|
|
{
|
|
if (!currentlyInTimeSequence)
|
|
{
|
|
return;
|
|
}
|
|
|
|
TimeSequenceProgressToTime(timeSequenceSecondsPassed + deltaSeconds);
|
|
}
|
|
|
|
private void TimeSequenceSkipToNextStep()
|
|
{
|
|
// Debug.Log($"{gameObject} TimeSequenceSkipToNextStep");
|
|
if (timeSequenceProgress < timeSequenceKeyframeTimes.Length)
|
|
{
|
|
TimeSequenceProgressToTime(timeSequenceKeyframeTimes[timeSequenceProgress]);
|
|
}
|
|
else
|
|
{
|
|
Debug.LogWarning($"{gameObject} Tried skipping to next time sequence step when already on last step!");
|
|
currentlyInTimeSequence = false;
|
|
}
|
|
}
|
|
|
|
private void TimeSequenceProgressToTime(float seconds)
|
|
{
|
|
timeSequenceSecondsPassed = seconds;
|
|
while (timeSequenceSecondsPassed >= timeSequenceKeyframeTimes[timeSequenceProgress])
|
|
{
|
|
TimeSequenceExecuteStep(timeSequenceProgress);
|
|
|
|
timeSequenceProgress += 1;
|
|
if (timeSequenceProgress >= timeSequenceKeyframeTimes.Length)
|
|
{
|
|
currentlyInTimeSequence = false;
|
|
TimeSequencePrepareForFinish();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void TimeSequencePrepareForFinish()
|
|
{
|
|
if (Networking.IsOwner(gameObject))
|
|
{
|
|
TimeSequenceExecuteFinalize();
|
|
if (!jumpingToTimeSequence)
|
|
{
|
|
TimeSequenceExecuteFinished();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
waitingForTimeSequenceFinish = true;
|
|
}
|
|
}
|
|
|
|
#region Events
|
|
|
|
public void JumpToTimeSequenceAttractScreenIntroduction()
|
|
{
|
|
StartTimeSequence(PacManTimeSequence.AttractScreenIntroduction);
|
|
}
|
|
|
|
public void JumpToTimeSequenceAttractScreenDemo()
|
|
{
|
|
StartTimeSequence(PacManTimeSequence.AttractScreenDemo);
|
|
}
|
|
|
|
public void JumpToTimeSequenceAttractScreenWaitToRestart()
|
|
{
|
|
StartTimeSequence(PacManTimeSequence.AttractScreenWaitToRestart);
|
|
}
|
|
|
|
public void JumpToTimeSequenceBoardClear()
|
|
{
|
|
StartTimeSequence(PacManTimeSequence.BoardClear);
|
|
}
|
|
|
|
public void JumpToTimeSequenceGameOver()
|
|
{
|
|
StartTimeSequence(PacManTimeSequence.GameOver);
|
|
}
|
|
|
|
public void JumpToTimeSequenceGhostCaught()
|
|
{
|
|
StartTimeSequence(PacManTimeSequence.GhostCaught);
|
|
}
|
|
|
|
public void JumpToTimeSequenceIntermission1()
|
|
{
|
|
StartTimeSequence(PacManTimeSequence.Intermission1);
|
|
}
|
|
|
|
public void JumpToTimeSequenceIntermission2()
|
|
{
|
|
StartTimeSequence(PacManTimeSequence.Intermission2);
|
|
}
|
|
|
|
public void JumpToTimeSequenceIntermission3()
|
|
{
|
|
StartTimeSequence(PacManTimeSequence.Intermission3);
|
|
}
|
|
|
|
public void JumpToTimeSequencePacManCaught()
|
|
{
|
|
StartTimeSequence(PacManTimeSequence.PacManCaught);
|
|
}
|
|
|
|
public void JumpToTimeSequenceRestartLevel()
|
|
{
|
|
StartTimeSequence(PacManTimeSequence.RestartLevel);
|
|
}
|
|
|
|
public void JumpToTimeSequenceStartNewGame()
|
|
{
|
|
StartTimeSequence(PacManTimeSequence.StartNewGame);
|
|
}
|
|
|
|
public void JumpToTimeSequenceStartNewLevel()
|
|
{
|
|
StartTimeSequence(PacManTimeSequence.StartNewLevel);
|
|
}
|
|
|
|
public void JumpToTimeSequenceWaitForStart()
|
|
{
|
|
StartTimeSequence(PacManTimeSequence.WaitForStart);
|
|
}
|
|
|
|
public void JumpToTimeSequenceWaitForStartTimeout()
|
|
{
|
|
StartTimeSequence(PacManTimeSequence.WaitForStartTimeout);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Jump tables
|
|
|
|
private void TimeSequenceExecuteStep(int sequenceProgress)
|
|
{
|
|
// Debug.Log($"{gameObject} Triggered time sequence step for sequence {currentTimeSequence} with progress {sequenceProgress}");
|
|
switch (currentTimeSequence)
|
|
{
|
|
default:
|
|
Debug.LogError($"{gameObject} No time sequence keyframes known for sequence {currentTimeSequence}");
|
|
break;
|
|
case PacManTimeSequence.AttractScreenIntroduction:
|
|
TimeSequenceStepAttractScreenIntroduction(sequenceProgress);
|
|
break;
|
|
case PacManTimeSequence.AttractScreenDemo:
|
|
TimeSequenceStepAttractScreenDemo(sequenceProgress);
|
|
break;
|
|
case PacManTimeSequence.WaitForStart:
|
|
TimeSequenceStepWaitForStart(sequenceProgress);
|
|
break;
|
|
case PacManTimeSequence.StartNewGame:
|
|
TimeSequenceStepStartNewGame(sequenceProgress);
|
|
break;
|
|
case PacManTimeSequence.BoardClear:
|
|
TimeSequenceStepBoardClear(sequenceProgress);
|
|
break;
|
|
case PacManTimeSequence.StartNewLevel:
|
|
TimeSequenceStepStartNewLevel(sequenceProgress);
|
|
break;
|
|
case PacManTimeSequence.GhostCaught:
|
|
TimeSequenceStepGhostCaught(sequenceProgress);
|
|
break;
|
|
case PacManTimeSequence.PacManCaught:
|
|
TimeSequenceStepPacManCaught(sequenceProgress);
|
|
break;
|
|
case PacManTimeSequence.RestartLevel:
|
|
TimeSequenceStepRestartLevel(sequenceProgress);
|
|
break;
|
|
case PacManTimeSequence.GameOver:
|
|
TimeSequenceStepGameOver(sequenceProgress);
|
|
break;
|
|
case PacManTimeSequence.Intermission1:
|
|
TimeSequenceStepIntermission1(sequenceProgress);
|
|
break;
|
|
case PacManTimeSequence.Intermission2:
|
|
TimeSequenceStepIntermission2(sequenceProgress);
|
|
break;
|
|
case PacManTimeSequence.Intermission3:
|
|
TimeSequenceStepIntermission3(sequenceProgress);
|
|
break;
|
|
case PacManTimeSequence.AttractScreenWaitToRestart:
|
|
case PacManTimeSequence.WaitForStartTimeout:
|
|
// These don't have steps
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void TimeSequenceExecuteFinalize()
|
|
{
|
|
// Debug.Log($"{gameObject} Triggered time sequence step for sequence {currentTimeSequence} with progress {sequenceProgress}");
|
|
switch (currentTimeSequence)
|
|
{
|
|
default:
|
|
Debug.LogError($"{gameObject} No time sequence finalize known for sequence {currentTimeSequence}");
|
|
break;
|
|
case PacManTimeSequence.AttractScreenIntroduction:
|
|
TimeSequenceFinalizeAttractScreenIntroduction();
|
|
break;
|
|
case PacManTimeSequence.WaitForStart:
|
|
TimeSequenceFinalizeWaitForStart();
|
|
break;
|
|
case PacManTimeSequence.StartNewGame:
|
|
TimeSequenceFinalizeStartNewGame();
|
|
break;
|
|
case PacManTimeSequence.StartNewLevel:
|
|
TimeSequenceFinalizeStartNewLevel();
|
|
break;
|
|
case PacManTimeSequence.GhostCaught:
|
|
TimeSequenceFinalizeGhostCaught();
|
|
break;
|
|
case PacManTimeSequence.RestartLevel:
|
|
TimeSequenceFinalizeRestartLevel();
|
|
break;
|
|
case PacManTimeSequence.Intermission2:
|
|
TimeSequenceFinalizeIntermission2();
|
|
break;
|
|
case PacManTimeSequence.Intermission3:
|
|
TimeSequenceFinalizeIntermission3();
|
|
break;
|
|
case PacManTimeSequence.AttractScreenDemo:
|
|
case PacManTimeSequence.WaitForStartTimeout:
|
|
case PacManTimeSequence.AttractScreenWaitToRestart:
|
|
case PacManTimeSequence.GameOver:
|
|
case PacManTimeSequence.Intermission1:
|
|
case PacManTimeSequence.PacManCaught:
|
|
case PacManTimeSequence.BoardClear:
|
|
// These don't have a finalize
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void TimeSequenceExecuteFinished()
|
|
{
|
|
// Debug.Log($"{gameObject} Triggered time sequence step for sequence {currentTimeSequence} with progress {sequenceProgress}");
|
|
switch (currentTimeSequence)
|
|
{
|
|
default:
|
|
Debug.LogError($"{gameObject} No time sequence finish known for sequence {currentTimeSequence}");
|
|
break;
|
|
case PacManTimeSequence.AttractScreenIntroduction:
|
|
TimeSequenceFinishedAttractScreenIntroduction();
|
|
break;
|
|
case PacManTimeSequence.AttractScreenDemo:
|
|
TimeSequenceFinishedAttractScreenDemo();
|
|
break;
|
|
case PacManTimeSequence.AttractScreenWaitToRestart:
|
|
TimeSequenceFinishedAttractScreenWaitToRestart();
|
|
break;
|
|
case PacManTimeSequence.WaitForStartTimeout:
|
|
TimeSequenceFinishedWaitForStartTimeout();
|
|
break;
|
|
case PacManTimeSequence.BoardClear:
|
|
TimeSequenceFinishedBoardClear();
|
|
break;
|
|
case PacManTimeSequence.PacManCaught:
|
|
TimeSequenceFinishedPacManCaught();
|
|
break;
|
|
case PacManTimeSequence.GameOver:
|
|
TimeSequenceFinishedGameOver();
|
|
break;
|
|
case PacManTimeSequence.Intermission1:
|
|
TimeSequenceFinishedIntermission1();
|
|
break;
|
|
case PacManTimeSequence.Intermission2:
|
|
TimeSequenceFinishedIntermission2();
|
|
break;
|
|
case PacManTimeSequence.Intermission3:
|
|
TimeSequenceFinishedIntermission3();
|
|
break;
|
|
case PacManTimeSequence.RestartLevel:
|
|
case PacManTimeSequence.StartNewLevel:
|
|
case PacManTimeSequence.GhostCaught:
|
|
case PacManTimeSequence.WaitForStart:
|
|
case PacManTimeSequence.StartNewGame:
|
|
// These don't have a finished
|
|
break;
|
|
}
|
|
}
|
|
|
|
private float[] GetTimeSequenceKeyframeTimes(PacManTimeSequence timeSequence)
|
|
{
|
|
switch (timeSequence)
|
|
{
|
|
default:
|
|
Debug.LogError($"{gameObject} No time sequence keyframe times known for sequence {timeSequence}");
|
|
return new float[0];
|
|
case PacManTimeSequence.AttractScreenIntroduction:
|
|
return DeltaToAbsolute(new float[] { 0, 0.032f, 1f, 1f, .5f, .5f, 1f, .5f, .5f, 1f, .5f, .5f, 1f, .5f, 1f, 1f, 1f,
|
|
5f, 0.2f, 2f, 0.91667f, 2f, 0.91667f, 2f, 0.91667f, 2f, 0.91667f });
|
|
case PacManTimeSequence.AttractScreenDemo:
|
|
return DeltaToAbsolute(new float[] { 0, 0.016f, 0.05f, 0.16f, 0.33f, 1.85f, 54f });
|
|
case PacManTimeSequence.AttractScreenWaitToRestart:
|
|
return DeltaToAbsolute(new float[] { 0, 2f });
|
|
case PacManTimeSequence.WaitForStart:
|
|
return DeltaToAbsolute(new float[] { 0, 0.016f });
|
|
case PacManTimeSequence.WaitForStartTimeout:
|
|
return DeltaToAbsolute(new float[] { 0, 5f });
|
|
case PacManTimeSequence.StartNewGame:
|
|
return DeltaToAbsolute(new float[] { 0, 0.016f, 2.2f, 0.032f, 0.032f, 1.92f, 0.032f });
|
|
case PacManTimeSequence.BoardClear:
|
|
return DeltaToAbsolute(new float[] { 0, 2f, 0.016f, 1.6f - 0.016f, 0.016f, 0.032f, 0.3f });
|
|
case PacManTimeSequence.StartNewLevel:
|
|
return DeltaToAbsolute(new float[] { 0, 0.064f, 0.032f, 1.85f, 0.016f });
|
|
case PacManTimeSequence.GhostCaught:
|
|
return DeltaToAbsolute(new float[] { 0, 0.91667f });
|
|
case PacManTimeSequence.PacManCaught:
|
|
return DeltaToAbsolute(new float[] { 0, 1, 0.35f, 2.40f });
|
|
case PacManTimeSequence.RestartLevel:
|
|
return DeltaToAbsolute(new float[] { 0, 0.016f, 0.064f, 0.032f, 1.85f, 0.016f });
|
|
case PacManTimeSequence.GameOver:
|
|
return DeltaToAbsolute(new float[] { 0, 1.95f });
|
|
case PacManTimeSequence.Intermission1:
|
|
return DeltaToAbsolute(new float[] { 0, 0.316f, 0.3f, 3.96f, 2.25f, 3.93f });
|
|
case PacManTimeSequence.Intermission2:
|
|
return DeltaToAbsolute(new float[] { 0, 0.25f, 0.083f, 0.3f, 1.43f, 2.5f, 1.816f, 1.25f, 0.017f, 1f, 1.966f, 0.033f });
|
|
case PacManTimeSequence.Intermission3:
|
|
return DeltaToAbsolute(new float[] { 0, 0.316f, 0.7f, 3.35f, 0.83f, 3.67f });
|
|
}
|
|
}
|
|
|
|
private static float[] DeltaToAbsolute(float[] delta)
|
|
{
|
|
if (delta.Length < 1)
|
|
{
|
|
return new float[0];
|
|
}
|
|
|
|
float[] absolute = new float[delta.Length];
|
|
absolute[0] = delta[0];
|
|
for (int i = 1; i < delta.Length; i++)
|
|
{
|
|
absolute[i] = delta[i] + absolute[i - 1];
|
|
}
|
|
return absolute;
|
|
}
|
|
|
|
#endregion
|
|
|
|
public int TimeSequenceProgress
|
|
{
|
|
get => timeSequenceProgress;
|
|
}
|
|
|
|
public float TimeSequenceSecondsPassed
|
|
{
|
|
get => timeSequenceSecondsPassed;
|
|
set => TimeSequenceProgressToTime(value);
|
|
}
|
|
}
|
|
} |