Changeset 410:d7bd9adb105a for nagslang


Ignore:
Timestamp:
Sep 7, 2013, 10:33:35 AM (7 years ago)
Author:
Jeremy Thurgood <firxen@…>
Branch:
default
rebase_source:
a8c24b828f392321fa814f01e4fef5a7b0a40be9
Message:

Sheep! (And refactoring!)

Location:
nagslang
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • nagslang/constants.py

    r371 r410  
    2525COLLISION_TYPE_PROJECTILE = 7
    2626COLLISION_TYPE_WEREWOLF_ATTACK = 8
     27COLLISION_TYPE_SHEEP = 9
    2728
    2829SWITCH_PUSHERS = [COLLISION_TYPE_PLAYER, COLLISION_TYPE_FURNITURE]
     
    3536    COLLISION_TYPE_ENEMY,
    3637    COLLISION_TYPE_DOOR,
     38    COLLISION_TYPE_SHEEP,
    3739]
    3840
  • nagslang/enemies.py

    r409 r410  
    66
    77from nagslang import render
    8 from nagslang.constants import (COLLISION_TYPE_ENEMY, COLLISION_TYPE_FURNITURE,
    9                                 ACID_SPEED, ACID_DAMAGE, ZORDER_MID)
     8from nagslang.constants import (
     9    COLLISION_TYPE_ENEMY, COLLISION_TYPE_FURNITURE, COLLISION_TYPE_SHEEP,
     10    ACID_SPEED, ACID_DAMAGE, ZORDER_MID)
    1011from nagslang.game_object import (GameObject, SingleShapePhysicser, Result,
    1112                                  Bullet, make_body)
     
    3637    health = None
    3738    impulse_factor = None
     39    random_move_time = 0.3
    3840
    3941    def __init__(self, space, world, position):
     
    4244        self.world = world
    4345        self.angle = 0
     46        self.add_timer('random_move', self.random_move_time)
     47        self._last_random_direction = (0, 0)
    4448
    4549    def make_physics(self, space, position):
     
    5660        })
    5761
    58     def attack(self):
    59         raise NotImplementedError
    60 
    61     @classmethod
    62     def requires(cls):
    63         return [("name", "string"), ("position", "coordinates")]
     62    def get_render_angle(self):
     63        # No image rotation when rendering, please.
     64        return 0
     65
     66    def get_facing_direction(self):
     67        # Enemies can face left or right.
     68        if - math.pi / 2 < self.angle <= math.pi / 2:
     69            return 'right'
     70        else:
     71            return 'left'
    6472
    6573    def hit(self, weapon):
     
    102110        return target - pos
    103111
    104     def ranged_attack(self, range_, speed, damage, type_, reload_time,
    105                       result=None):
    106         if result is None:
    107             result = Result()
    108 
     112    def ranged_attack(self, range_, speed, damage, type_, reload_time, result):
    109113        vec = self.range_to_visible_protagonist()
    110114        if vec is None:
    111             return result
     115            return
    112116
    113117        if not self.check_timer('reload_time'):
     
    118122                    self.get_space(), self.physicser.position, vec, damage,
    119123                    type_, COLLISION_TYPE_ENEMY),)
    120         return result
    121124
    122125    def greedy_move(self, target):
     
    136139    def random_move(self):
    137140        """Random move"""
    138         x_step = random.choice([-1, 0, 1])
    139         y_step = random.choice([-1, 0, 1])
    140         return x_step, y_step
     141        if not self.check_timer('random_move'):
     142            self.start_timer('random_move')
     143            self._last_random_direction = (
     144                random.choice([-1, 0, 1]), random.choice([-1, 0, 1]))
     145        return self._last_random_direction
     146
     147    def attack(self, result):
     148        pass
     149
     150    def move(self, result):
     151        pass
    141152
    142153    def update(self, dt):
     
    148159                                     self.physicser.position,
    149160                                     self.enemy_type),)
     161        self.move(result)
     162        self.attack(result)
    150163        return result
     164
     165    @classmethod
     166    def requires(cls):
     167        return [("name", "string"), ("position", "coordinates")]
    151168
    152169
     
    191208        return SingleShapePhysicser(space, shape)
    192209
    193     def get_render_angle(self):
    194         # No image rotation when rendering, please.
    195         return 0
    196 
    197     def get_facing_direction(self):
    198         # Enemies can face left or right.
    199         if - math.pi / 2 < self.angle <= math.pi / 2:
    200             return 'right'
    201         else:
    202             return 'left'
    203 
    204210    def _switch_direction(self):
    205211        if self._direction == 'away':
     
    208214            self._direction = 'away'
    209215
    210     def update(self, dt):
    211         # Calculate the step every frame
     216    def move(self, result):
    212217        if self._direction == 'away':
    213218            target = self._end_pos
     
    218223            self._switch_direction()
    219224        self.set_direction(x_step, y_step)
    220         result = self.ranged_attack(300, ACID_SPEED, ACID_DAMAGE, 'acid', 0.2)
    221         return result.merge(super(PatrollingAlien, self).update(dt))
     225
     226    def attack(self, result):
     227        self.ranged_attack(300, ACID_SPEED, ACID_DAMAGE, 'acid', 0.2, result)
    222228
    223229    @classmethod
     
    247253        return SingleShapePhysicser(space, shape)
    248254
    249     def get_render_angle(self):
    250         # No image rotation when rendering, please.
    251         return 0
    252 
    253     def get_facing_direction(self):
    254         # Enemies can face left or right.
    255         if - math.pi / 2 < self.angle <= math.pi / 2:
    256             return 'right'
    257         else:
    258             return 'left'
    259 
    260     def _calc_movement(self):
     255    def move(self, result):
    261256        pos = self.physicser.position
    262257        target = self.world.protagonist.get_shape().body.position
     
    267262        self.is_moving = True
    268263        dx, dy = self.greedy_move(target)
    269         return dx, dy
    270 
    271     def update(self, dt):
    272         # Calculate the step every frame
    273         # Distance to the protagonist
    274         result = self.ranged_attack(300, ACID_SPEED, ACID_DAMAGE, 'acid', 0.2)
    275         dx, dy = self._calc_movement()
    276264        self.set_direction(dx, dy)
    277         return result.merge(super(ChargingAlien, self).update(dt))
     265
     266    def attack(self, result):
     267        self.ranged_attack(300, ACID_SPEED, ACID_DAMAGE, 'acid', 0.2, result)
    278268
    279269    @classmethod
     
    288278    impulse_factor = 90
    289279    is_moving = True
    290 
    291     def __init__(self, space, world, position, attack_range=100):
    292         super(RunAndGunAlien, self).__init__(space, world, position,
    293                                              attack_range)
    294         self.count = 0
    295         self._old_move = (0, 0)
    296280
    297281    def make_physics(self, space, position):
     
    303287        return SingleShapePhysicser(space, shape)
    304288
    305     def _calc_movement(self):
     289    def move(self, result):
    306290        pos = self.physicser.position
    307291        target = self.world.protagonist.get_shape().body.position
    308292        if pos.get_distance(target) < self._range:
    309             if self.count > 10:
    310                 self._old_move = self.random_move()
    311                 self.count = 0
    312             return self._old_move
    313         else:
    314             return self.greedy_move(target)
    315 
    316     def update(self, dt):
    317         self.count += 1
    318         return super(RunAndGunAlien, self).update(dt)
     293            step = self.random_move()
     294        else:
     295            step = self.greedy_move(target)
     296        self.set_direction(*step)
    319297
    320298    @classmethod
     
    322300        return [("name", "string"), ("position", "coordinates"),
    323301                ("attack_range", "distance")]
     302
     303
     304class Sheep(Enemy):  # Only because we don't have a DeliciousCreature class.
     305    is_moving = True  # Always walking.
     306    enemy_type = 'sheep'
     307    health = 10
     308    impulse_factor = 50
     309
     310    vision_range = 100
     311
     312    def make_physics(self, space, position):
     313        body = make_body(10, pymunk.inf, position, 0.8)
     314        shape = pymunk.Circle(body, 30)
     315        shape.elasticity = 1.0
     316        shape.friction = 0.05
     317        shape.collision_type = COLLISION_TYPE_SHEEP
     318        return SingleShapePhysicser(space, shape)
     319
     320    def move(self, result):
     321        vec = self.range_to_visible_protagonist()
     322        if vec is not None and vec.length < self.vision_range:
     323            # TODO: Run away! Wander towards!
     324            step = (0, 0)
     325        else:
     326            step = self.random_move()
     327        self.set_direction(*step)
     328
     329    @classmethod
     330    def requires(cls):
     331        return [("name", "string"), ("position", "coordinates")]
Note: See TracChangeset for help on using the changeset viewer.