Exemplo n.º 1
0
class PlayerSprite(BaseObject):
    def __init__(self, var_dict):
        BaseObject.__init__(self, var_dict)
        self.type = PLAYER
        self.xvel = 0
        self.yvel = 0
        self.jumpvel = 1
        self.walkvel = 0.05
        self.maxXvel = 2.3
        self.maxYvel = 8
        self.direction = DIR_RIGHT
        self.iswalking = False
        self.on_object = None
        self.col_object = None
        self.jump_state = NOT_JUMPING
        self.airborne = True
        self.j_delay_timer = Timer(50, self.__next_jump_state, False)
        self.jump_timer = Timer(240, self.__next_jump_state, False)
        self._layer = 10
        #Array of objects currently colliding with rect - Tracks objects that are possible to interact with
        self.pos_interact = []
        self.held_item = None
        self.drop_item = None
        self.collidable = True
        self.held_ofs_x = 0.0
        self.held_ofs_y = 0.0
        self.obey_gravity = True
        self.visible = True

        self.idle_files = var_dict['idle_files'].split(',')
        self.idle_times = var_dict['idle_times'].split(',')
        self.jump_files = var_dict['jump_files'].split(',')
        self.jump_times = var_dict['jump_times'].split(',')
        self.walk_files = var_dict['walk_files'].split(',')
        self.walk_times = var_dict['walk_times'].split(',')
        self.idle_anim = Animation(self.idle_files, self.idle_times)
        self.jumping_anim = Animation(self.jump_files, self.jump_times)
        self.walking_anim = Animation(self.walk_files, self.walk_times)
        self.walking_anim.set_colorkey((255, 255, 255))

        if var_dict['w'] == 0 or var_dict['h'] == 0:
            self.rect.w = self.idle_anim.getRect().w
            self.rect.h = self.idle_anim.getRect().h
        else:
            pass
            #Needs to scale all animations while keeping aspect ratio.
            #self.walking_anim.scale((var_dict['w'], var_dict['h']))
            #self.jumping_anim.scale((var_dict['w'], var_dict['h']))
        self.anim_player = Animation_Player()
        self.anim_player.add(self.walking_anim, WALK_ANIM)
        self.anim_player.add(self.jumping_anim, JUMP_ANIM)
        self.anim_player.add(self.idle_anim, IDLE_ANIM)
        self.anim_player.set(IDLE_ANIM, True)

    def draw(self, screen, rect_loc):
        if self.jump_state > 0:
            self.anim_player.set(JUMP_ANIM)
        elif self.iswalking is True:
            self.anim_player.set(WALK_ANIM)
        else:
            self.anim_player.set(IDLE_ANIM)

        self.anim_player.draw(screen, rect_loc)

    def move(self):
        if self.iswalking is False:
            if self.xvel <= 0:
                self.xvel = 0
            else:
                self.xvel -= 1
        if self.direction == DIR_RIGHT and self.iswalking:
            if self.col_object is None:
                self._change_vel(DIR_RIGHT, self.walkvel)
            else:
                #check what side the object is on, permit walking the other way
                if self.col_object.rect.x < self.rect.x:
                    self._change_vel(DIR_RIGHT, self.walkvel)
        elif self.direction == DIR_LEFT and self.iswalking:
            if self.col_object is None:
                self._change_vel(DIR_LEFT, self.walkvel)
            else:
                if self.col_object.rect.x > self.rect.x:
                    self._change_vel(DIR_LEFT, self.walkvel)

        #Is the player colliding with ANY objects?
        if self.col_object is not None:
            #Check if still colliding with col_object
            if not self.rect.colliderect(self.col_object.rect):
                self.col_object = None

        #If player was on top of an object last tick
        if self.on_object is not None:
            #Check if player is still on object
            if self.on_object.rect.collidepoint(self.rect.midbottom):
                self.airborne = False
                #If player is on an object and yvel is being modified by do_jump(), stop the jump
                #if self._is_jumping():
                 #   self._stop_jump()
            else:
                self.on_object = None
        else:
            self.airborne = True

        if self.jump_state == JUMP:
            self._do_jump()

        self.update_pos()

    def move_direction(self, player_dir):
        #check if changing direction, if so lessen x velocity
        if player_dir != self.direction:
            self.xvel -= self.xvel / 2
            self.anim_player.flip()
        self.direction = player_dir
        self.iswalking = True

    def collide(self, obj):
        """Returns if object is colliding, calls _respond_collision on True and _check_pos_interact every time"""
        colliding = False
        if self.rect.colliderect(obj.rect):
            colliding = True
            self._respond_collision(obj)

        self._check_pos_interact(obj, colliding)
        return colliding

    def _respond_collision(self, obj):
        """Responds to a collision, trusts the caller that the objects are colliding"""
        if obj.collidable:
                #save the last collided object
                self.col_object = obj
                if obj.rect.collidepoint(self.rect.midbottom):
                    self.yvel = 0
                    self.rect.bottom = obj.rect.top
                    #save the object the player is on
                    self.on_object = obj
                    #If falling, let jump state know player landed
                    if self.jump_state == FALLING:
                        self.__next_jump_state()
                elif obj.rect.collidepoint(self.rect.bottomleft):
                    if self.direction == DIR_LEFT:
                        self.xvel = 0
                elif obj.rect.collidepoint(self.rect.bottomright):
                    if self.direction == DIR_RIGHT:
                        self.xvel = 0

    def _check_pos_interact(self, obj, colliding):
        """Maintains list of objects with possible interaction"""
        if colliding:
            if obj not in self.pos_interact:
                self.pos_interact.append(obj)
        else:
            if obj in self.pos_interact:
                self.pos_interact.remove(obj)

    def __next_jump_state(self):
        if self.jump_state == NOT_JUMPING:
            self.jump_state = JUMP_DELAY
            self.j_delay_timer.start_timer()
        elif self.jump_state == JUMP_DELAY:
            self.jump_state = JUMP
            self.jump_timer.start_timer()
            self._change_vel(DIR_UP, 2)
        elif self.jump_state == JUMP:
            self.jump_state = FALLING
        elif self.jump_state == FALLING:
            self.jump_state = NOT_JUMPING
        else:
            print("Invalid player jump state: " + str(self.jump_state))

    def start_jump(self):
        self.__next_jump_state()

    def _do_jump(self):
        self._change_vel(DIR_UP, self.jumpvel)

    def update(self):
        self.move()

    def do_gravity(self, gravity):
        self._change_vel(DIR_DOWN, gravity)

    def check_interactions(self):
        if not self._use_timer:
            self._use_timer = Timer(self.use_timer_len, self._set_can_use)
        if self._can_use:
            #interact with held item
            if self.held_item:
                if self.interact(self.held_item, PLACE):
                    self._can_use = False
                    self._use_timer.start_timer()
                    return

            for obj in self.pos_interact:
                if self.interact(obj, TOGGLE_POWER):
                    return

    def interact(self, obj, behvaior):
        print('interacting with ' + obj.name)
        for behavior in self.behaviors:
            if self.delegate_behavior(obj, behavior):
                return True
        return False

    def delegate_behavior(self, obj, behavior):
        if behavior == PICKUP:
            return self.pickup(obj)
        if behavior == PLACE:
            return self.drop()

        return obj.interact(self, behavior)

    def drop(self):
        if self.held_item:
            self.drop_item = self.held_item
            self.drop_item.visible = True
            self.drop_item.obey_gravity = True
            self.held_item = None
            print('dropped item')
            return True
        return False

    def pickup(self, obj):
        if PICKUP in obj.behaviors and not self.held_item:
            obj.visible = False
            obj.obey_gravity = False
            self.held_item = obj
            #level.objects.change_layer(self.held_item, self._layer) #Check/update this in level.draw function
            self.held_item.rect.y = self.rect.centery + (self.rect.w / 6)
            self.held_item.rect.x = self.rect.centerx
            #save offsets from the top left of player sprite
            self.held_ofs_x = self.held_item.rect.x - self.rect.x
            self.held_ofs_y = self.held_item.rect.y - self.rect.y
            print('picked up item')
            return True
        return False

    def update_pos(self):
        self.rect.x += self.xvel
        self.rect.y += self.yvel
        if self.held_item:
            self.held_item.rect.x = self.held_ofs_x + self.rect.x
            self.held_item.rect.y = self.held_ofs_y + self.rect.y
