Skip to content

Instantly share code, notes, and snippets.

@LordNed
Created March 25, 2015 01:44
Show Gist options
  • Save LordNed/0bbb3c97d7cb4da849b1 to your computer and use it in GitHub Desktop.
Save LordNed/0bbb3c97d7cb4da849b1 to your computer and use it in GitHub Desktop.
using UnityEngine;
using System.Collections;
using System;
[RequireComponent(typeof(CharacterController2D))]
public class CreatureGarfunkel : StatelyMachine, IDamageable
{
public enum MoveDirection
{
None, Left, Right
}
public IdleState Idle;
public EnragedState Enraged;
[SerializeField] private float m_rageIncreaseRate = 0.2f;
[SerializeField] private float m_rageDecayRate = 0.3f;
[SerializeField] private float m_maxHealth = 25f;
[SerializeField] private float m_enrageThreashold = 0.9f;
public float Gravity = -25f;
private float m_currentRage;
private float m_currentHealth;
private Vector3 m_velocity;
private CharacterController2D m_controller;
private MoveDirection m_movementDir;
private void Start()
{
m_currentRage = 0f;
m_currentHealth = m_maxHealth;
m_controller = GetComponent<CharacterController2D>();
m_movementDir = MoveDirection.None;
}
[System.Serializable]
public class EnragedState : BaseCreatureState
{
private CreatureGarfunkel m_baseState;
public override void OnAddedToMachine(StatelyMachine machine)
{
m_baseState = (CreatureGarfunkel)machine;
base.OnAddedToMachine(machine);
}
}
[System.Serializable]
public class IdleState : BaseCreatureState
{
private CreatureGarfunkel m_baseState;
public override void OnAddedToMachine(StatelyMachine machine)
{
m_baseState = (CreatureGarfunkel)machine;
base.OnAddedToMachine(machine);
StartCoroutine(TestMovementState());
}
private IEnumerator TestMovementState()
{
while(true)
{
m_baseState.m_movementDir = (MoveDirection)UnityEngine.Random.Range(0, 3);
yield return new WaitForSeconds(UnityEngine.Random.Range(0.5f, 1.2f));
}
}
public override void Update()
{
base.Update();
// Apply decay to any rage we currently have.
m_baseState.m_currentRage -= m_baseState.m_rageDecayRate * Time.deltaTime;
m_baseState.m_currentRage = Mathf.Clamp(m_baseState.m_currentRage, 0f, 1f);
if (m_baseState.m_currentRage >= m_baseState.m_enrageThreashold)
{
Trigger("ToEnraged");
}
}
}
[System.Serializable]
public class BaseCreatureState : StatelyState, IDamageable
{
public virtual void TakeDamage(GameObject attacker, float damageAmount)
{
}
}
public void TakeDamage(GameObject attacker, float damageAmount)
{
// Forward the damage event onto the current state.
BaseCreatureState baseState = currentState as BaseCreatureState;
if(baseState != null)
{
baseState.TakeDamage(attacker, damageAmount);
}
// Each time we take a bit of damage, increase our rage amount.
// Rage will automatically decay over time so if you space out
// your hits enough, then it won't ever get enraged. However,
// hitting too fast/often will cause it to trigger the enraged
// state which will have its own cooldown.
m_currentRage += m_rageIncreaseRate;
m_currentHealth -= damageAmount;
// Impart some velocity from the attacker.
Vector3 dir = transform.position - attacker.transform.position;
dir.Normalize();
m_velocity += dir * 5f;
if(m_currentHealth <= 0f)
{
Debug.Log("Garfunkel has died. :(");
Destroy(gameObject);
}
}
public override void Update()
{
base.Update();
// Only allow us to change velocity state
// if we're on the ground.
if(m_controller.isGrounded)
{
switch (m_movementDir)
{
case MoveDirection.None:
m_velocity.x = 0;
break;
case MoveDirection.Left:
m_velocity.x = -4;
break;
case MoveDirection.Right:
m_velocity.x = 4;
break;
}
}
// Apply gravity and move us.
m_velocity.y += Gravity * Time.deltaTime;
DoThatTracyThing(transform.position + (m_velocity * Time.deltaTime));
m_controller.move(m_velocity * Time.deltaTime);
if (m_controller.isGrounded)
m_velocity.y = 0;
}
private void DoThatTracyThing(Vector3 destPos)
{
Vector3 curPos = transform.position;
// Look down to make sure where we're trying to go is valid.
int xBlock = Mathf.RoundToInt(destPos.x + (-1 * Mathf.Sign(destPos.x)));
Vector3 traceStartPos = new Vector3(xBlock, curPos.y + 1.15f, 0f);
Debug.DrawRay(traceStartPos, Vector3.down * 2.5f, Color.blue);
RaycastHit2D hitInfo = Physics2D.Raycast(traceStartPos, Vector3.down, 2.5f, (1 << LayerMask.NameToLayer("Platforms")));
if(hitInfo.collider != null)
{
// We did hit something. Let's check the Y value of our hit. If it's 1 block above us,
float deltaY = hitInfo.point.y - curPos.y;
if(deltaY > 0f && deltaY < 1.25f)
{
// Jump and keep going that direction lol
m_velocity.y = 8;
}
}
else
{
// We didn't hit anything. Don't move that way!
m_velocity.x = 0;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment