Added time sequence buttons

This commit is contained in:
2025-12-26 16:05:03 +01:00
parent a251763158
commit 8dec85e9f2
10 changed files with 5401 additions and 381 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -43,7 +43,7 @@ MonoBehaviour:
Data: Data:
- Name: - Name:
Entry: 12 Entry: 12
Data: 36 Data: 37
- Name: - Name:
Entry: 7 Entry: 7
Data: Data:
@@ -1789,25 +1789,19 @@ MonoBehaviour:
Data: Data:
- Name: $k - Name: $k
Entry: 1 Entry: 1
Data: currentTimeSequence Data: waitingForTimeSequenceFinish
- Name: $v - Name: $v
Entry: 7 Entry: 7
Data: 110|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor Data: 110|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField - Name: <Name>k__BackingField
Entry: 1 Entry: 1
Data: currentTimeSequence Data: waitingForTimeSequenceFinish
- Name: <UserType>k__BackingField - Name: <UserType>k__BackingField
Entry: 7 Entry: 9
Data: 111|System.RuntimeType, mscorlib Data: 108
- Name:
Entry: 1
Data: Marro.PacManUdon.PacManTimeSequence, Assembly-CSharp
- Name:
Entry: 8
Data:
- Name: <SystemType>k__BackingField - Name: <SystemType>k__BackingField
Entry: 9 Entry: 9
Data: 55 Data: 108
- Name: <SyncMode>k__BackingField - Name: <SyncMode>k__BackingField
Entry: 7 Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
@@ -1822,7 +1816,7 @@ MonoBehaviour:
Data: false Data: false
- Name: _fieldAttributes - Name: _fieldAttributes
Entry: 7 Entry: 7
Data: 112|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], Data: 111|System.Collections.Generic.List`1[[System.Attribute, mscorlib]],
mscorlib mscorlib
- Name: - Name:
Entry: 12 Entry: 12
@@ -1844,19 +1838,25 @@ MonoBehaviour:
Data: Data:
- Name: $k - Name: $k
Entry: 1 Entry: 1
Data: hasTimeSequenceQueued Data: currentTimeSequence
- Name: $v - Name: $v
Entry: 7 Entry: 7
Data: 113|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor Data: 112|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField - Name: <Name>k__BackingField
Entry: 1 Entry: 1
Data: hasTimeSequenceQueued Data: currentTimeSequence
- Name: <UserType>k__BackingField - Name: <UserType>k__BackingField
Entry: 9 Entry: 7
Data: 108 Data: 113|System.RuntimeType, mscorlib
- Name:
Entry: 1
Data: Marro.PacManUdon.PacManTimeSequence, Assembly-CSharp
- Name:
Entry: 8
Data:
- Name: <SystemType>k__BackingField - Name: <SystemType>k__BackingField
Entry: 9 Entry: 9
Data: 108 Data: 55
- Name: <SyncMode>k__BackingField - Name: <SyncMode>k__BackingField
Entry: 7 Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
@@ -1893,25 +1893,19 @@ MonoBehaviour:
Data: Data:
- Name: $k - Name: $k
Entry: 1 Entry: 1
Data: timeSequenceQueue Data: hasTimeSequenceQueued
- Name: $v - Name: $v
Entry: 7 Entry: 7
Data: 115|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor Data: 115|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField - Name: <Name>k__BackingField
Entry: 1 Entry: 1
Data: timeSequenceQueue Data: hasTimeSequenceQueued
- Name: <UserType>k__BackingField - Name: <UserType>k__BackingField
Entry: 7 Entry: 9
Data: 116|System.RuntimeType, mscorlib Data: 108
- Name:
Entry: 1
Data: VRC.SDK3.Data.DataList, VRCSDK3
- Name:
Entry: 8
Data:
- Name: <SystemType>k__BackingField - Name: <SystemType>k__BackingField
Entry: 9 Entry: 9
Data: 116 Data: 108
- Name: <SyncMode>k__BackingField - Name: <SyncMode>k__BackingField
Entry: 7 Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
@@ -1926,7 +1920,62 @@ MonoBehaviour:
Data: false Data: false
- Name: _fieldAttributes - Name: _fieldAttributes
Entry: 7 Entry: 7
Data: 117|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], Data: 116|System.Collections.Generic.List`1[[System.Attribute, mscorlib]],
mscorlib
- Name:
Entry: 12
Data: 0
- Name:
Entry: 13
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 8
Data:
- Name:
Entry: 7
Data:
- Name: $k
Entry: 1
Data: timeSequenceQueue
- Name: $v
Entry: 7
Data: 117|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField
Entry: 1
Data: timeSequenceQueue
- Name: <UserType>k__BackingField
Entry: 7
Data: 118|System.RuntimeType, mscorlib
- Name:
Entry: 1
Data: VRC.SDK3.Data.DataList, VRCSDK3
- Name:
Entry: 8
Data:
- Name: <SystemType>k__BackingField
Entry: 9
Data: 118
- Name: <SyncMode>k__BackingField
Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
- Name:
Entry: 6
Data:
- Name:
Entry: 8
Data:
- Name: <IsSerialized>k__BackingField
Entry: 5
Data: false
- Name: _fieldAttributes
Entry: 7
Data: 119|System.Collections.Generic.List`1[[System.Attribute, mscorlib]],
mscorlib mscorlib
- Name: - Name:
Entry: 12 Entry: 12
@@ -1951,13 +2000,13 @@ MonoBehaviour:
Data: timeSequenceSecondsPassed Data: timeSequenceSecondsPassed
- Name: $v - Name: $v
Entry: 7 Entry: 7
Data: 118|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor Data: 120|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField - Name: <Name>k__BackingField
Entry: 1 Entry: 1
Data: timeSequenceSecondsPassed Data: timeSequenceSecondsPassed
- Name: <UserType>k__BackingField - Name: <UserType>k__BackingField
Entry: 7 Entry: 7
Data: 119|System.RuntimeType, mscorlib Data: 121|System.RuntimeType, mscorlib
- Name: - Name:
Entry: 1 Entry: 1
Data: System.Single, mscorlib Data: System.Single, mscorlib
@@ -1966,7 +2015,7 @@ MonoBehaviour:
Data: Data:
- Name: <SystemType>k__BackingField - Name: <SystemType>k__BackingField
Entry: 9 Entry: 9
Data: 119 Data: 121
- Name: <SyncMode>k__BackingField - Name: <SyncMode>k__BackingField
Entry: 7 Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
@@ -1981,14 +2030,14 @@ MonoBehaviour:
Data: false Data: false
- Name: _fieldAttributes - Name: _fieldAttributes
Entry: 7 Entry: 7
Data: 120|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], Data: 122|System.Collections.Generic.List`1[[System.Attribute, mscorlib]],
mscorlib mscorlib
- Name: - Name:
Entry: 12 Entry: 12
Data: 1 Data: 1
- Name: - Name:
Entry: 7 Entry: 7
Data: 121|UdonSharp.UdonSyncedAttribute, UdonSharp.Runtime Data: 123|UdonSharp.UdonSyncedAttribute, UdonSharp.Runtime
- Name: - Name:
Entry: 8 Entry: 8
Data: Data:
@@ -2012,7 +2061,7 @@ MonoBehaviour:
Data: timeSequenceProgress Data: timeSequenceProgress
- Name: $v - Name: $v
Entry: 7 Entry: 7
Data: 122|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor Data: 124|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField - Name: <Name>k__BackingField
Entry: 1 Entry: 1
Data: timeSequenceProgress Data: timeSequenceProgress
@@ -2036,7 +2085,7 @@ MonoBehaviour:
Data: false Data: false
- Name: _fieldAttributes - Name: _fieldAttributes
Entry: 7 Entry: 7
Data: 123|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], Data: 125|System.Collections.Generic.List`1[[System.Attribute, mscorlib]],
mscorlib mscorlib
- Name: - Name:
Entry: 12 Entry: 12
@@ -2061,13 +2110,13 @@ MonoBehaviour:
Data: timeSequenceKeyframeTimes Data: timeSequenceKeyframeTimes
- Name: $v - Name: $v
Entry: 7 Entry: 7
Data: 124|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor Data: 126|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor
- Name: <Name>k__BackingField - Name: <Name>k__BackingField
Entry: 1 Entry: 1
Data: timeSequenceKeyframeTimes Data: timeSequenceKeyframeTimes
- Name: <UserType>k__BackingField - Name: <UserType>k__BackingField
Entry: 7 Entry: 7
Data: 125|System.RuntimeType, mscorlib Data: 127|System.RuntimeType, mscorlib
- Name: - Name:
Entry: 1 Entry: 1
Data: System.Single[], mscorlib Data: System.Single[], mscorlib
@@ -2076,7 +2125,7 @@ MonoBehaviour:
Data: Data:
- Name: <SystemType>k__BackingField - Name: <SystemType>k__BackingField
Entry: 9 Entry: 9
Data: 125 Data: 127
- Name: <SyncMode>k__BackingField - Name: <SyncMode>k__BackingField
Entry: 7 Entry: 7
Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib
@@ -2091,7 +2140,7 @@ MonoBehaviour:
Data: false Data: false
- Name: _fieldAttributes - Name: _fieldAttributes
Entry: 7 Entry: 7
Data: 126|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], Data: 128|System.Collections.Generic.List`1[[System.Attribute, mscorlib]],
mscorlib mscorlib
- Name: - Name:
Entry: 12 Entry: 12

View File

@@ -106,6 +106,12 @@ namespace Marro.PacManUdon
StartTimeSequence(PacManTimeSequence.WaitForStartTimeout); StartTimeSequence(PacManTimeSequence.WaitForStartTimeout);
} }
public void ResetButtonPressed()
{
Debug.Log($"{gameObject} Reset button was pressed!");
Start();
}
public void StartGameButtonPressed() public void StartGameButtonPressed()
{ {
Debug.Log($"{gameObject} Start Game Button was pressed!"); Debug.Log($"{gameObject} Start Game Button was pressed!");
@@ -491,338 +497,5 @@ namespace Marro.PacManUdon
} }
get => level; get => level;
} }
#region TIME SEQUENCE BEHAVIOUR
// 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;
PacManTimeSequence currentTimeSequence;
bool hasTimeSequenceQueued;
private DataList timeSequenceQueue;
[UdonSynced] float timeSequenceSecondsPassed;
int timeSequenceProgress;
float[] timeSequenceKeyframeTimes;
private void StartTimeSequence(PacManTimeSequence timeSequence)
{
if (timeSequenceQueue == null)
{
timeSequenceQueue = new DataList();
}
if (currentlyInTimeSequence == true)
{
int timeSequenceInt = (int)timeSequence; // Doing the conversion in the line below crashes the script. I love working in Udon
timeSequenceQueue.Add(timeSequenceInt);
hasTimeSequenceQueued = true;
return;
}
Debug.Log($"StartTimeSequence: {timeSequence}");
currentlyInTimeSequence = true;
currentTimeSequence = timeSequence;
timeSequenceProgress = 0;
timeSequenceSecondsPassed = 0;
timeSequenceKeyframeTimes = GetTimeSequenceKeyframeTimes(timeSequence);
TimeSequenceProgressToTime(timeSequenceSecondsPassed);
}
private void InsertTimeSequence(PacManTimeSequence timeSequence)
{
StartTimeSequence(timeSequence);
}
private void TimeSequenceUpdate(float deltaSeconds)
{
if (!currentlyInTimeSequence && hasTimeSequenceQueued)
{
timeSequenceQueue.TryGetValue(0, out DataToken nextTimeSequence);
StartTimeSequence((PacManTimeSequence)nextTimeSequence.Int);
timeSequenceQueue.RemoveAt(0);
hasTimeSequenceQueued = timeSequenceQueue.Count > 0 ? true : false;
return;
}
if (currentlyInTimeSequence)
{
if (hasTimeSequenceQueued)
{
while (currentlyInTimeSequence)
{
TimeSequenceSkipToNextStep();
}
}
else
{
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 (!hasTimeSequenceQueued)
{
TimeSequenceExecuteFinished();
}
}
else
{
waitingForTimeSequenceFinish = true;
}
}
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.WaitForStartTimeout:
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.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.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.WaitForStartTimeout:
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.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;
}
public int TimeSequenceProgress
{
get => timeSequenceProgress;
}
public float TimeSequenceSecondsPassed
{
get => timeSequenceSecondsPassed;
set => TimeSequenceProgressToTime(value);
}
#endregion
} }
} }

