public void TestMove() { var itemsAdded = new List <MySpatialMapItem>(); var sm = new LayeredSpatialMap <MySpatialMapItem>(5); for (int i = 0; i < 5; i++) { var item = new MySpatialMapItem(i); itemsAdded.Add(item); sm.Add(item, (1, 2)); } var lastItem = new MySpatialMapItem(3); itemsAdded.Add(lastItem); sm.Add(lastItem, (5, 6)); bool result = sm.Move(lastItem, 1, 2); Assert.AreEqual(false, result); // Blocked by first 5 adds and they no layers support multiple items result = sm.Move(lastItem, (2, 3)); // At 2, 3 we now have item on layer 3 Assert.AreEqual(true, result); List <MySpatialMapItem> itemsMoved = sm.Move((1, 2), (2, 3)).ToList(); Assert.AreEqual(4, itemsMoved.Count); // All original items minus 1 because that one was blocked itemsMoved = sm.Move((2, 3), (1, 2), ~sm.LayerMasker.Mask(2)).ToList(); Assert.AreEqual(3, itemsMoved.Count); // lastItem from above masked out by layer sm = new LayeredSpatialMap <MySpatialMapItem>(5, 1); for (int i = 0; i < itemsAdded.Count - 1; i++) // All but that last item so we add at diff pos { sm.Add(itemsAdded[i], (1, 2)); } sm.Add(lastItem, (2, 3)); // We should have added all but the one that was layer 0 itemsMoved = sm.Move(1, 2, 2, 3).ToList(); Assert.AreEqual(3, itemsMoved.Count); itemsMoved = sm.Move(2, 3, 1, 2, ~sm.LayerMasker.Mask(2)).ToList(); Assert.AreEqual(2, itemsMoved.Count); List <MySpatialMapItem> itemsLeft = sm.GetItems((2, 3)).ToList(); Assert.AreEqual(2, itemsLeft.Count); bool found = false; foreach (var item in itemsLeft) { found = found || item == itemsAdded[2]; } Assert.AreEqual(true, found); }
public void ManualTestPrint() { var map = new LayeredSpatialMap <MySpatialMapItem>(3, 1, LayerMasker.DEFAULT.Mask(2)); map.Add(new MySpatialMapItem(1), (1, 2)); map.Add(new MySpatialMapItem(1), (3, 4)); map.Add(new MySpatialMapItem(2), (1, 1)); map.Add(new MySpatialMapItem(3), (0, 0)); Console.WriteLine("SpatialMap: "); Console.WriteLine(map); Console.WriteLine("No need to test stringifier, as used by impl of regular ToString()"); }
public void TestAdd() { var sm = new LayeredSpatialMap <MySpatialMapItem>(5); bool result; for (int i = 0; i < 5; i++) { var item = new MySpatialMapItem(i); result = sm.Add(item, (1, 2)); Assert.AreEqual(true, result); } result = sm.Add(new MySpatialMapItem(5), (2, 3)); // Out of range layer Assert.AreEqual(false, result); sm = new LayeredSpatialMap <MySpatialMapItem>(5, 1); result = sm.Add(new MySpatialMapItem(0), (5, 6)); Assert.AreEqual(false, result); }
public void TestRemove() { var itemsAdded = new List <MySpatialMapItem>(); var sm = new LayeredSpatialMap <MySpatialMapItem>(5); for (int i = 0; i < 5; i++) { var item = new MySpatialMapItem(i); itemsAdded.Add(item); sm.Add(item, (1, 2)); } bool result; var nonAddedItem = new MySpatialMapItem(2); result = sm.Remove(nonAddedItem); Assert.AreEqual(false, result); foreach (var i in itemsAdded) { result = sm.Remove(i); Assert.AreEqual(true, result); } foreach (var i in itemsAdded) { sm.Add(i, (1, 2)); } List <MySpatialMapItem> itemsRemoved = sm.Remove((5, 6)).ToList(); Assert.AreEqual(0, itemsRemoved.Count); itemsRemoved = sm.Remove((1, 2)).ToList(); Assert.AreEqual(itemsAdded.Count, itemsRemoved.Count); }
/// <summary> /// Constructor. Constructs map with the given terrain layer, determining width/height based on the width/height of that terrain layer. /// </summary> /// <remarks> /// Because of the way polymorphism works for custom classes in C#, the <paramref name="terrainLayer"/> parameter MUST be of type /// <see cref="ISettableMapView{IGameObject}"/>, rather than <see cref="ISettableMapView{T}"/> where T is a type that derives from or implements /// <see cref="IGameObject"/>. If you need to use a map view storing type T rather than IGameObject, use the /// <see cref="CreateMap{T}(ISettableMapView{T}, int, Distance, uint, uint, uint)"/> function to create the map. /// </remarks> /// <param name="terrainLayer">The <see cref="ISettableMapView{IGameObject}"/> that represents the terrain layer for this map. After the /// map has been created, you should use the <see cref="SetTerrain(IGameObject)"/> function to modify the values in this map view, rather /// than setting the values via the map view itself -- if you re-assign the value at a location via the map view, the /// <see cref="ObjectAdded"/>/<see cref="ObjectRemoved"/> events are NOT guaranteed to be called, and many invariants of map may not be properly /// enforced.</param> /// <param name="numberOfEntityLayers">Number of non-terrain layers for the map.</param> /// <param name="distanceMeasurement"><see cref="Distance"/> measurement to use for pathing/measuring distance on the map.</param> /// <param name="layersBlockingWalkability">Layer mask containing those layers that should be allowed to have items that block walkability. /// Defaults to all layers.</param> /// <param name="layersBlockingTransparency">Layer mask containing those layers that should be allowed to have items that block FOV. /// Defaults to all layers.</param> /// <param name="entityLayersSupportingMultipleItems">Layer mask containing those layers that should be allowed to have multiple objects at the same /// location on the same layer. Defaults to no layers.</param> public Map(ISettableMapView <IGameObject> terrainLayer, int numberOfEntityLayers, Distance distanceMeasurement, uint layersBlockingWalkability = uint.MaxValue, uint layersBlockingTransparency = uint.MaxValue, uint entityLayersSupportingMultipleItems = 0) { _terrain = terrainLayer; Explored = new ArrayMap <bool>(_terrain.Width, _terrain.Height); _entities = new LayeredSpatialMap <IGameObject>(numberOfEntityLayers, 1, entityLayersSupportingMultipleItems); LayersBlockingWalkability = layersBlockingWalkability; LayersBlockingTransparency = layersBlockingTransparency; _entities.ItemAdded += (s, e) => ObjectAdded?.Invoke(this, e); _entities.ItemRemoved += (s, e) => ObjectRemoved?.Invoke(this, e); _entities.ItemMoved += (s, e) => ObjectMoved?.Invoke(this, e); if (layersBlockingTransparency == 1) // Only terrain so we optimize { TransparencyView = new LambdaMapView <bool>(_terrain.Width, _terrain.Height, c => _terrain[c] == null || _terrain[c].IsTransparent); } else { TransparencyView = new LambdaMapView <bool>(_terrain.Width, _terrain.Height, FullIsTransparent); } if (layersBlockingWalkability == 1) // Similar, only terrain blocks, so optimize { WalkabilityView = new LambdaMapView <bool>(_terrain.Width, _terrain.Height, c => _terrain[c] == null || _terrain[c].IsWalkable); } else { WalkabilityView = new LambdaMapView <bool>(_terrain.Width, _terrain.Height, FullIsWalkable); } _fov = new FOV(TransparencyView); AStar = new AStar(WalkabilityView, distanceMeasurement); }
public void TestConstruction() { // No multiple item layers, 32 layers, starting at 0 var sm = new LayeredSpatialMap <MySpatialMapItem>(32); Assert.AreEqual(32, sm.NumberOfLayers); Assert.AreEqual(0, sm.StartingLayer); foreach (var layer in sm.Layers) { Assert.AreEqual(true, layer is AdvancedSpatialMap <MySpatialMapItem>); } // Test multiple item layers uint multipleItemLayerMask = LayerMasker.DEFAULT.Mask(0, 2, 5); sm = new LayeredSpatialMap <MySpatialMapItem>(10, 0, multipleItemLayerMask); Assert.AreEqual(10, sm.NumberOfLayers); Assert.AreEqual(0, sm.StartingLayer); int layerNum = 0; foreach (var layer in sm.Layers) { Assert.AreEqual(LayerMasker.DEFAULT.HasLayer(multipleItemLayerMask, layerNum), layer is AdvancedMultiSpatialMap <MySpatialMapItem>); layerNum++; } // Test arbitrary starting layer (initial values) int startingLayer = 1; int numberOfLayers = 5; sm = new LayeredSpatialMap <MySpatialMapItem>(numberOfLayers, startingLayer); Assert.AreEqual(numberOfLayers, sm.NumberOfLayers); Assert.AreEqual(startingLayer, sm.StartingLayer); }
public Level(int mapWidth, int mapHeight, int numberOfLayers, uint LayersThatAreMulti) { MapWidth = mapWidth; MapHeight = mapHeight; entities = new LayeredSpatialMap <Entity>(numberOfLayers, 0, LayersThatAreMulti); }