namespace Marro.PacManUdon { using System; using UnityEngine; public enum Direction { Zero = 0, Up = 1, Down = 2, Left = 4, Right = 8, UpLeft = 5, UpRight = 9, DownLeft = 6, DownRight = 10 } public enum DirectionAxis { Horizontal = 0, Vertical = 1, Both = 2 } public abstract class GridMover : SyncedObject { protected Direction direction; // Cannot be static, much to my annoyance public readonly Vector2[] directionVectors = { Vector2.zero, // 0 Vector2.down, // 1 Vector2.up, // 2 Vector2.zero, // 3 Vector2.left, // 4 Vector2.down + Vector2.left, // 5 Vector2.up + Vector2.left, // 6 Vector2.left, // 7 Vector2.right, // 8 Vector2.down + Vector2.right, // 9 Vector2.up + Vector2.right, // 10 Vector2.right, // 11 Vector2.zero, // 12 Vector2.down, // 13 Vector2.up, // 14 Vector2.zero, // 15 }; public virtual Vector2 GetPosition() { return (Vector2)transform.localPosition; } public virtual void SetPosition(Vector2 position) { 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 void SetDirection(Direction direction) { this.direction = direction; UpdateAnimator(); } public void SetDirection(Vector2 vector) { direction = VectorToDirection(vector); 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) { return Direction.Left; } if (horizontal > 0) { return Direction.Right; } return Direction.Zero; } protected static Direction VerticalToDirection(float vertical) { if (vertical < 0) { return Direction.Up; } if (vertical > 0) { return Direction.Down; } return Direction.Zero; } protected abstract void UpdateAnimator(); public override void CollectSyncedData(byte[] data, ref int index, NetworkEventType eventType) { data.Append(GetPosition(), ref index); data.AppendAsByte((int)direction, ref index); } public void PadSyncedData(byte[] data, ref int index, NetworkEventType eventType) { index += 9; } public override bool WriteSyncedData(byte[] data, ref int index, NetworkEventType eventType) { SetPosition(data.ReadVector2(ref index)); SetDirection((Direction)data.ReadByte(ref index)); return true; } public bool ConsumeSyncedData(byte[] data, ref int index, NetworkEventType eventType) { index += 9; return true; } #region Utils public static Direction GetInverseDirection(Direction direction) { switch (direction) { case Direction.Up: return Direction.Down; case Direction.Down: return Direction.Up; case Direction.Left: return Direction.Right; case Direction.Right: return Direction.Left; case Direction.UpLeft: return Direction.DownRight; case Direction.UpRight: return Direction.DownLeft; case Direction.DownLeft: return Direction.UpRight; case Direction.DownRight: return Direction.UpLeft; default: return Direction.Zero; } } public static bool IsVertical(Direction direction) => ((int)direction & 0b0011) != 0; public static bool IsHorizontal(Direction direction) => ((int)direction & 0b1100) != 0; public static Direction VerticalComponent(Direction direction) => (Direction)((int)direction & 0b0011); public static Direction HorizontalComponent(Direction direction) => (Direction)((int)direction & 0b1100); public static Vector2 GetNextPosition(Vector2 currentPosition, Vector2 directionVector, float speed, float deltaTime) { var nextPosition = currentPosition + deltaTime * speed * directionVector; nextPosition = new Vector2((nextPosition.x + 32) % 32, (nextPosition.y + 32) % 32); return nextPosition; } public static Vector2 PositionToGrid(Vector2 position) { return new Vector2((int)position.x + 0.5f, (int)position.y + 0.5f); } public static bool CrossesTileBorder(Vector2 currentPosition, Vector2 nextPosition, Direction direction) { bool result = false; if (IsHorizontal(direction)) { result = Math.Floor(currentPosition.x) != Math.Floor(nextPosition.x); } if (!result && IsVertical(direction)) { result = Math.Floor(currentPosition.y) != Math.Floor(nextPosition.y); } return result; } public static bool CrossesTileCenter(Vector2 currentPosition, Vector2 nextPosition, Direction direction) { bool result = false; if (IsHorizontal(direction)) { result = Math.Round(currentPosition.x) != Math.Round(nextPosition.x); } if (!result && IsVertical(direction)) { result = Math.Round(currentPosition.y) != Math.Round(nextPosition.y); } return result; } #endregion } }