diff --git a/Assets/Scripts/GameAssembly.asmdef b/Assets/Scripts/GameAssembly.asmdef new file mode 100644 index 0000000..48d70d7 --- /dev/null +++ b/Assets/Scripts/GameAssembly.asmdef @@ -0,0 +1,3 @@ +{ + "name": "GameAssembly" +} diff --git a/Assets/Scripts/GameAssembly.asmdef.meta b/Assets/Scripts/GameAssembly.asmdef.meta new file mode 100644 index 0000000..13d0a8c --- /dev/null +++ b/Assets/Scripts/GameAssembly.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 6ee199c72d6db6244ac382d3d4d61bfc +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/LevelManager.meta b/Assets/Scripts/LevelManager.meta new file mode 100644 index 0000000..54e35be --- /dev/null +++ b/Assets/Scripts/LevelManager.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6de7614753584724c88bf88102975375 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/LevelManager/ILevelObject.cs b/Assets/Scripts/LevelManager/ILevelObject.cs new file mode 100644 index 0000000..13874ff --- /dev/null +++ b/Assets/Scripts/LevelManager/ILevelObject.cs @@ -0,0 +1,3 @@ +public interface ILevelObject +{ +} \ No newline at end of file diff --git a/Assets/Scripts/LevelManager/ILevelObject.cs.meta b/Assets/Scripts/LevelManager/ILevelObject.cs.meta new file mode 100644 index 0000000..1a63bc1 --- /dev/null +++ b/Assets/Scripts/LevelManager/ILevelObject.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e8c55ebc87e041b419aa13dffc17b91f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/LevelManager/LevelManager.cs b/Assets/Scripts/LevelManager/LevelManager.cs new file mode 100644 index 0000000..6e0001c --- /dev/null +++ b/Assets/Scripts/LevelManager/LevelManager.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; + +public class LevelManager : Singleton +{ + public event System.Action Added; + public event System.Action Removed; + + private List levelObjects; + public LevelManager() + { + levelObjects = new List(); + } + + public void Add(ILevelObject levelObject) + { + if (levelObjects.Contains(levelObject)) return; + levelObjects.Add(levelObject); + Added?.Invoke(levelObject); + } + public void Remove(ILevelObject levelObject) + { + if (!levelObjects.Contains(levelObject)) return; + levelObjects.Remove(levelObject); + Removed?.Invoke(levelObject); + } + public void Clear() + { + levelObjects.RemoveAll(obj => + { + Removed?.Invoke(obj); + return true; + }); + } + public T Get(System.Func predicate = default) where T : ILevelObject + { + if (predicate == default) predicate = (t) => true; + return (T)levelObjects.Find(t => t is T t1 && predicate(t1)); + } + public List GetAll(System.Func predicate = default) where T : ILevelObject + { + if (predicate == default) predicate = (t) => true; + List ret = new List(); + foreach (var t in levelObjects) if (t is T t1 && predicate(t1)) ret.Add(t1); + return ret; + } + + public int Count(Func predicate = default) where T : ILevelObject + { + return GetAll(predicate).Count; + } + + public bool Has(System.Func predicate = default) + { + if (predicate == default) predicate = (t) => true; + return levelObjects.Exists(t => t is T && predicate((T)t)); + } +} \ No newline at end of file diff --git a/Assets/Scripts/LevelManager/LevelManager.cs.meta b/Assets/Scripts/LevelManager/LevelManager.cs.meta new file mode 100644 index 0000000..2a75210 --- /dev/null +++ b/Assets/Scripts/LevelManager/LevelManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1af43055ac165604e992f071c5520910 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Singleton.cs b/Assets/Scripts/Singleton.cs new file mode 100644 index 0000000..01d04da --- /dev/null +++ b/Assets/Scripts/Singleton.cs @@ -0,0 +1,16 @@ +/// +/// this class is not a MonoBehaviour. Its purpose is to make it possible to have global classes that will not be in the scene. +/// +/// +public class Singleton where T : Singleton, new() +{ + private static T _instance; + public static T Instance + { + get + { + if (_instance == null) _instance = new T(); + return _instance; + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Singleton.cs.meta b/Assets/Scripts/Singleton.cs.meta new file mode 100644 index 0000000..6a83a8a --- /dev/null +++ b/Assets/Scripts/Singleton.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7f3fd6219c44e484db1f5c351626bf3e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Tiles.meta b/Assets/Scripts/Tiles.meta new file mode 100644 index 0000000..403a246 --- /dev/null +++ b/Assets/Scripts/Tiles.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a9710b36b8754824f8f0cc22dc85ed59 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Tiles/ResourceTile.cs b/Assets/Scripts/Tiles/ResourceTile.cs new file mode 100644 index 0000000..184c050 --- /dev/null +++ b/Assets/Scripts/Tiles/ResourceTile.cs @@ -0,0 +1,34 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Tilemaps; + + +[CreateAssetMenu(menuName = "Gather And Defend/Resource Tile")] +public class ResourceTile : TileBase, ILevelObject +{ + [SerializeField] + [Tooltip("the prefab of the currency that will be spawned when mining this resource")] + private GameObject _yieldPrefab; + [SerializeField] + private Sprite _sprite; + public Vector3 Position { get; private set; } + + public Sprite Sprite { get => _sprite; set => _sprite = value; } + public override bool StartUp(Vector3Int position, ITilemap tilemap, GameObject go) + { + if (!Application.isPlaying) return base.StartUp(position, tilemap, go); + + //need to create an instance of the tile, otherwise the position will change for all tiles instead of only this one. + var instance = Instantiate(this); + instance.Position = position; + LevelManager.Instance.Add(instance); + return base.StartUp(position, tilemap, go); + } + public override void GetTileData(Vector3Int position, ITilemap tilemap, ref TileData tileData) + { + tileData.sprite = _sprite; + tileData.transform.SetTRS(Vector3.zero, Quaternion.identity, Vector3.one); + tileData.color = Color.white; + } +} \ No newline at end of file diff --git a/Assets/Scripts/Tiles/ResourceTile.cs.meta b/Assets/Scripts/Tiles/ResourceTile.cs.meta new file mode 100644 index 0000000..704714e --- /dev/null +++ b/Assets/Scripts/Tiles/ResourceTile.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 84b05f2a26f63da46a1028488482d079 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Tests.meta b/Assets/Tests.meta new file mode 100644 index 0000000..2f07245 --- /dev/null +++ b/Assets/Tests.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fc8abee0ea7bd1a47b2fcce297d01648 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Tests/Playmode.meta b/Assets/Tests/Playmode.meta new file mode 100644 index 0000000..904119f --- /dev/null +++ b/Assets/Tests/Playmode.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 48410eca65be77149bf834b1df6f55f5 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Tests/Playmode/Playmode.asmdef b/Assets/Tests/Playmode/Playmode.asmdef new file mode 100644 index 0000000..9e10228 --- /dev/null +++ b/Assets/Tests/Playmode/Playmode.asmdef @@ -0,0 +1,22 @@ +{ + "name": "Tests", + "rootNamespace": "", + "references": [ + "UnityEngine.TestRunner", + "UnityEditor.TestRunner", + "GameAssembly" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": true, + "precompiledReferences": [ + "nunit.framework.dll" + ], + "autoReferenced": false, + "defineConstraints": [ + "UNITY_INCLUDE_TESTS" + ], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Assets/Tests/Playmode/Playmode.asmdef.meta b/Assets/Tests/Playmode/Playmode.asmdef.meta new file mode 100644 index 0000000..6ab6141 --- /dev/null +++ b/Assets/Tests/Playmode/Playmode.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 35cea9d83a6dea3488659da5d3f262a9 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Tests/Playmode/TestLevelManager.cs b/Assets/Tests/Playmode/TestLevelManager.cs new file mode 100644 index 0000000..655d1f2 --- /dev/null +++ b/Assets/Tests/Playmode/TestLevelManager.cs @@ -0,0 +1,56 @@ +using System.Collections; +using System.Collections.Generic; +using NUnit.Framework; +using UnityEngine; +using UnityEngine.TestTools; +using UnityEngine.Tilemaps; + +public class TestLevelManager +{ + private ResourceTile _farm; + private Tilemap _tilemap; + const int size = 25; + const int sqrt_size = 5; + + private YieldInstruction Timing => new WaitForSeconds(0.1f); + [SetUp] + public void SetUp() + { + _farm = ScriptableObject.CreateInstance(); + _farm.name = nameof(_farm); + + _tilemap = new GameObject("Tilemap").AddComponent(); + for (int i = 0; i < size; i++) + { + var pos = new Vector3Int(i % sqrt_size, i / sqrt_size); + _tilemap.SetTile(pos, _farm); + } + } + [TearDown] + public void TearDown() + { + Object.Destroy(_tilemap.gameObject); + } + + // A UnityTest behaves like a coroutine in Play Mode. In Edit Mode you can use + // `yield return null;` to skip a frame. + [UnityTest] + public IEnumerator TestLevelManagerWithEnumeratorPasses() + { + yield return Timing; + Assert.AreEqual(size, LevelManager.Instance.Count(), "there should be " + size + " tiles"); + for (int i = 0; i < 25; i++) + { + var pos = new Vector3(i % sqrt_size, i / sqrt_size); + var tileExists = LevelManager.Instance.Has(t => Mathf.Approximately(Vector2.Distance(pos, t.Position), 0)); + Assert.True(tileExists, "there should be a tile at position " + pos); + } + + var newPos = new Vector3Int(-5, -5); + _tilemap.SetTile(newPos, _farm); + yield return Timing; + + var newTileExists = LevelManager.Instance.Has(t => Mathf.Approximately(Vector3.Distance(t.Position, newPos), 0)); + Assert.True(newTileExists, "new tile wasn't added to level manager"); + } +} diff --git a/Assets/Tests/Playmode/TestLevelManager.cs.meta b/Assets/Tests/Playmode/TestLevelManager.cs.meta new file mode 100644 index 0000000..6de040c --- /dev/null +++ b/Assets/Tests/Playmode/TestLevelManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c8b5cb265fff43142b83e2584ba2620e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/ProjectSettings/ProjectSettings.asset b/ProjectSettings/ProjectSettings.asset index afd8da9..7b42db3 100644 --- a/ProjectSettings/ProjectSettings.asset +++ b/ProjectSettings/ProjectSettings.asset @@ -76,7 +76,7 @@ PlayerSettings: androidFullscreenMode: 1 defaultIsNativeResolution: 1 macRetinaSupport: 1 - runInBackground: 0 + runInBackground: 1 captureSingleScreen: 0 muteOtherAudioSources: 0 Prepare IOS For Recording: 0