2D Roguelike

This game is about surviving as many days as possible by picking up food, soda and not getting hit by the zombies and making it to the exit to start another day.
It’s a top down game with a food and soda counter that will add points if you pick up food and soda and will deplete if you move or get hit by a zombie.
There are also breakable walls who you can destroy to create new paths. The first couple moves you won’t activate the zombies, but after a couple rounds they will start moving every 2 moves you make.
As the days pass the levels will get harder by adding more walls and zombies, also after a couple days a new zombie will spawn that does double the damage of the normal zombie.

2DRogueLike Unity

2DRogueLike ingame

BoardManager.cs

using UnityEngine; using System; using System.Collections.Generic; using Random = UnityEngine.Random; public class BoardManager : MonoBehaviour { [Serializable] public class Count { public int minimum; public int maximum; public Count(int min, int max) { minimum = min; maximum = max; } } public int columns = 8; public int rows = 8; public Count wallCount = new Count(5, 9); public Count foodCount = new Count(1, 5); public GameObject exit; public GameObject[] floorTiles; public GameObject[] wallTiles; public GameObject[] foodTiles; public GameObject[] enemyTiles; public GameObject[] outerWallTiles; private Transform boardHolder; private List gridPositions = new List(); void InitialiseList() { gridPositions.Clear(); for (int x = 1; x < columns - 1; x++) { for (int y = 1; y < rows - 1; y++) { gridPositions.Add(new Vector3(x, y, 0f)); } } } void BoardSetup() { boardHolder = new GameObject("Board").transform; for (int x = -1; x < columns + 1; x++) { for (int y = -1; y < rows + 1; y++) { GameObject toInstantiate = floorTiles[Random.Range(0, floorTiles.Length)]; if (x == -1 || x == columns || y == -1 || y == rows) toInstantiate = outerWallTiles[Random.Range(0, outerWallTiles.Length)]; GameObject instance = Instantiate(toInstantiate, new Vector3(x, y, 0f), Quaternion.identity) as GameObject; instance.transform.SetParent(boardHolder); } } } Vector3 RandomPosition() { int randomIndex = Random.Range(0, gridPositions.Count); Vector3 randomPosition = gridPositions[randomIndex]; gridPositions.RemoveAt(randomIndex); return randomPosition; } void LayoutObjectAtRandom(GameObject[] tileArray, int minimum, int maximum) { int objectCount = Random.Range(minimum, maximum + 1); for (int i = 0; i < objectCount; i++) { Vector3 randomPosition = RandomPosition(); GameObject tileChoice = tileArray[Random.Range(0, tileArray.Length)]; Instantiate(tileChoice, randomPosition, Quaternion.identity); } } public void SetupScene(int level) { BoardSetup(); InitialiseList(); LayoutObjectAtRandom(wallTiles, wallCount.minimum, wallCount.maximum); LayoutObjectAtRandom(foodTiles, foodCount.minimum, foodCount.maximum); int enemyCount = (int)Mathf.Log(level, 2f); LayoutObjectAtRandom(enemyTiles, enemyCount, enemyCount); Instantiate(exit, new Vector3(columns - 1, rows - 1, 0f), Quaternion.identity); } }
Enemy.cs using UnityEngine; using System.Collections; public class Enemy : MovingObject { public int playerDamage; public AudioClip enemyAttack1; public AudioClip enemyAttack2; private Animator animator; private Transform target; private bool skipMove; protected override void Start() { GameManager.instance.AddEnemyToList(this); animator = GetComponent(); target = GameObject.FindGameObjectWithTag("Player").transform; base.Start(); } protected override void AttemptMove(int xDir, int yDir) { if (skipMove) { skipMove = false; return; } base.AttemptMove(xDir, yDir); skipMove = true; } public void MoveEnemy() { int xDir = 0; int yDir = 0; if (Mathf.Abs(target.position.x - transform.position.x) < float.Epsilon) yDir = target.position.y > transform.position.y ? 1 : -1; else xDir = target.position.x > transform.position.x ? 1 : -1; AttemptMove(xDir, yDir); } protected override void OnCantMove(T component) { Player hitPlayer = component as Player; hitPlayer.LoseFood(playerDamage); animator.SetTrigger("enemyAttack"); SoundManager.instance.RandomizeSfx(enemyAttack1,enemyAttack2); } }

