Source code for steering.priority
# -*- coding: utf-8 -*-
""" Priority Steering Behaviors
This module implements a class that holds a list of
:py:class:`~.kinematic.KinematicSteeringBehavior`\ s and applies them in order,
keeping only the first one that produces an output greater than a certain
treshold. This means that some behaviors which are considered more important
(like :py:class:`~.kinematic.ObstacleAvoidance` and
:py:class:`~.kinematic.CollisionAvoidance`) but are not always neccesary
to reach the character's goal can be ignored when they don't produce a
meaningful output, it also means that when they do produce a meaningful
output they will be the only ones in action.
This is a very simple form of decision making that involves only steering
algorithms, and therefore it is classified as a steering behavior.
Derives from :py:class:`~.kinematic.KinematicSteeringBehavior`.
Example
--------
This is how you would normally create your own :py:class:`~PrioritySteering`\ ,
in this case we are making a behavior that will most of the time **Pursue**
a target, but will prioritize **Avoiding Obstacles** when that behavior
returns a steering greater than the treshold.
.. code-block:: python
mybehavior = PrioritySteering(
behaviors = [
kinematic.ObstacleAvoidance(character, obstacles),
kinematic.Pursue(character, target),
],
)
"""
from . import kinematic
from . import blended
from . import path
[docs]class PrioritySteering(kinematic.KinematicSteeringBehavior):
def __init__(self, behaviors, epsilon = 0.1):
self.behaviors = behaviors
self.epsilon = epsilon
def __repr__(self):
return 'PrioritySteering '+super(PrioritySteering, self).__repr__()
[docs] def draw_indicators(self, screen, offset = (lambda pos: pos)):
for behavior in self.behaviors:
behavior.draw_indicators(screen, offset)
[docs] def get_steering(self):
for behavior in self.behaviors:
# Get behavior's steering
steering = behavior.get_steering()
# If any of it's components surpases the treshold, return it
if steering.linear.length() > self.epsilon or abs(steering.angular) > self.epsilon:
return steering
# If we get here, no output surpased the treshold
# Return the last group's steering as small as it is
return steering
class OscilateHorizontally(PrioritySteering):
def __init__(self, character, target, solid_entities, width = 160, height = 80, start_x = 0):
def mypath(self, i):
x, y = self.center()
a = [(x - width//2, y - height), (x, y - height), (x + width//2, y - height)]
return a[i]
hpath = path.MirroredPath(mypath, domain_end = 2)
hpath.center = lambda: target.position
hpath.x = start_x
behaviors = [
kinematic.CollisionAvoidance(character, solid_entities),
kinematic.FollowPath(character, hpath),
]
super(OscilateHorizontally, self).__init__(behaviors, epsilon = 10)