def plotLocalRouteAroundTarget(owner, target): steeringController = owner.steeringController ownerPosition = owner.getPosition() targetPosition = target.getPosition() ownerToTarget = calculate.subtractPoints(targetPosition, ownerPosition) distanceToTarget = vector.getMagnitude(ownerToTarget) optimalPathDistance = min(distanceToTarget, owner.getMaximumFiringRange()) #These are the eight "compass" directions, projected #in the target's local space vectors = ((0, 1), (1, 1), (1, 0), (-1, 1), (-1, 0), (-1, -1), (0, -1), (1, -1)) #Now scale the directions so that they have my magnitude. #We can treat these vectors as points in an octagonal #path around the target - a path scaled to an optimal distance. pathPoints = [calculate.multiplyVectorAndScalar(normalizedVector, optimalPathDistance) for normalizedVector in vectors] #Find the point in the path that is closest to my position. ownerLocalPosition = convert.pointToLocalSpace(ownerPosition, targetPosition, target.getDirection()) closestDistanceSquared = None closestIndex = None for index in range(len(pathPoints)): pathPoint = pathPoints[index] ownerToPathPoint = calculate.subtractPoints(pathPoint, ownerLocalPosition) distanceSquaredToPathPoint =\ vector.getMagnitudeSquared(ownerToPathPoint) if (closestDistanceSquared is None or distanceSquaredToPathPoint < closestDistanceSquared): closestIndex = index closestDistanceSquared = distanceSquaredToPathPoint #Now "shift" the path so that my closest point is the first in the list. path = pathPoints[closestIndex:] + pathPoints[:closestIndex] #Plot a course to visit the path. If at any point I find a clear shot to the target, #I will dive at it. steeringController.plotPath(path, closed=True)
def intersectsPoint(self, point): shipPosition = self.getPosition() shipToPoint = calculate.subtractPoints(point, shipPosition) distanceSquaredToPoint = vector.getMagnitudeSquared(shipToPoint) if (distanceSquaredToPoint > self.lengthSquared or distanceSquaredToPoint > self.widthSquared): return None directionRadians = self.getDirection() localPoint = convert.pointToLocalSpace(point, shipPosition, directionRadians) (topy, rightx, bottomy, leftx) = self.boundingBox x, y = localPoint if (x > leftx and x < rightx and y < topy and y > bottomy): return True
def _getClosestObstacle(agent, obstaclesInRange): agentPosition = agent.getPosition() agentDirectionRadians = agent.getDirectionRadians() (obstacleDetectionLength, obstacleDetectionWidth) = agent.getObstacleDetectionDimensions() closestObstacle = None distanceToClosestInterceptPoint = None obstacleLocalPosition = None for obstacle in obstaclesInRange: (obstacleX, obstacleY) = convert.pointToLocalSpace(obstacle.getPosition(), agentPosition, agentDirectionRadians) if obstacleX >= 0: expandedRadius = obstacle.getRadius() + (obstacleDetectionWidth / 2) if abs(obstacleY) < expandedRadius: #obstacleX +/- sqrt(expandedRadius^2 - obstacleY^2) if expandedRadius ** 2 < obstacleY ** 2: sqrtPart = 0 else: sqrtPart = math.sqrt((expandedRadius**2) - (obstacleY**2)) interceptPoint = obstacleX - sqrtPart if interceptPoint <= 0: interceptPoint = obstacleX + sqrtPart if closestObstacle is None or interceptPoint < distanceToClosestInterceptPoint: closestObstacle = obstacle distanceToClosestInterceptPoint = interceptPoint obstacleLocalPosition = (obstacleX, obstacleY) return (closestObstacle, obstacleLocalPosition)
def test_localSpaceIsWorldSpace_pointIsTheSame(self): newPoint = convert.pointToLocalSpace(point=(1, 1), localOrigin=(0, 0), localDirection=0) self.assertEquals((1, 1), newPoint)
def test_localSpaceIsRotated90Degrees(self): newPoint = convert.pointToLocalSpace(point=(1, 0), localOrigin=(0, 0), localDirection=math.pi / 2) self.assertEquals((0, -1), newPoint)
def test_pointIsOneAwayFromLocalSpaceOrigin_pointIsOne(self): newPoint = convert.pointToLocalSpace(point=(2, 2), localOrigin=(1, 1), localDirection=0) self.assertEquals((1, 1), newPoint)
def test_pointIsOnLocalSpaceOrigin_pointIsZero(self): newPoint = convert.pointToLocalSpace(point=(1, 1), localOrigin=(1, 1), localDirection=0) self.assertEquals((0, 0), newPoint)