Compare commits

..

2 Commits

Author SHA1 Message Date
74e6493108 Bunch of cleaning 2026-06-19 21:01:01 +02:00
b3d6ebaf67 Updated wait for start logic 2026-06-19 15:03:15 +02:00
8 changed files with 1565 additions and 1469 deletions

View File

@@ -266,6 +266,7 @@ MonoBehaviour:
networkManager: {fileID: 0}
ghostType: 3
startState: 0
targetIndicator: {fileID: 5838653651634851978}
--- !u!212 &4205939556154507887
SpriteRenderer:
m_ObjectHideFlags: 0

View File

@@ -14359,6 +14359,10 @@ PrefabInstance:
propertyPath: serializationData.Prefab
value:
objectReference: {fileID: 2302080303850322446, guid: 15ac0ed4c56c7784ea3ae9000fc2af1f, type: 3}
- target: {fileID: 2363388972565578221, guid: 15ac0ed4c56c7784ea3ae9000fc2af1f, type: 3}
propertyPath: m_IsActive
value: 1
objectReference: {fileID: 0}
- target: {fileID: 2453516282149910127, guid: 15ac0ed4c56c7784ea3ae9000fc2af1f, type: 3}
propertyPath: serializationData.Prefab
value:
@@ -14919,6 +14923,10 @@ PrefabInstance:
propertyPath: serializationData.Prefab
value:
objectReference: {fileID: 6158062801045854909, guid: 15ac0ed4c56c7784ea3ae9000fc2af1f, type: 3}
- target: {fileID: 6163542432859079166, guid: 15ac0ed4c56c7784ea3ae9000fc2af1f, type: 3}
propertyPath: m_IsActive
value: 1
objectReference: {fileID: 0}
- target: {fileID: 6197616826011328172, guid: 15ac0ed4c56c7784ea3ae9000fc2af1f, type: 3}
propertyPath: serializationData.Prefab
value:
@@ -15095,6 +15103,10 @@ PrefabInstance:
propertyPath: serializationData.Prefab
value:
objectReference: {fileID: 7427293407238038421, guid: 15ac0ed4c56c7784ea3ae9000fc2af1f, type: 3}
- target: {fileID: 7442305855105656444, guid: 15ac0ed4c56c7784ea3ae9000fc2af1f, type: 3}
propertyPath: m_IsActive
value: 1
objectReference: {fileID: 0}
- target: {fileID: 7460243684392980024, guid: 15ac0ed4c56c7784ea3ae9000fc2af1f, type: 3}
propertyPath: serializationData.Prefab
value:
@@ -15175,6 +15187,10 @@ PrefabInstance:
propertyPath: serializationData.Prefab
value:
objectReference: {fileID: 7731328103401244395, guid: 15ac0ed4c56c7784ea3ae9000fc2af1f, type: 3}
- target: {fileID: 7802576444906671046, guid: 15ac0ed4c56c7784ea3ae9000fc2af1f, type: 3}
propertyPath: m_IsActive
value: 1
objectReference: {fileID: 0}
- target: {fileID: 7815531346117498356, guid: 15ac0ed4c56c7784ea3ae9000fc2af1f, type: 3}
propertyPath: serializationData.Prefab
value:

File diff suppressed because it is too large Load Diff

View File

@@ -234,7 +234,7 @@ namespace Marro.PacManUdon
public void PacManCaught()
{
//return;
return;
StartTimeSequence(PacManTimeSequence.PacManCaught);
}

File diff suppressed because it is too large Load Diff

View File

@@ -22,7 +22,8 @@ namespace Marro.PacManUdon
Returning,
Entering,
Home,
Exiting
Exiting,
WaitingForStart,
}
public enum PacManGhostStartState
@@ -38,6 +39,7 @@ namespace Marro.PacManUdon
{
[SerializeField] private PacManGhostType ghostType;
[SerializeField] private PacManGhostStartState startState;
[SerializeField] private GameObject targetIndicator;
// External references
private GhostManager ghostManager;
@@ -115,6 +117,8 @@ namespace Marro.PacManUdon
Index = index;
SubscribeToEvent(NetworkEventType.GhostUpdate);
targetIndicator.transform.parent = transform.parent;
}
public void Reset()
@@ -122,37 +126,31 @@ namespace Marro.PacManUdon
// Debug.Log($"{gameObject} Reset!");
transform.SetLocalPositionAndRotation(startPosition, startRotation);
if (startState == PacManGhostStartState.Outside)
{
ghostState = PacManGhostState.Exiting;
OffGridTargetReached();
}
else
{
if (startState == PacManGhostStartState.TargetingIdlePosition1)
{
SetOffGridTarget(idlePosition1, false);
SetTargetDirection(Direction.Down);
}
else
{
SetTargetDirection(Direction.Up);
}
ghostState = PacManGhostState.Entering;
OffGridTargetReached();
}
offGrid = true;
isScared = false;
inTunnel = false;
kinematic = false;
followingPredefinedPath = false;
turnAroundSoon = false;
specialLook = false;
rngState = 1;
UpdateSpeed();
UpdateAnimator();
ghostState = PacManGhostState.WaitingForStart;
switch (startState)
{
case PacManGhostStartState.TargetingIdlePosition1:
SetTargetDirection(Direction.Up);
break;
case PacManGhostStartState.TargetingIdlePosition2:
SetTargetDirection(Direction.Down);
break;
default:
SetTargetDirection(Direction.Left);
break;
}
UpdateSpeed();
// Debug.Log($"{gameObject} reset with state: {state}, target: {target}, offGrid: {offGrid}");
}
@@ -160,7 +158,7 @@ namespace Marro.PacManUdon
public override void SyncedUpdate()
{
if (frozenState == PacManGhostFrozenState.Frozen ||
(frozenState == PacManGhostFrozenState.FrozenIfNotCaught && ghostState != PacManGhostState.Returning && ghostState != PacManGhostState.Entering))
(frozenState == PacManGhostFrozenState.FrozenIfNotCaught && ghostState != PacManGhostState.Returning && ghostState != PacManGhostState.Entering))
{
return;
}
@@ -189,6 +187,25 @@ namespace Marro.PacManUdon
return nextPosition;
}
if (ghostState == PacManGhostState.WaitingForStart)
{
switch (startState)
{
case PacManGhostStartState.TargetingIdlePosition1:
SetOffGridTarget(idlePosition1, false);
ghostState = PacManGhostState.Entering;
break;
case PacManGhostStartState.TargetingIdlePosition2:
SetOffGridTarget(idlePosition2, false);
ghostState = PacManGhostState.Entering;
break;
default:
ghostState = PacManGhostState.Exiting;
break;
}
OffGridTargetReached();
}
if (offGrid || ghostState == PacManGhostState.Returning)
{
PerformOffgridRelatedMovement(position, ref nextPosition);
@@ -266,30 +283,50 @@ namespace Marro.PacManUdon
var upcomingGridPosition = PositionToGrid(position + directionVectors[(int)direction]);
var availableDirections = collisionManager.GetAvailableDirections(upcomingGridPosition);
if ((availableDirections & (int)PacManCollisionInfoType.NoTurn) != 0 )
if ((availableDirections & (int)PacManCollisionInfoType.NoTurn) != 0)
{
return;
}
availableDirections &= ~(int)GetInverseDirection(direction); // Not allowed to turn around
if (!isScared && (availableDirections & (int)PacManCollisionInfoType.HorizontalOnly) != 0)
{
availableDirections &= ~0b0011;
availableDirections &= 0b1100;
}
availableDirections &= ~(int)GetInverseDirection(direction) & 0b1111; // Not allowed to turn around, also filter flags other than direction
if (availableDirections == 0)
{
return;
}
Direction newDirection;
if (isSingleBitSet[availableDirections])
{
newDirection = (Direction)availableDirections;
}
else
{
target = GetGridTarget(upcomingGridPosition);
targetIndicator.transform.localPosition = target;
newDirection = GetGridDirectionToTargetGreedy(availableDirections, upcomingGridPosition, target);
}
target = GetGridTarget(upcomingGridPosition);
var newDirection = GetGridDirectionToTargetGreedy(availableDirections, upcomingGridPosition, target);
if (newDirection == direction)
{
return;
}
SetTargetDirection(newDirection);
//Debug.Log($"{gameObject.name} Turned from direction {direction} to direction {newDirection}");
}
// Static fields are not yet supported on user-defined types
private readonly bool[] isSingleBitSet = new bool[]
{
//0000,0001, 0010, 0011 , 0100, 0101 , 0110 , 0111 , 1000, 1001 , 1010 , 1011 , 1100 , 1101 , 1110 , 1111
false, true, true, false, true, false, false, false, true, false, false, false, false, false, false, false
};
private void ApplyTargetDirection(Vector2 position, out Vector2 nextPosition)
{
var gridPosition = PositionToGrid(position);
@@ -313,7 +350,7 @@ namespace Marro.PacManUdon
if (nextValidDirectionIndex == predefinedPathIndex)
{
SetDirectionAndTargetDirection(predefinedPath[nextValidDirectionIndex]);
nextPosition = PositionToGrid(nextPosition) + GetVector(direction) * 0.01f;
nextPosition = PositionToGrid(nextPosition) + directionVectors[(int)direction] * 0.01f;
// Check if we've reached the end of the path, which includes making sure the path doesn't end on Vector2.zero
do
@@ -334,57 +371,56 @@ namespace Marro.PacManUdon
}
}
Vector2 GetGridTarget(Vector2 gridPosition)
private Vector2 GetGridTarget(Vector2 gridPosition)
{
// if (followingPredefinedPath)
// {
// predefinedPathIndex++;
// if (predefinedPathIndex >= predefinedPath.Length)
// {
// followingPredefinedPath = false;
// }
// return gridPosition + predefinedPath[predefinedPathIndex];
// }
if (isScared)
{
return gridPosition + directionVectors[(int)cardinalDirections[PseudoRNG() % 4]];
}
switch (ghostState)
if (ghostState == PacManGhostState.Returning)
{
return homePosition;
}
if (scattering)
{
return cornerPosition;
}
switch (ghostType)
{
default:
return gridPosition;
case PacManGhostState.Normal:
if (scattering)
case PacManGhostType.Blinky: // Chase PacMan directly
return PositionToGrid(pacMan.transform.localPosition);
case PacManGhostType.Pinky: // Try to get ahead of PacMan
return GetTargetAheadOfPacMan(4);
case PacManGhostType.Inky: // Try to attack from the opposite side of Blinky
var blinkyPosition = PositionToGrid(blinky.transform.localPosition);
return ((GetTargetAheadOfPacMan(2) - blinkyPosition) * 2) + blinkyPosition;
case PacManGhostType.Clyde: // Chase PacMan, but retreat to corner if PacMan gets to close
if (Vector2.Distance(gridPosition, PositionToGrid(pacMan.transform.localPosition)) < 8)
{
return cornerPosition;
}
switch (ghostType)
{
default:
return gridPosition;
case PacManGhostType.Blinky:
return PositionToGrid(pacMan.transform.localPosition);
case PacManGhostType.Pinky:
return PositionToGrid(pacMan.transform.localPosition) + pacMan.GetVector(direction) * 4;
case PacManGhostType.Inky:
return 2 * PositionToGrid(pacMan.transform.localPosition) + 4 * pacMan.GetVector(direction) - PositionToGrid(blinky.transform.localPosition);
case PacManGhostType.Clyde:
if (Vector2.Distance(gridPosition, PositionToGrid(pacMan.transform.localPosition)) >= 8)
{
return PositionToGrid(pacMan.transform.localPosition);
}
else
{
// Debug.Log($"{gameObject} goes to cornerPosition {cornerPosition}");
return cornerPosition;
}
}
case PacManGhostState.Returning:
return homePosition;
return PositionToGrid(pacMan.transform.localPosition);
}
}
private Vector2 GetTargetAheadOfPacMan(int tilesInFront)
{
var direction = pacMan.GetTargetDirection();
var result = PositionToGrid(pacMan.transform.localPosition) + directionVectors[(int)direction] * tilesInFront;
if (direction == Direction.Up) // Reproducing a bug in the original game
{
result.x -= tilesInFront;
}
return result;
}
bool CheckAndAllignToTargetX(Vector2 currentPosition, Vector2 nextPosition, Vector2 target)
{
return (currentPosition.x - target.x) * (nextPosition.x - target.x) <= 0.01;
@@ -455,13 +491,12 @@ namespace Marro.PacManUdon
}
private readonly Direction[] cardinalDirections = new Direction[] { Direction.Up, Direction.Left, Direction.Down, Direction.Right };
private readonly Direction[] horizontalDirections = new Direction[] { Direction.Left, Direction.Right };
Direction GetGridDirectionToTargetGreedy(int availableDirections, Vector2 gridPosition, Vector2 targetGridPosition)
{
Direction bestDirection = Direction.Zero;
float bestDistance = float.MaxValue;
foreach (var direction in horizontalOnly ? horizontalDirections : cardinalDirections)
foreach (var direction in cardinalDirections)
{
if (((int)direction & availableDirections) == 0)
{
@@ -499,33 +534,33 @@ namespace Marro.PacManUdon
if (!gameObject.activeInHierarchy)
return;
// Debug.Log($"{gameObject} UpdateAnimator with state: {ghostState}, isScared: {isScared}, direction: {direction}");
if (specialLook)
if (frozenState == PacManGhostFrozenState.FrozenIfNotCaught) // Looks like a bug but matches the original game
{
SetAnimatorGhostType((int)PacManGhostType.Special);
}
else if (!isScared) // Note: Don't update ghost type while scared as this interrupts the white/blue blinking
{
switch (ghostState)
{
default:
case PacManGhostState.Normal:
case PacManGhostState.Home:
case PacManGhostState.Exiting:
// Debug.Log($"{gameObject} Set GhostType in animator to: {GhostTypeToAnimationValue(ghostType)}");
SetAnimatorGhostType((int)ghostType);
break;
case PacManGhostState.Returning:
case PacManGhostState.Entering:
SetAnimatorGhostType((int)PacManGhostType.Caught);
break;
}
return;
}
if (specialLook || targetDirection != Direction.Zero)
{
SetAnimatorDirection((int)targetDirection);
}
if (isScared) // Don't update ghost type while scared as this interrupts the white/blue blinking
{
return;
}
PacManGhostType ghostType = this.ghostType;
if (specialLook)
{
ghostType = PacManGhostType.Special;
}
else if (ghostState == PacManGhostState.Returning || ghostState == PacManGhostState.Entering)
{
ghostType = PacManGhostType.Caught;
}
SetAnimatorGhostType((int)ghostType);
}
// A Udon bug means converting an enum to a float causes an exception unless the conversion from int to float is in a separate method
@@ -672,7 +707,13 @@ namespace Marro.PacManUdon
}
else
{
var oldFrozenState = frozenState;
frozenState = PacManGhostFrozenState.NotFrozen;
if (oldFrozenState == PacManGhostFrozenState.FrozenIfNotCaught) // Catch animator up after not updating during FrozenIfNotCaught
{
UpdateAnimator();
}
}
animator.speed = frozen && !keepAnimating ? 0 : 1; // This would cause issues if the returning sprite was animated, luckily it isn't :)
}

View File

@@ -51,16 +51,16 @@ namespace Marro.PacManUdon
transform.localPosition = new Vector3(position.x, position.y, transform.localPosition.z);
}
public Vector2 GetVector(Direction direction)
{
return directionVectors[(int)direction];
}
public Direction GetDirection()
{
return direction;
}
public Direction GetTargetDirection()
{
return targetDirection;
}
public void SetDirection(Direction direction)
{
this.direction = direction;
@@ -80,31 +80,6 @@ namespace Marro.PacManUdon
UpdateAnimator();
}
protected static Direction VectorToDirection(Vector2 vector)
{
var directionId = 0;
if (vector.x < 0)
{
directionId = 4;
}
else if (vector.x > 0)
{
directionId = 8;
}
if (vector.y < 0)
{
directionId += 1;
}
else if (vector.y > 0)
{
directionId += 2;
}
return (Direction)directionId;
}
protected static Direction HorizontalToDirection(float horizontal)
{
if (horizontal < 0)
@@ -137,26 +112,22 @@ namespace Marro.PacManUdon
{
data.Append(GetPosition(), ref index);
data.AppendAsByte((int)direction, ref index);
}
public void PadSyncedData(byte[] data, ref int index, NetworkEventType eventType)
{
index += 9;
data.AppendAsByte((int)targetDirection, ref index);
}
public override bool WriteSyncedData(byte[] data, ref int index, NetworkEventType eventType)
{
SetPosition(data.ReadVector2(ref index));
SetDirection((Direction)data.ReadByte(ref index));
direction = (Direction)data.ReadByte(ref index);
targetDirection = (Direction)data.ReadByte(ref index);
UpdateAnimator();
return true;
}
public bool ConsumeSyncedData(byte[] data, ref int index, NetworkEventType eventType)
public void PadSyncedData(ref int index)
{
index += 9;
return true;
index += 10;
}
#region Utils
@@ -231,6 +202,7 @@ namespace Marro.PacManUdon
{
result = Math.Round(currentPosition.y) != Math.Round(nextPosition.y);
}
return result;
}
#endregion

View File

@@ -341,7 +341,7 @@ namespace Marro.PacManUdon
if (kinematic || frozen || !enabled)
{
index += 1;
base.PadSyncedData(data, ref index, eventType);
PadSyncedData(ref index);
return;
}
@@ -360,7 +360,7 @@ namespace Marro.PacManUdon
if (kinematic || frozen || !enabled)
{
index += 1;
base.ConsumeSyncedData(data, ref index, eventType);
PadSyncedData(ref index);
return true;
}