def test_SpecifyThatVector2DCanDetermineIfOneVectorIsFacingAnother(self): pos = Vector2D(0, 0) v1 = Vector2D(0, 1) v2 = Vector2D(0, 10) fov = 0.5 self.assertTrue(Vector2D.IsSecondInFovOfFirst(pos, v1, v2, fov))
def test_SpecifyThatAVectorCanReflected(self): v = Vector2D(4, 5) n = Vector2D(1, 0) v.Reflect(n) self.assertAlmostEqual(-4, v.X, places=3) self.assertAlmostEqual(5, v.Y, places=3)
def IsTouching(self, entityPosition, entityRadius): entityBox = Box2D( Vector2D(entityPosition.X - entityRadius, entityPosition.Y - entityRadius), Vector2D(entityPosition.X + entityRadius, entityPosition.Y + entityRadius)) return entityBox.IsOverlappedWith(self._box)
def test_SpecifyThatARectangularRegionCanBeConstructed(self): rectangularRegion = TriggerRegionRectangle(topLeft=Vector2D(3, 4), bottomRight=Vector2D(9, 10)) self.assertEqual(3, rectangularRegion._box.Left, "Left") self.assertEqual(4, rectangularRegion._box.Top, "Top") self.assertEqual(9, rectangularRegion._box.Right, "Right") self.assertEqual(10, rectangularRegion._box.Bottom, "Bottom")
def test_SpecifyThatACircularRegionCanDetermineIfAnEntityIsTouching(self): circularRegion = TriggerRegionCircle(position=Vector2D(10, 10), radius=5) self.assertTrue( circularRegion.IsTouching(entityPosition=Vector2D(7, 7), entityRadius=2)) self.assertFalse( circularRegion.IsTouching(entityPosition=Vector2D(1, 1), entityRadius=2))
def test_SpecifyThatAVectorCanBeComparedForEquality(self): v1 = Vector2D(1, 3) v2 = Vector2D(1, 3) v3 = Vector2D(2, 4) print(v1 == v2) self.assertTrue(v1 == v2) self.assertTrue(v1 == v1) self.assertTrue(v1 != v3)
def test_SpecifyThatGraphNodeNavCanBeModified(self): graphNode = GraphNodeNav(index=10, position=Vector2D(20, 30)) graphNode.Index = 40 graphNode.Position = Vector2D(50, 60) graphNode.ExtraInfo = "Extra Node Info" self.assertEqual(40, graphNode.Index, "Index") self.assertEqual(50, graphNode.Position.X, "Position.X") self.assertEqual(60, graphNode.Position.Y, "Position.Y") self.assertEqual("Extra Node Info", graphNode.ExtraInfo, "ExtraInfo")
def test_SpecifyThatARectangularRegionCanDetermineIfAnEntityIsTouching( self): rectangularRegion = TriggerRegionRectangle(topLeft=Vector2D(3, 4), bottomRight=Vector2D(9, 10)) self.assertTrue( rectangularRegion.IsTouching(entityPosition=Vector2D(7, 7), entityRadius=2)) self.assertFalse( rectangularRegion.IsTouching(entityPosition=Vector2D(1, 1), entityRadius=2))
def test_SpecifyThatABox2DCanBeConstructed(self): box = Box2D(Vector2D(1, 2), Vector2D(8, 9)) self.assertEqual(1, box.TopLeft.X, "TopLeft.X") self.assertEqual(2, box.TopLeft.Y, "TopLeft.Y") self.assertEqual(8, box.BottomRight.X, "BottomRight.X") self.assertEqual(9, box.BottomRight.Y, "BottomRight.Y") self.assertEqual(4.5, box.Center.X, "Center.X") self.assertEqual(5.5, box.Center.Y, "Center.Y") self.assertEqual(2, box.Top, "Top") self.assertEqual(1, box.Left, "Left") self.assertEqual(9, box.Bottom, "Bottom") self.assertEqual(8, box.Right, "Right")
def CalculateAverageGraphEdgeLength(graph): """ Determines the average length of the edges in a navGraph (using the distance between the source & target node positions (not the cost of the edge as represented in the graph, which may account for all sorts of other factors such as terrain type, gradients etc) :param graph: :return: """ totalLength = 0 numberOfEdgesCounted = 0 for node in graph.Nodes: if node.Index != -1: for edge in graph.GetNodeEdges(node.Index): # Increment edge counter numberOfEdgesCounted += 1 # Add length of edge to total length totalLength += Vector2D.Vec2DDistance( graph.GetNode(edge.From).Position, graph.GetNode(edge.To).Position) return totalLength / numberOfEdgesCounted
def WeightNavGraphNodeEdges(graph, nodeIndex, weight): """ Given a cost value and an index to a valid node this function examines all a node's edges, calculates their length, and multiplies the value with the weight. Useful for setting terrain costs. :param graph: :param nodeIndex: :param weight: :return: """ # Make sure the node is present if nodeIndex > graph.NumberOfNodes(): raise Exception("Invalid node index") # Set the cost for each edge for edge in graph.GetNodeEdges(nodeIndex): # Calculate the distance between nodes distance = Vector2D.Vec2DDistance( graph.GetNode(edge.From).Position, graph.GetNode(edge.To).Position) # Set the cost of this edge graph.SetEdgeCost(edge.From, edge.To, distance * weight) # If not a digraph, set the cost of the parallel edge to be the same if not graph.IsDigraph: graph.SetEdgeCost(edge.To, edge.From, distance * weight)
def test_SpecifyThatACircularRegionCanBeConstructed(self): circularRegion = TriggerRegionCircle(position=Vector2D(10, 9), radius=5) self.assertEqual(10, circularRegion._position.X, "position.X") self.assertEqual(9, circularRegion._position.Y, "position.Y") self.assertEqual(5, circularRegion._radius, "radius")
def test_SpecifyThatGraphNodeNavCanBeConstructed(self): graphNode = GraphNodeNav(index=10, position=Vector2D(20, 30)) self.assertEqual(10, graphNode.Index, "Index") self.assertEqual(20, graphNode.Position.X, "Position.X") self.assertEqual(30, graphNode.Position.Y, "Position.Y") self.assertEqual(None, graphNode.ExtraInfo, "ExtraInfo")
def test_SpecifyThatAVectorCanBeDeterminedIfItIsWithinASpecifiedRegion2( self): left = 1 top = 1 bottom = 10 right = 10 self.assertTrue( Vector2D.InsideRegion2(Vector2D(2, 3), left, top, right, bottom)) self.assertFalse( Vector2D.InsideRegion2(Vector2D(0, 3), left, top, right, bottom)) self.assertFalse( Vector2D.InsideRegion2(Vector2D(15, 3), left, top, right, bottom)) self.assertFalse( Vector2D.InsideRegion2(Vector2D(2, 0), left, top, right, bottom)) self.assertFalse( Vector2D.InsideRegion2(Vector2D(2, 20), left, top, right, bottom))
def test_SpecifyThatVectorCanBeZeroed(self): v = Vector2D(5, 10) self.assertEqual((5, 10), (v.X, v.Y)) v.Zero() self.assertEqual((0, 0), (v.X, v.Y))
def test_SpecifyThatPropertyMethodsWorkCorrectly(self): v = Vector2D(5, 10) self.assertEqual((5, 10), (v.X, v.Y)) v.X = 20 v.Y = 30 self.assertEqual((20, 30), (v.X, v.Y))
def test_SpecifyThatGraphNodeCanWriteOutItsContentsToConsole(self): graphNode = GraphNodeNav(index=10, position=Vector2D(20, 30), extraInfo="node info") stringOutput = str(graphNode) self.assertEqual( stringOutput, "Index: 10 | Position: (20.00, 30.00) | ExtraInfo: 'node info'")
def __init__(self, left, top, right, bottom, regionId=-1): self._left = left self._top = top self._right = right self._bottom = bottom self._regionId = regionId self._width = abs(right - left) self._height = abs(bottom - top) self._center = Vector2D((left + right) * 0.5, (top + bottom) * 0.5)
def Calculate(graph, nodeIndex1, nodeIndex2): """ Calculate the straight line distance from node nodeIndex1 to node nodeIndex2 :param graph: :param nodeIndex1: :param nodeIndex2: :return: """ return Vector2D.Vec2DDistance( graph.GetNode(nodeIndex1).Position, graph.GetNode(nodeIndex2).Position) * uniform(0.9, 1.1)
def test_SpecifyThatTheRegionCanDetermineIfAPositionCoordinateIsInside( self): # arrange region = self.CreateTestRegion() # assert self.assertFalse(region.IsInside(Vector2D(5, 25)), "Expected position vector to be outside region") self.assertTrue(region.IsInside(Vector2D(15, 25)), "Expected position vector to be inside region") self.assertFalse( region.IsInside(Vector2D(5, 55), RegionModifier.HalfSize), "Expected position vector to be outside half-size region") self.assertTrue( region.IsInside(Vector2D(35, 55), RegionModifier.HalfSize), "Expected position vector to be inside half-size region") self.assertRaises(ValueError, region.IsInside, Vector2D(35, 55), "invalid modifier")
def test_SpecifyThatAVectorCanWrappedAroundWhenItExceedsTheBoundingBox( self): v = Vector2D(1, 3) Vector2D.WrapAround(v, 10, 20) self.assertEqual((1, 3), (v.X, v.Y)) v = Vector2D(11, 3) Vector2D.WrapAround(v, 10, 20) self.assertEqual((0, 3), (v.X, v.Y)) v = Vector2D(-1, 3) Vector2D.WrapAround(v, 10, 20) self.assertEqual((10, 3), (v.X, v.Y)) v = Vector2D(1, 23) Vector2D.WrapAround(v, 10, 20) self.assertEqual((1, 0), (v.X, v.Y)) v = Vector2D(1, -23) Vector2D.WrapAround(v, 10, 20) self.assertEqual((1, 20), (v.X, v.Y))
def test_SpecifyThatBoxCanDetermineIfAnotherBoxOverlapsWithItself(self): box = Box2D(Vector2D(1, 2), Vector2D(8, 9)) otherOverlapping = Box2D(Vector2D(0, 0), Vector2D(3, 3)) otherNotOverlapping = Box2D(Vector2D(-1, -1), Vector2D(1, 1)) self.assertTrue(box.IsOverlappedWith(otherOverlapping), "overlapping") self.assertFalse(box.IsOverlappedWith(otherNotOverlapping), "not overlapping")
def test_SpecifyThatVectorOperationCanBePerformed(self): v1 = Vector2D(1, 0) v2 = Vector2D(1, 3) w = v1 + v2 self.assertEqual((2, 3), (w.X, w.Y), "add 1") w = v2 + v1 self.assertEqual((2, 3), (w.X, w.Y), "add 2") w = v1 - v2 self.assertEqual((0, -3), (w.X, w.Y), "sub 1") w = v2 - v1 self.assertEqual((0, 3), (w.X, w.Y), "sub 2") w = v2 * 2 self.assertEqual((2, 6), (w.X, w.Y), "mul 1") # Doesn't work # w = 2 * v2 # self.assertEqual((0, 3), (w.X, w.Y), "mul 2") w = Vector2D(4, 2) / 2 self.assertEqual((2, 1), (w.X, w.Y), "div 1") w = Vector2D(4, 2) w /= 2 self.assertEqual((2, 1), (w.X, w.Y), "idiv 1") w = Vector2D(4, 2) w *= 2 self.assertEqual((8, 4), (w.X, w.Y), "imul 1") v1 = Vector2D(1, 0) v2 = Vector2D(1, 3) v1 += v2 self.assertEqual((2, 3), (v1.X, v1.Y), "iadd 1") v1 = Vector2D(5, 4) v2 = Vector2D(1, 3) v1 -= v2 self.assertEqual((4, 1), (v1.X, v1.Y), "isub 1")
def CreateGrid(graph, cxSize, cySize, numCellsX, numCellsY): """ creates a graph based on a grid layout. This function requires the dimensions of the environment and the number of cells required horizontally and vertically :param graph: :param cxSize: :param cySize: :param numCellsX: :param numCellsY: :return: """ if numCellsX == 0 or numCellsY == 0: return # Need some temporaries to help calculate each node center cellWidth = cySize / numCellsX cellHeight = cxSize / numCellsY midX = cellWidth / 2 midY = cellHeight / 2 # First create all the nodes for rowIndex in range(numCellsY): for colIndex in range(numCellsX): nodePosition = Vector2D(midX + (colIndex * cellWidth), midY + (rowIndex * cellHeight)) node = GraphNodeNav(graph.GetNextFreeNodeIndex(), nodePosition) graph.AddNode(node) # Now to calculate the edges. (A position in a 2d array [x][y] is the same # as [y*NumCellsX + x] in a 1d array). Each cell has up to eight neighbours. for rowIndex in range(numCellsY): for colIndex in range(numCellsX): GraphTools.AddAllNeighboursToGridNode(graph, rowIndex, colIndex, numCellsX, numCellsY)
def test_SpecifyThatWhenNoRegionOfInfluenceIsAssignedTheTriggerIsTouchingReturnsFalseByDefault(self): trigger = self.CreateTestTrigger() self.assertEqual(False, trigger.IsTouchingTrigger(entityGpsPosition=Vector2D(3, 4), entityRadius=3))
def test_SpecifyThatATriggerCanDetermineIfAnEntityIsTouchingTheTrigger(self): trigger = self.CreateTestTrigger() trigger.AddRectangularTriggerRegion(topLeft=Vector2D(1, 3), bottomRight=Vector2D(5, 6)) self.assertEqual(True, trigger.IsTouchingTrigger(entityGpsPosition=Vector2D(3, 4), entityRadius=3))
def test_SpecifyThatARectangularRegionCanBeAdded(self): trigger = self.CreateTestTrigger() trigger.AddRectangularTriggerRegion(topLeft=Vector2D(1, 3), bottomRight=Vector2D(5, 6)) self.assertEqual(type(trigger._regionOfInfluence), TriggerRegionRectangle)
def test_SpecifyThatACircularRegionCanBeAdded(self): trigger = self.CreateTestTrigger() trigger.AddCircularTriggerRegion(center=Vector2D(1, 3), radius=3) self.assertEqual(type(trigger._regionOfInfluence), TriggerRegionCircle)
def test_SpecifyThatAVectorCanBeReversed(self): v = Vector2D(4, 5) w = v.GetReverse() self.assertEqual((-4, -5), (w.X, w.Y))
def test_SpecifyThatTheDistanceSquaredBetweenTwoVectorsCanBeCalculated( self): v1 = Vector2D(1, 0) v2 = Vector2D(1, 3) self.assertAlmostEqual(9.0, v1.DistanceSq(v2), places=3)