Soren Rogiers

Game developer

Judgment


Judgment is a top down battle arena where you play the character of a priest. God and Satan are having a quarrel which means bad news for the guys on earth.
Your hero’s adventure starts in his own church which is transformed into a maze-like stage, infested with the devil’s spawns. Luckily your lord and savior God has granted you access to some superhumanly powers. Defend your church, exterminate all of Satan’s followers to show him which deity is the real Almighty!

I was responsible for the following:
  • Enemy AI
  • Different types of enemies
  • Shaders, when the enemies or players are behind objects or walls I made sure they were still visible to our camera
  • Player feedback: Indicators on important objects or enemies
  • Mini tutorial design
  • Particle effects

Read more about our struggles and progress during development.

Trailer


Code snippets


									
//********************************************************
//IDamageAble Interface
//General interface which is used by entity
//Entities can take hits - take damage - knockback and die
//********************************************************
using UnityEngine;
public interface IDamageable
{
    void TakeHit(float damage);
    void TakeDamage(float damage);
    void Knockback(Vector3 direction, float force);
    void Die();
}

//*****************************************
//EnemyAI script
//Inherits from Entity
//Controls the basic things of the enemy
//Enemy states - Drop items - Assign target
//*****************************************
using System.Collections;
using System.Collections.Generic;
using System.Linq.Expressions;
using UnityEngine;
using UnityEngine.AI;

public class EnemyAI : Entity {

    //PUBLIC
    //******
    public enum State { CHASING, ATTACKING, DYING }
    [HideInInspector] public Transform Target;

    //PRIVATE
    //*******
    private State _currentState;
    private EnemyFieldOfView _fov;
    private DropEssence _dropEssence;
    private PathBehaviour _pathBehaviour;

    public override void Start()
    {
        base.Start();
        CurrentState = State.CHASING;
       
        //Path
        _pathBehaviour = GetComponent();

        //Enemy field of view
        _fov = GetComponent();
        _fov.Target = Target;
        StartCoroutine(_fov.FindTargetsWithDelay(0.1f));

        //Drop essence when dead
        _dropEssence = GetComponent();

        //Assign target
        Target = _pathBehaviour.CurrentTarget;
    }

    public override void Update()
    {
        base.Update();
        DetermineState();

        if (IsDead)
        {
            _dropEssence.SpawnEssence();
            _dropEssence.SpawnHealthOrbs();
        }
    }

    //Determinstate
    //Params: void
    //Description: Assigns a target, if our target is in our fov we attack else we chase
    //return: void
    public void DetermineState()
    {
        Target = _pathBehaviour.CurrentTarget;
        
        if (_fov != null)
        {
            if (_fov.IsTargetInFov && _fov.VisibleTarget == Target)
            {
                _currentState = State.ATTACKING;
                Vector3 newTarget = new Vector3(Target.position.x, transform.position.y, Target.position.z);
                this.transform.LookAt(newTarget);
                _pathBehaviour.NavMeshAgent.isStopped = true;
            }
            else
            {
                _currentState = State.CHASING;
                _pathBehaviour.NavMeshAgent.isStopped = false;
            }
        }
    }

    public State CurrentState
    {
        get { return _currentState; }
        set { _currentState = value; }
    }
}

//***************************************
//EnemyFieldOfView script
//Creates a field of view for our enemies
//Can filter layers 
//***************************************
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EnemyFieldOfView : MonoBehaviour
{
    //PUBLIC
    //******
    [Header("FOV Radius & Angle")]
    public float ViewRadius;
    [Range(0, 360)] public float ViewAngle;

    [Header("Layermask to filter")]
    public LayerMask TargetMask;
    public LayerMask ObstaclesMask;

    [HideInInspector] public bool IsTargetInFov;
    [HideInInspector] public Transform Target;
    [HideInInspector] public Transform VisibleTarget;

    //Find target with delay
    //Param: float
    //Description: find targets every x amount of delay to not stress our performance to much
    //Return: IEnumerator 
    public IEnumerator FindTargetsWithDelay(float delay)
    {
        while (true)
        {
            yield return new WaitForSeconds(delay);
            FindVisibleTargets();
        }
    }
    //Find target Visible targets
    //Param: void
    //Description: Cast a sphere and check what we hit in our angle and range if we see the player we assign a target
    //Return: void 
    void FindVisibleTargets()
    {
        IsTargetInFov = false;
        Collider[] targetsInViewRadius = Physics.OverlapSphere(transform.position, ViewRadius, TargetMask);

        for (int i = 0; i < targetsInViewRadius.Length; i++)
        {
            Target = targetsInViewRadius[i].transform;
            Vector3 dirToTarget = (Target.position - transform.position).normalized;

            if (Vector3.Angle(transform.forward, dirToTarget) < ViewAngle / 2)
            {
                float distToTarget = Vector3.Distance(transform.position, Target.position);

                if (!Physics.Raycast(transform.position, dirToTarget, distToTarget, ObstaclesMask))
                {
                    IsTargetInFov = true;
                    VisibleTarget = Target;
                }
            }
        }
    }
    //Random Point in circle
    //Param: Transform
    //Description: Find a random point in a circle around a given target
    //Return: vector3 
    public Vector3 RandomPointInCircle(Transform aroundTarget)
    {
        Vector3 position = Vector3.zero;

        float offsetX = 0;
        float offsetZ = 0;

        while (!(offsetX > 1.0f || offsetX < -1.0f) && !(offsetZ > 1.0f || offsetZ < -1.0f))
        {
            offsetX = Random.Range(-3.0f, 3.0f);
            offsetZ = Random.Range(-3.0f, 3.0f);
        }
        position = new Vector3(aroundTarget.transform.position.x + offsetX, 0, aroundTarget.transform.position.z + offsetZ);

        return position;
    }

    //DirectionFromAngle
    //Param: float - bool
    //Description: Create a direction from a given angle
    //Return: vector3 
    public Vector3 DirectionFromAngle(float angleInDegrees, bool angleIsGlobal)
    {
        if (!angleIsGlobal)
        {
            angleInDegrees += transform.eulerAngles.y;
        }
        return new Vector3(Mathf.Sin(angleInDegrees * Mathf.Deg2Rad), 0, Mathf.Cos(angleInDegrees * Mathf.Deg2Rad));
    }
}
								
							

Screenshots


Go back