GameManager.cs
using UnityEngine; using System.Collections; using System.Collections.Generic; using UnityEngine.UI; public class GameManager : MonoBehaviour { public float levelStartDelay = 2f; public float turnDelay = .1f; public static GameManager instance = null; public BoardManager boardScript; public int playerFoodPoints = 100; [HideInInspector] public bool playersTurn = true; private Text levelText; private GameObject levelImage; private int level = 1; private List enemies; private bool enemiesMoving; private bool doingSetup; void Awake() { if (instance == null) instance = this; else if (instance != this) Destroy(gameObject); DontDestroyOnLoad(gameObject); enemies = new List(); boardScript = GetComponent(); InitGame(); } private void OnLevelWasLoaded (int index) { level++; InitGame(); } void InitGame() { doingSetup = true; levelImage = GameObject.Find("LevelImage"); levelText = GameObject.Find("LevelText").GetComponent(); levelText.text = "Day " + level; levelImage.SetActive(true); Invoke("HideLevelImage", levelStartDelay); enemies.Clear(); boardScript.SetupScene(level); } private void HideLevelImage() { levelImage.SetActive(false); doingSetup = false; } public void GameOver() { levelText.text = "After " + level + " days, you starved."; levelImage.SetActive(true); enabled = false; } void Update() { if (playersTurn || enemiesMoving || doingSetup) return; StartCoroutine(MoveEnemies()); } public void AddEnemyToList(Enemy script) { enemies.Add(script); } IEnumerator MoveEnemies() { enemiesMoving = true; yield return new WaitForSeconds(turnDelay); if (enemies.Count == 0) { yield return new WaitForSeconds(turnDelay); } for (int i = 0; i < enemies.Count; i++) { enemies[i].MoveEnemy(); yield return new WaitForSeconds(enemies[i].moveTime); } playersTurn = true; enemiesMoving = false; } }

Loader.cs
using UnityEngine; using System.Collections; public class Loader : MonoBehaviour { public GameObject gameManager; void Awake() { if (GameManager.instance == null) Instantiate(gameManager); } }
MovingObject.cs
using UnityEngine; using System.Collections; public abstract class MovingObject : MonoBehaviour { public float moveTime = 0.1f; public LayerMask blockingLayer; private BoxCollider2D boxCollider; private Rigidbody2D rb2D; private float inverseMoveTime; protected virtual void Start() { boxCollider = GetComponent(); rb2D = GetComponent(); inverseMoveTime = 1f / moveTime; } protected bool Move(int xDir, int yDir, out RaycastHit2D hit) { Vector2 start = transform.position; Vector2 end = start + new Vector2(xDir, yDir); boxCollider.enabled = false; hit = Physics2D.Linecast(start, end, blockingLayer); boxCollider.enabled = true; if (hit.transform == null) { StartCoroutine(SmoothMovement(end)); return true; } return false; } protected IEnumerator SmoothMovement(Vector3 end) { float sqrRemainingDistance = (transform.position - end).sqrMagnitude; while (sqrRemainingDistance > float.Epsilon) { Vector3 newPostion = Vector3.MoveTowards(rb2D.position, end, inverseMoveTime * Time.deltaTime); rb2D.MovePosition(newPostion); sqrRemainingDistance = (transform.position - end).sqrMagnitude; yield return null; } } protected virtual void AttemptMove(int xDir, int yDir) where T : Component { RaycastHit2D hit; bool canMove = Move(xDir, yDir, out hit); if (hit.transform == null) return; T hitComponent = hit.transform.GetComponent(); if (!canMove && hitComponent != null) OnCantMove(hitComponent); } protected abstract void OnCantMove(T component) where T : Component; }

Player.cs
using UnityEngine; using System.Collections; using UnityEngine.UI; public class Player : MovingObject { public float restartLevelDelay = 1f; public int pointsPerFood = 10; public int pointsPerSoda = 20; public int wallDamage = 1; public Text foodText; public AudioClip moveSound1; public AudioClip moveSound2; public AudioClip eatSound1; public AudioClip eatSound2; public AudioClip drinkSound1; public AudioClip drinkSound2; public AudioClip gameOverSound; private Animator animator; private int food; private Vector2 touchOrigin = -Vector2.one; protected override void Start() { animator = GetComponent(); food = GameManager.instance.playerFoodPoints; foodText.text = "Food: " + food; base.Start(); } private void OnDisable() { GameManager.instance.playerFoodPoints = food; } private void Update() { if (!GameManager.instance.playersTurn) return; int horizontal = 0; int vertical = 0; #if UNITY_STANDALONE || UNITY_WEBPLAYER horizontal = (int)(Input.GetAxisRaw("Horizontal")); vertical = (int)(Input.GetAxisRaw("Vertical")); if (horizontal != 0) { vertical = 0; } #else if (Input.touchCount > 0) { Touch myTouch = Input.touches[0]; if (myTouch.phase == TouchPhase.Began) { touchOrigin = myTouch.position; } else if (myTouch.phase == TouchPhase.Ended && touchOrigin.x >= 0) { Vector2 touchEnd = myTouch.position; float x = touchEnd.x - touchOrigin.x; float y = touchEnd.y - touchOrigin.y; touchOrigin.x = -1; if (Mathf.Abs(x) > Mathf.Abs(y)) horizontal = x > 0 ? 1 : -1; else vertical = y > 0 ? 1 : -1; } } #endif if (horizontal != 0 || vertical != 0) { AttemptMove(horizontal, vertical); } } protected override void AttemptMove(int xDir, int yDir) { food--; foodText.text = "Food: " + food; base.AttemptMove(xDir, yDir); RaycastHit2D hit; if (Move(xDir, yDir, out hit)) { SoundManager.instance.RandomizeSfx(moveSound1, moveSound2); } CheckIfGameOver(); GameManager.instance.playersTurn = false; } protected override void OnCantMove(T component) { Wall hitWall = component as Wall; hitWall.DamageWall(wallDamage); animator.SetTrigger("playerChop"); } private void OnTriggerEnter2D(Collider2D other) { if (other.tag == "Exit") { Invoke("Restart", restartLevelDelay); enabled = false; } else if (other.tag == "Food") { food += pointsPerFood; foodText.text = "+" + pointsPerFood + "Food: " + food; SoundManager.instance.RandomizeSfx(eatSound1, eatSound2); other.gameObject.SetActive(false); } else if (other.tag == "Soda") { food += pointsPerSoda; foodText.text = "+" + pointsPerSoda + "Food: " + food; SoundManager.instance.RandomizeSfx(drinkSound1, drinkSound2); other.gameObject.SetActive(false); } } private void Restart() { Application.LoadLevel(Application.loadedLevel); } public void LoseFood(int loss) { animator.SetTrigger("playerHit"); food -= loss; foodText.text = "-" + loss + "Food: " + food; CheckIfGameOver(); } private void CheckIfGameOver() { if (food <= 0) { SoundManager.instance.PlaySingle(gameOverSound); SoundManager.instance.musicSource.Stop(); GameManager.instance.GameOver(); Destroy(gameObject); } } }

SoundManager.cs
using UnityEngine; using System.Collections; public class SoundManager : MonoBehaviour { public AudioSource efxSource; public AudioSource musicSource; public static SoundManager instance = null; public float lowPitchRange = 0.95f; public float highPitchRange = 1.05f; // Use this for initialization void Awake () { if (instance == null) instance = this; else if (instance != this) Destroy(gameObject); DontDestroyOnLoad(gameObject); } public void PlaySingle (AudioClip clip) { efxSource.clip = clip; efxSource.Play(); } public void RandomizeSfx(params AudioClip[] clips) { int randomIndex = Random.Range(0, clips.Length); float randomPitch = Random.Range(lowPitchRange, highPitchRange); efxSource.pitch = randomPitch; efxSource.clip = clips[randomIndex]; efxSource.Play(); } }

Wall.cs
using UnityEngine; using System.Collections; public class Wall : MonoBehaviour { public Sprite dmgSprite; public int hp = 4; public AudioClip chopSound1; public AudioClip chopSound2; private SpriteRenderer spriteRenderer; void Awake() { spriteRenderer = GetComponent(); } public void DamageWall(int loss) { SoundManager.instance.RandomizeSfx(chopSound1, chopSound2); spriteRenderer.sprite = dmgSprite; hp -= loss; if (hp <= 0) gameObject.SetActive(false); } }