Skip to content

Instantly share code, notes, and snippets.

@Ratstail91
Created June 29, 2018 15:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Ratstail91/6751212452a6fde15710e05de88fa2fd to your computer and use it in GitHub Desktop.
Save Ratstail91/6751212452a6fde15710e05de88fa2fd to your computer and use it in GitHub Desktop.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Blowsnower : MonoBehaviour {
//structures
public enum Behaviour {
IDLE, WANDER, ATTACK, MELTED
}
//components
Animator animator;
CircleCollider2D circleCollider;
Rigidbody2D rigidBody;
//movement
Vector2 deltaForce;
Vector2 lastDirection;
const float speed = 0.3f;
//behaviour
GameObject player;
public GameObject snowballPrefab;
public Behaviour behaviour = Behaviour.IDLE;
float idleTimer = float.NegativeInfinity;
float walkTimer = float.NegativeInfinity;
float shotTimer = float.NegativeInfinity;
float shotSpawnDistance = 0.15f;
//item
public GameObject collectable;
void Awake() {
animator = GetComponent<Animator> ();
circleCollider = GetComponent<CircleCollider2D> ();
rigidBody = GetComponent<Rigidbody2D> ();
lastDirection = new Vector2 (0, -1);
}
void Start() {
//cache the player reference
player = GameObject.Find ("Player");
if (collectable != null) {
collectable.SetActive (false);
}
}
void Update() {
HandleBehaviour ();
SendAnimationInfo ();
}
void FixedUpdate() {
HandleMove ();
}
void OnCollisionStay2D(Collision2D collision) {
//collide with anything, change direction
if (behaviour == Behaviour.WANDER) {
deltaForce = Rotate (deltaForce, 90);
//snap to an 90 degree angle
if (deltaForce.x < 0.001f && deltaForce.x > -0.001f) {
deltaForce.x = 0;
}
if (deltaForce.y < 0.001f && deltaForce.y > -0.001f) {
deltaForce.y = 0;
}
deltaForce.Normalize ();
}
}
void OnTriggerEnter2D(Collider2D collider) {
if (behaviour != Behaviour.MELTED) {
FireDamager fire = collider.gameObject.GetComponent<FireDamager> ();
if (fire != null) {
behaviour = Behaviour.MELTED;
deltaForce = Vector2.zero;
idleTimer = walkTimer = shotTimer = float.NegativeInfinity;
circleCollider.enabled = false;
animator.SetBool ("melted", true);
if (collectable != null) {
collectable.SetActive (true);
Rigidbody2D rb = collectable.GetComponent<Rigidbody2D> ();
if (rb != null) {
rb.position = rigidBody.position;
} else {
collectable.transform.position = rigidBody.position;
}
}
return;
}
}
if (behaviour == Behaviour.MELTED) {
IceDamager ice = collider.gameObject.GetComponent<IceDamager> ();
if (ice != null) {
behaviour = Behaviour.IDLE;
circleCollider.enabled = true;
animator.SetBool ("melted", false);
return;
}
}
}
void HandleBehaviour() {
//the result
Behaviour newBehaviour = behaviour;
switch (behaviour) {
case Behaviour.IDLE:
if (float.IsNegativeInfinity (idleTimer)) {
idleTimer = Time.time;
deltaForce = Vector2.zero;
}
//idle for 2 seconds
if (Time.time - idleTimer > 2f) {
idleTimer = float.NegativeInfinity;
newBehaviour = Behaviour.WANDER;
}
break;
case Behaviour.WANDER:
if (float.IsNegativeInfinity (walkTimer)) {
walkTimer = Time.time;
//actually walk
deltaForce = Vector2.zero;
switch (Random.Range (0, 4)) {
case 0:
deltaForce.x = 1;
break;
case 1:
deltaForce.x = -1;
break;
case 2:
deltaForce.y = 1;
break;
case 3:
deltaForce.y = -1;
break;
}
}
//walk for 2 seconds
if (Time.time - walkTimer > 2f) {
walkTimer = float.NegativeInfinity;
newBehaviour = Behaviour.IDLE;
}
break;
case Behaviour.ATTACK:
//DO NOTHING
break;
case Behaviour.MELTED:
//DO NOTHING
break;
}
//override if can attack
if (Vector3.Distance(player.transform.position, transform.position) < 0.8f && behaviour != Behaviour.MELTED) {
newBehaviour = Behaviour.ATTACK;
deltaForce = Vector2.zero;
//should've used blend trees
lastDirection.x = player.transform.position.x - transform.position.x;
lastDirection.y = player.transform.position.y - transform.position.y;
if (Mathf.Abs (lastDirection.x) > Mathf.Abs (lastDirection.y)) {
lastDirection.y = 0;
} else {
lastDirection.x = 0;
}
lastDirection.Normalize ();
//shoot on a timer
if (Time.time - shotTimer > 3f) {
shotTimer = Time.time;
animator.SetTrigger ("attack");
//lambdas would be fantastic here!
StartCoroutine (ShootSnowballAfter (0.3f));
}
} else if (newBehaviour == Behaviour.ATTACK) {
newBehaviour = Behaviour.IDLE;
}
//set the result
behaviour = newBehaviour;
}
IEnumerator ShootSnowballAfter(float delay) {
yield return new WaitForSeconds(delay);
//create and set the snowball
GameObject go = Instantiate (snowballPrefab);
Rigidbody2D rb = go.GetComponent<Rigidbody2D> ();
rb.position = rigidBody.position + lastDirection.normalized * shotSpawnDistance;
Vector3 direction = player.transform.position - new Vector3 (rb.position.x, rb.position.y, 0);
rb.velocity = direction.normalized * 0.4f;
}
void SendAnimationInfo() {
if (deltaForce != Vector2.zero) {
lastDirection = deltaForce.normalized;
}
animator.SetFloat ("lastXSpeed", lastDirection.x);
animator.SetFloat ("lastYSpeed", lastDirection.y);
animator.SetBool ("moving", deltaForce != Vector2.zero);
}
void HandleMove() {
//determine how to move the character
rigidBody.velocity = Vector2.zero;
Vector2 impulse = deltaForce.normalized * speed;
rigidBody.AddForce (impulse, ForceMode2D.Impulse);
}
Vector3 Rotate(Vector3 normalisedDirection, float angle) {
return Quaternion.AngleAxis(angle, Vector3.forward) * normalisedDirection;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment