class SimpleVehicle2d(BasePointMass2d): """Point mass with steering behaviour.""" def __init__(self, position, radius, velocity, spritedata=None): BasePointMass2d.__init__(self, position, radius, velocity, spritedata) # Steering behavior class for this object. self.steering = SteeringBehavior(self) def move(self, delta_t=1.0): """Compute steering force and update rectilinear motion.""" force = self.steering.compute_force() BasePointMass2d.move(self, delta_t, force)
def __init__(self, img_surf, img_rect, position, radius, velocity): # Must call pygame's Sprite.__init__ first! pygame.sprite.Sprite.__init__(self) # Pygame image information for blitting self.orig = img_surf self.image = img_surf self.rect = img_rect # Basic object physics # Note: We can't use self.pos = position here because of Point2d's # __init__ method (and lack of __copy__), ditto for self.vel. self.pos = Point2d(position[0], position[1]) # Center of object self.radius = radius # Bounding radius self.vel = Point2d(velocity[0], velocity[1]) # Current Velocity # Normalized front vector in world coordinates. # This stays aligned with the object's velocity. try: self.front = velocity.unit() except ZeroDivisionError: # If velocity is <0,0>, set facing to screen upwards self.front = Point2d(0,-1) self.left = Point2d(-self.front[1], self.front[0]) self._rotate_for_blit() # Movement constraints (defaults from steering_constants.py) ## TODO: Put these in the function argument, perhaps as **kwargs self.mass = POINTMASS2D_MASS self.maxspeed = POINTMASS2D_MAXSPEED self.maxforce = POINTMASS2D_MAXFORCE # Steering behavior class for this object. self.steering = SteeringBehavior(self)
class PointMass2d(pygame.sprite.Sprite): """A pygame.Sprite with rectilnear motion and steering behaviour. Parameters ---------- img_surf: pygame.Surface Contains the image of the sprite; used for blitting. img_rect: pygame.rect Pygame rectangle with sprite information; used for blitting. position: Point2d Center of mass, in screen coordinates. radius: float Bounding radius of the object. velocity: Point2d Velocity vector, in screen coordinates. Facing will match this. Notes ----- This class uses Pygame's sprite group update() method to automatically compute steering and rectilinear motion along with each render update. While this works for simple use, it is causing integaration issues with other update (i.e., FSM and messaging). The new BasePointMass2d class above decouples the pygame sprite update, and may be more appropriate. As a result, it is not unlikely that this class will be deprecated. It is recommended to use the load_image() function above to initialize the image surface and rectangle, then pass the values to this function. One reason for separating these functions is to allow multiple sprites to use the same image file. """ def __init__(self, img_surf, img_rect, position, radius, velocity): # Must call pygame's Sprite.__init__ first! pygame.sprite.Sprite.__init__(self) # Pygame image information for blitting self.orig = img_surf self.image = img_surf self.rect = img_rect # Basic object physics # Note: We can't use self.pos = position here because of Point2d's # __init__ method (and lack of __copy__), ditto for self.vel. self.pos = Point2d(position[0], position[1]) # Center of object self.radius = radius # Bounding radius self.vel = Point2d(velocity[0], velocity[1]) # Current Velocity # Normalized front vector in world coordinates. # This stays aligned with the object's velocity. try: self.front = velocity.unit() except ZeroDivisionError: # If velocity is <0,0>, set facing to screen upwards self.front = Point2d(0,-1) self.left = Point2d(-self.front[1], self.front[0]) self._rotate_for_blit() # Movement constraints (defaults from steering_constants.py) ## TODO: Put these in the function argument, perhaps as **kwargs self.mass = POINTMASS2D_MASS self.maxspeed = POINTMASS2D_MAXSPEED self.maxforce = POINTMASS2D_MAXFORCE # Steering behavior class for this object. self.steering = SteeringBehavior(self) def move(self, delta_t=1.0, force_vector=None): """Update the position of this object, using its current velocity. Parameters ---------- delta_t: float Time increment since last move. """ self.pos = self.pos + self.vel.scale(delta_t) self.rect.center = self.pos[0], self.pos[1] if force_vector: # Don't exceed our maximum force; compute acceleration/velocity force_vector.truncate(self.maxforce) accel = force_vector.scale(delta_t/self.mass) self.vel = self.vel + accel # Don't exceed our maximum speed self.vel.truncate(self.maxspeed) # If velocity is very small, skip alignment to avoid jittering. if self.vel.sqnorm() > SPEED_EPSILON: self.front = self.vel.unit() self.left = Point2d(-self.front[1], self.front[0]) def _rotate_for_blit(self): """Used to rotate the object's image prior to blitting. Note ---- This function does not update any physics, it only rotates the image, based on the object's current front vector. """ theta = self.front.angle()*SCREEN_DEG center = self.rect.center self.image = pygame.transform.rotate(self.orig, theta) self.rect = self.image.get_rect() self.rect.center = center def update(self, delta_t=1.0): """Update the object's position and autonomous steering force. Parameters ---------- dt: float Time increment since last update. Default = 1.0. Note ---- This function is intended to be called by a pygame.Group.update() method each cycle. This passes the same arguments to each sprite, so instance-specific behaviour must be computed within this function. """ # Autonomous steering behaviour computed here force = self.steering.compute_force() # Movement and image rotation: self.move(delta_t, force) self._rotate_for_blit() # Used to draw force vectors for pygame demos self.force = force
def __init__(self, position, radius, velocity, spritedata=None): BasePointMass2d.__init__(self, position, radius, velocity, spritedata) # Steering behavior class for this object. self.steering = SteeringBehavior(self)