Exemplo n.º 2
0
class LevelObject(BaseObject):
    def __init__(self, var_dict):
        BaseObject.__init__(self, var_dict)
        self.type = LEVEL_OBJECT
        self.files = var_dict['files'].split(',')
        self.times = var_dict['times'].split(',')

        #HACK - ANIMATION WILL CHANGE THIS
        #If files is larger than 1, create animation with 2 frames
        # if len(self.files) > 1 and self.files[1] != '':
        #     self.idle_anim = pyganim.PygAnimation([(os.path.join(self.files[0]), .75),
        #                                            (os.path.join(self.files[1]), .75)])
        #     self.idle_anim.set_colorkey((255, 255, 255))
        # #Else if files has 1 file, create animation with 1 frame
        # elif len(self.files) > 0:
        #     self.idle_anim = pyganim.PygAnimation([(os.path.join(self.files[0]), 1)])
        #     self.idle_anim.set_colorkey((255, 255, 255))

        self.idle_anim = Animation(self.files, self.times)

        #If width or height is 0, use default w/h
        if var_dict['w'] == 0 or var_dict['h'] == 0:
            self.rect.w = self.idle_anim.getRect().w
            self.rect.h = self.idle_anim.getRect().h
        else:
            self.idle_anim.scale((var_dict['w'], var_dict['h']))
        self.rect.x = var_dict['x']
        self.rect.y = var_dict['y']
        self.col_objects = []
        self.on_object = None
        self._layer = var_dict['_layer']
        self.layer = self._layer
        self.collidable = to_bool(var_dict['collidable'])
        self.idle_anim.play()
        self.obey_gravity = to_bool(var_dict['obey_gravity'])
        self.visible = True

    def draw(self, screen, translated):
        self.idle_anim.blit(screen, translated)

    def update(self):
        self.move()

    def do_gravity(self, gravity):
        self._change_vel(DIR_DOWN, gravity)

    def collide(self, obj):
        if self.rect.colliderect(obj.rect):
            if obj.collidable:
                self.col_objects.append(obj)
                if obj.type == PLAYER:
                    return
                if obj.rect.collidepoint(self.rect.midbottom):
                    self.yvel = 0
                    #save the object the object is on
                    self.on_object = obj.rect
        elif obj in self.col_objects:
            self.col_objects.remove(obj)

    def config_files(self, config, counter):
        config.set(self.name, 'file' + str(counter), self.files[counter])
        if counter >= len(self.files):
            counter += 1
            self.config_files(config, counter)

    def serialize(self, config):
        BaseObject.serialize(self, config)