View File

@@ -62,7 +62,7 @@ namespace Marro.PacManUdon
break; break;
} }
InsertTimeSequence(nextSequence); StartTimeSequence(nextSequence);
} }
} }
} }

View File

@@ -64,12 +64,10 @@ namespace Marro.PacManUdon
private void TimeSequenceFinalizeIntermission3() private void TimeSequenceFinalizeIntermission3()
{ {
soundManager.StopAllSound(); soundManager.StopAllSound();
StartTimeSequence(PacManTimeSequence.StartNewLevel);
} }
private void TimeSequenceFinishedIntermission3() private void TimeSequenceFinishedIntermission3()
{ {
soundManager.StopAllSound();
StartTimeSequence(PacManTimeSequence.StartNewLevel); StartTimeSequence(PacManTimeSequence.StartNewLevel);
} }
} }

View File

@@ -43,7 +43,7 @@ namespace Marro.PacManUdon
nextSequence = PacManTimeSequence.GameOver; nextSequence = PacManTimeSequence.GameOver;
} }
InsertTimeSequence(nextSequence); StartTimeSequence(nextSequence);
} }
} }
} }

View File

@@ -0,0 +1,420 @@
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;
PacManTimeSequence currentTimeSequence;
bool hasTimeSequenceQueued;
private DataList timeSequenceQueue;
[UdonSynced] float timeSequenceSecondsPassed;
int timeSequenceProgress;
float[] timeSequenceKeyframeTimes;
private void StartTimeSequence(PacManTimeSequence timeSequence)
{
if (timeSequenceQueue == null)
{
timeSequenceQueue = new DataList();
}
if (currentlyInTimeSequence == true)
{
int timeSequenceInt = (int)timeSequence; // Doing the conversion in the line below crashes the script. I love working in Udon
timeSequenceQueue.Add(timeSequenceInt);
hasTimeSequenceQueued = true;
return;
}
Debug.Log($"StartTimeSequence: {timeSequence}");
currentlyInTimeSequence = true;
currentTimeSequence = timeSequence;
timeSequenceProgress = 0;
timeSequenceSecondsPassed = 0;
timeSequenceKeyframeTimes = GetTimeSequenceKeyframeTimes(timeSequence);
TimeSequenceProgressToTime(timeSequenceSecondsPassed);
}
private void TimeSequenceUpdate(float deltaSeconds)
{
if (!currentlyInTimeSequence && hasTimeSequenceQueued)
{
timeSequenceQueue.TryGetValue(0, out DataToken nextTimeSequence);
StartTimeSequence((PacManTimeSequence)nextTimeSequence.Int);
timeSequenceQueue.RemoveAt(0);
hasTimeSequenceQueued = timeSequenceQueue.Count > 0 ? true : false;
return;
}
if (currentlyInTimeSequence)
{
if (hasTimeSequenceQueued)
{
while (currentlyInTimeSequence)
{
TimeSequenceSkipToNextStep();
}
}
else
{
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 (!hasTimeSequenceQueued)
{
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);
}
}
}

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: ac77c2211d465d445934f6bf7398f743 guid: a11df70b39ac2924c825f9951b58dafd
MonoImporter: MonoImporter:
externalObjects: {} externalObjects: {}
serializedVersion: 2 serializedVersion: 2

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 445b4cd5c436f3645824ef18948c8593
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: