evershade/Packages/super-tiled2unity.v2.2.0/Samples~/Overhead/Sprites/MegaDad/OverheadMegaDadController.cs

214 lines
6.7 KiB
C#

using System.Collections;
using System.Linq;
using UnityEngine;
namespace MegaDad
{
public class OverheadMegaDadController : MonoBehaviour
{
private enum State
{
WaitingForInput,
Moving,
Drowning
}
private State m_State;
private const float MovementBlockSize = 8.0f;
private const float MovingSpeedPPS = 64.0f;
private const float TimeToMoveOneBlock = MovementBlockSize / MovingSpeedPPS;
public GameObject m_SplashPrefab;
private Vector2 m_Facing = Vector2.down;
private Animator m_Animator;
private float m_MoveTimer;
private Vector2 m_MovingFrom;
private Vector2 m_MovingTo;
private Vector2 m_SpawnPoint;
private SpriteRenderer m_Renderer;
private void Awake()
{
m_Animator = gameObject.GetComponentInChildren<Animator>();
m_Animator.SetFloat("Dir_x", m_Facing.x);
m_Animator.SetFloat("Dir_y", m_Facing.y);
m_Renderer = gameObject.GetComponentInChildren<SpriteRenderer>();
}
private void Start()
{
SetOverheadCamera();
// Find the position on the game map we're supposed to spawn at
#if UNITY_2023_1_OR_NEWER
var spawner = FindObjectsByType<SuperTiled2Unity.SuperObject>(FindObjectsSortMode.None).FirstOrDefault(s => s.m_TiledName == "Spawn");
#else
var spawner = FindObjectsOfType<SuperTiled2Unity.SuperObject>().FirstOrDefault(s => s.m_TiledName == "Spawn");
#endif
if (spawner != null)
{
m_SpawnPoint = spawner.transform.position;
}
// Make sure the player starts off aligned to the (imaginary) grid
m_SpawnPoint.x = RoundToGrid(m_SpawnPoint.x);
m_SpawnPoint.y = RoundToGrid(m_SpawnPoint.y);
gameObject.transform.localPosition = m_SpawnPoint;
m_State = State.WaitingForInput;
}
private void Update()
{
if (m_State == State.Moving)
{
MoveUpdate();
}
if (m_State == State.WaitingForInput)
{
InputUpdate();
}
}
private void LateUpdate()
{
m_Animator.SetFloat("Dir_x", m_Facing.x);
m_Animator.SetFloat("Dir_y", m_Facing.y);
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.layer == LayerMask.NameToLayer("Water"))
{
StartCoroutine(Drowned());
}
}
private void MoveUpdate()
{
// Move towards our target position
m_MoveTimer += Time.deltaTime;
var ratio = m_MoveTimer / TimeToMoveOneBlock;
var pos = Vector2.Lerp(m_MovingFrom, m_MovingTo, ratio);
gameObject.transform.position = pos;
if (ratio >= 1.0f)
{
m_State = State.WaitingForInput;
m_MoveTimer = Mathf.Repeat(m_MoveTimer, TimeToMoveOneBlock);
}
}
private void InputUpdate()
{
Vector2 dv = Vector2.zero;
dv.x = Input.GetAxisRaw("Horizontal");
dv.y = Input.GetAxisRaw("Vertical");
// Favor horizontal movement over vertical
if (dv.x != 0)
{
m_Facing.x = dv.x;
m_Facing.y = 0;
}
else if (dv.y != 0)
{
m_Facing.x = 0;
m_Facing.y = dv.y;
}
m_Facing.Normalize();
m_MovingFrom = gameObject.transform.position;
if (dv.SqrMagnitude() > 0 && !Input.GetKey(KeyCode.LeftControl))
{
// We are attempting to move so we want to animate
m_Animator.SetBool("Moving", true);
// We may not be allowed to move, however, if that would cause a collision with the default colliders
var pos = gameObject.transform.position;
var hit = Physics2D.Raycast(pos, m_Facing, MovementBlockSize, 1 << LayerMask.NameToLayer("Default"));
if (hit)
{
m_State = State.WaitingForInput;
m_MoveTimer = 0.0f;
}
else
{
m_State = State.Moving;
m_MovingTo = m_MovingFrom + m_Facing * MovementBlockSize;
}
}
else
{
// No input means we aren't even trying to move
m_MoveTimer = 0.0f;
m_Animator.SetBool("Moving", false);
}
}
private int RoundToGrid(float value)
{
if (value < 0)
{
return (int)(((value - MovementBlockSize * 0.5f) / MovementBlockSize)) * (int)MovementBlockSize;
}
return (int)(((value + MovementBlockSize * 0.5f) / MovementBlockSize)) * (int)MovementBlockSize;
}
private IEnumerator Drowned()
{
m_State = State.Drowning;
// Place the player in the water
var pos = m_MovingTo + m_Facing * MovementBlockSize;
// Move the player into the water
gameObject.transform.position = pos;
m_MoveTimer = 0.0f;
yield return new WaitForSeconds(0.0675f);
// Move the player to the spawn location and make him invisible
gameObject.transform.position = m_SpawnPoint;
m_Facing = Vector2.down;
m_Animator.SetBool("Moving", false);
m_Renderer.enabled = false;
// Spawn a splash prefab where we fell into the water
var splash = Instantiate(m_SplashPrefab, pos, Quaternion.identity);
Destroy(splash, 0.5f);
yield return new WaitForSeconds(0.125f);
for (int i = 0; i < 8; i++)
{
m_Renderer.enabled = !m_Renderer.enabled;
yield return new WaitForSeconds(0.125f);
}
// We're done. Go back to waiting for input.
m_Renderer.enabled = true;
m_State = State.WaitingForInput;
}
private void SetOverheadCamera()
{
// This example requires a sort axis for sorting
// (This could be set globablly for all cameras in the project settings)
var camera = GameObject.FindGameObjectWithTag("MainCamera").GetComponent<Camera>();
camera.transparencySortMode = TransparencySortMode.CustomAxis;
camera.transparencySortAxis = Vector3.up;
}
}
}