예제 #1
0
    def __init__(self, game, color, startpos=(0, 0)):
        pygame.sprite.Sprite.__init__(self)
        self.game = game
        self.color = color
        self.sprite_map = SpriteMap('gfx/fighter.json', color=color)
        self.rect = pygame.Rect(startpos[0], startpos[1], 128, 256)
        self.sprite = 'still'
        self.speed_x = 0
        self.speed_y = 0
        self.looking_right = True
        self.wins = 0
        self.start_pos = startpos

        self.kick_sound = pygame.mixer.Sound('snd/kick_empty.wav')
        self.punch_sound = pygame.mixer.Sound('snd/punch_empty.wav')
        self.hit_sounds = [pygame.mixer.Sound('snd/kick_hit.wav'), None]

        # speed multiplicator
        self.speed_multi = 1
        self.damage_reduction = 0
        self.damage_modifier = 1
        self.health = MAX_HEALTH
        self.punching = False
        self.kicking = False
        self.blocking = False
        self.block_delay = 0
        self.block_frame = -1
        self.anim_frame = 0
        self.jump_frame = 0
        self.jump_count = 0
        self.jump_max = 1
        self.damage_callbacks = []
        self.health_callbacks = []
        self.injection_callbacks = []
        self.update_callbacks = []
        self.damage_veto_callbacks = []

        self.injections = [(mutation.WingsMutation(), mutation.HardenedSkinMutation(), None),
                           (mutation.WingsMutation(), mutation.SwiftFeetMutation(), None), 
                           (mutation.StrengthMutation(), mutation.ToxicMutation(), None)]
        self.current_injection = -1 

        # holds the speed to be subtracted when the user lifts the 'left' or 'right'
        # button
        self.speed_reset_l = 0
        self.speed_reset_r = 0

        # holds pushback amount
        self.pushback = 0

        # used to keep track of whether a keypress belongs to a sequence:
        # when a key is pressed and sequence_frame is smaller than SEQUENCE_LIMIT
        # the key is added to the key sequence
        # if sequence_frame is greater than or equal to SEQUENCE_LIMIT, the key sequence
        # and sequence frame number are reset
        self.sequence_frame = 0
        self.current_sequence = []
        self.sequence_listeners = {}
예제 #2
0
class Fighter(pygame.sprite.Sprite):
    def __init__(self, game, color, startpos=(0, 0)):
        pygame.sprite.Sprite.__init__(self)
        self.game = game
        self.color = color
        self.sprite_map = SpriteMap('gfx/fighter.json', color=color)
        self.rect = pygame.Rect(startpos[0], startpos[1], 128, 256)
        self.sprite = 'still'
        self.speed_x = 0
        self.speed_y = 0
        self.looking_right = True
        self.wins = 0
        self.start_pos = startpos

        self.kick_sound = pygame.mixer.Sound('snd/kick_empty.wav')
        self.punch_sound = pygame.mixer.Sound('snd/punch_empty.wav')
        self.hit_sounds = [pygame.mixer.Sound('snd/kick_hit.wav'), None]

        # speed multiplicator
        self.speed_multi = 1
        self.damage_reduction = 0
        self.damage_modifier = 1
        self.health = MAX_HEALTH
        self.punching = False
        self.kicking = False
        self.blocking = False
        self.block_delay = 0
        self.block_frame = -1
        self.anim_frame = 0
        self.jump_frame = 0
        self.jump_count = 0
        self.jump_max = 1
        self.damage_callbacks = []
        self.health_callbacks = []
        self.injection_callbacks = []
        self.update_callbacks = []
        self.damage_veto_callbacks = []

        self.injections = [(mutation.WingsMutation(), mutation.HardenedSkinMutation(), None),
                           (mutation.WingsMutation(), mutation.SwiftFeetMutation(), None), 
                           (mutation.StrengthMutation(), mutation.ToxicMutation(), None)]
        self.current_injection = -1 

        # holds the speed to be subtracted when the user lifts the 'left' or 'right'
        # button
        self.speed_reset_l = 0
        self.speed_reset_r = 0

        # holds pushback amount
        self.pushback = 0

        # used to keep track of whether a keypress belongs to a sequence:
        # when a key is pressed and sequence_frame is smaller than SEQUENCE_LIMIT
        # the key is added to the key sequence
        # if sequence_frame is greater than or equal to SEQUENCE_LIMIT, the key sequence
        # and sequence frame number are reset
        self.sequence_frame = 0
        self.current_sequence = []
        self.sequence_listeners = {}

    def render(self, surface):
        off = self.sprite_map.offset(self.sprite)
        rect = self.game.viewport.real_rect(self.rect)
        hb = self.hit_boxes()
        #for b in hb:
        #    rb = self.game.viewport.real_rect(b)
        #    pygame.draw.rect(surface, pygame.Color(0,0,0,255), rb, 1)
        rect.x -= off
        rect.w += off
        if self.blocking:
            erect = pygame.Rect(rect.x, rect.y + self.sprite_map.offset_y(self.sprite),
                rect.w, rect.h)
            pygame.draw.ellipse(surface, pygame.Color(0, 255, 0, 200), erect, 5)
        if off != 0:
            rect = pygame.Rect(rect.x, rect.y, rect.w, rect.h)
        surface.blit(self.sprite_map.image(), rect, area=self.sprite_map.sprite_rect(self.sprite))

    def randomize_injections(self):
        possible_injections = [lambda: mutation.WingsMutation(), lambda: mutation.HardenedSkinMutation(),
                               lambda: mutation.SwiftFeetMutation(), lambda: mutation.TranquilityMutation(),
                               lambda: mutation.MagicalAffinityMutation(), lambda: mutation.ToxicMutation(),
                               lambda: mutation.StrengthMutation()]
        self.injections = [(possible_injections[random.randint(0, len(possible_injections) - 1)](),
                            possible_injections[random.randint(0, len(possible_injections) - 1)](), None)
                           for i in range(0, 3)]

    def mask(self):
        return self.sprite_map.mask(self.sprite)
    
    def _hit_boxes(self, rect):
        return [x.move(rect.x, rect.y) for x in self.sprite_map.hit_boxes(self.sprite)]
    
    def hit_boxes(self):
        return self._hit_boxes(self.rect)
    
    def fireball(self):
        self.game.fireballs.append(Fireball(self.game, self))

    def real_rect(self):
        return self.game.viewport.real_rect(self.rect)
    
    def injection_names(self):
        return [x.name for x in self.injections[self.current_injection] if x != None]

    def update(self):
        dy = GRAVITY
        if self.current_injection == -1:
            self.switch_to_injection(0)

        for platform in self.game.world.obstacles(self):
            if not util.collide_line_top(self.rect, platform):
                if self.rect.right > platform[0][0] and self.rect.left < platform[1][0]:
                    dy = min(dy, abs(self.rect.bottom - platform[0][1]))
            else:
                dy = 0
        dy += math.trunc(JUMP_SPEED * math.cos((math.pi / (2 * JUMP_DURATION)) * min(self.jump_frame, JUMP_DURATION)))

        if not self.pushback:
            new_rect = self.rect.move(self.speed_x - self.pushback, dy)
        else:
            new_rect = self.rect.move(self.speed_x - self.pushback, dy*.35)
            if self.pushback > 0:
                self.pushback -= 1
            elif self.pushback < 0:
                self.pushback += 1

        if not self.game.viewport.can_move(self, new_rect):
            new_rect.left = self.rect.left
        self.rect = new_rect

        if self.speed_x != 0 and not self.punching and not self.kicking:
            if self.anim_frame >= 4:
                self.sprite = 'walk01'
            if self.anim_frame >= 8:
                self.sprite = 'still'
                self.anim_frame = 0

        if self.punching:
            if self.anim_frame == 0:
                self.sprite = 'punch02'
            elif self.anim_frame == 2:
                self.sprite = 'punch03'
                self.game.hit_opponent(self, PUNCH_DAMAGE * self.damage_modifier)
            elif self.anim_frame >= 6:
                self.sprite = 'still'
                self.punching = False

        if self.kicking:
            if self.anim_frame == 0:
                self.sprite = 'kick02'
            elif self.anim_frame == 3:
                self.sprite = 'kick03'
                self.game.hit_opponent(self, KICK_DAMAGE * self.damage_modifier)
            elif self.anim_frame >= 8:
                self.sprite = 'still'
                self.kicking = False

        for cb in self.update_callbacks:
            cb()
        
        if self.block_frame > BLOCK_DURATION:
            self.block_frame = -1
            self.blocking = False
        
        self.anim_frame += 1
        self.jump_frame += 1
        self.sequence_frame += 1
        self.block_delay += 1
        if self.blocking:
            self.block_frame += 1
        if self.jump_frame > JUMP_DURATION:
            self.jump_count = 0

    def punch(self):
        self.register_keypress('punch')
        if self.active():
            return
        self.punching = True
        self.anim_frame = 0
        self.punch_sound.play()
    
    def kick(self):
        self.register_keypress('kick')
        if self.active():
            return
        self.kicking = True
        self.anim_frame = 0
        self.kick_sound.play()
    
    def active(self):
        return self.blocking or self.punching or self.kicking or self.pushback > 0
    
    def block(self):
        if self.active() or self.block_delay < BLOCK_DELAY:
            return
        self.block_delay = 0
        self.block_frame = 0
        self.blocking = True
    
    def take_damage(self, dmg, direction, kind='physical', sound=0, pushback_mod=1):
        print len(self.damage_veto_callbacks)
        for cb in self.damage_veto_callbacks:
            dmg = cb(dmg, kind)
        dmg = int((1 - self.damage_reduction) * dmg)
        if self.blocking:
            dmg = 0
        self.health -= dmg
        for cb in self.damage_callbacks:
            cb(self.health, dmg, kind)
        if self.hit_sounds[sound]:
            self.hit_sounds[sound].play()
        # we want a little pushback
        if not self.blocking:
            self.pushback = PUSHBACK_DISTANCE * direction * pushback_mod
        self.game.check_state()
    
    def increase_health(self, health):
        if self.health == MAX_HEALTH:
            return
        self.health += health
        if self.health > MAX_HEALTH:
            self.health = MAX_HEALTH
        for cb in self.health_callbacks:
            cb(self.health, health)
    
    def left(self):
        self.speed_x -= WALK_SPEED * self.speed_multi
        self.speed_reset_l = -1 * WALK_SPEED * self.speed_multi
        if self.looking_right:
            #self.register_keypress('back')
            self.looking_right = False
            self.sprite_map.flip()
        else:
            pass
            #self.register_keypress('forward')
        self.register_keypress('left')
    
    def right(self):
        self.speed_x += WALK_SPEED * self.speed_multi
        self.speed_reset_r = WALK_SPEED * self.speed_multi
        if not self.looking_right:
            #self.register_keypress('back')
            self.looking_right = True
            self.sprite_map.flip()
        else:
            pass
            #self.register_keypress('forward')
        self.register_keypress('right')

    def stop_left(self):
        self.speed_x -= self.speed_reset_l

    def stop_right(self):
        self.speed_x -= self.speed_reset_r

    def jump(self):
        if self.jump_count < self.jump_max:
            self.jump_count += 1
            self.jump_frame = 1
    
    def opponent(self):
        return self.game.opponent(self)

    def switch_to_injection(self, number):
        if self.current_injection != -1:
            for m in self.injections[self.current_injection]:
                if m != None:
                    m.deactivated(self)
        for m in self.injections[number]:
            if m != None:
                m.activated(self)
        for cb in self.injection_callbacks:
            cb(self.current_injection, number)
        self.current_injection = number
    
    def reset(self):
        self.health = 1000
        self.speed_x = 0
        self.speed_reset_l = 0
        self.speed_reset_r = 0
        self.rect.left = self.start_pos[0]
        self.rect.top = self.start_pos[1]
        if self.current_injection != -1:
            for m in self.injections[self.current_injection]:
                if m != None:
                    m.deactivated(self)
            self.current_injection = -1
        if self.rect.left < self.game.opponent(self).rect.left:
            if not self.looking_right:
                self.sprite_map.flip()
                self.looking_right = True
        else:
            if self.looking_right:
                self.sprite_map.flip()
                self.looking_right = False
    
    def mutation_names(self):
        return [mut.name for mut in self.injections[self.current_injection] if mut != None]

    def register_keypress(self, key):
        if self.sequence_frame < SEQUENCE_LIMIT:
            self.current_sequence.append(key)
            
            pos = 0
            for pos in range(0, len(self.current_sequence)):
                if self.sequence_listeners.has_key("".join(self.current_sequence[pos:])):
                    self.sequence_listeners["".join(self.current_sequence[pos:])](self)
                    break

            self.sequence_frame = 0
        else:
            self.sequence_frame = 0
            self.current_sequence = [key]
    
    def register_key_sequence(self, sequence, listener):
        self.sequence_listeners[sequence] = listener
    
    def deregister_key_sequence(self, sequence):
        if self.sequence_listeners.has_key(sequence):
            self.sequence_listeners.pop(sequence)
    
    def simulate_key_sequence(self, sequence):
        for p in sequence:
            self.register_keypress(p)