示例#1
0
class Punchable(collision.PunchableGravityCollision):
    left_key = events.Keybind([pygame.K_a, pygame.K_LEFT])
    right_key = events.Keybind([pygame.K_d, pygame.K_RIGHT])
    up_key = events.Keybind([pygame.K_w, pygame.K_UP])
    down_key = events.Keybind([pygame.K_s, pygame.K_DOWN])

    def __init__(self, level, camera, width, height, x, y):
        super().__init__(level, width, height, 20, x, y)
        self.camera = camera
        self.collide_void = False

    def update(self):
        self._take_inputs()
        super().update()

    def _take_inputs(self):
        if self.left_key.is_held:
            if self.right_key.is_held:
                self.x_vel = 0
            else:
                self.x_vel = -5
        elif self.right_key.is_held:
            self.x_vel = 5
        else:
            self.x_vel = 0

        if self.up_key.is_held:
            self.y_vel = -5
        if self.down_key.is_held:
            self.y_vel = 5
示例#2
0
class TopDown(collision.Collision):
    left_key = events.Keybind([pygame.K_a, pygame.K_LEFT])
    right_key = events.Keybind([pygame.K_d, pygame.K_RIGHT])
    up_key = events.Keybind([pygame.K_w, pygame.K_UP])
    down_key = events.Keybind([pygame.K_s, pygame.K_DOWN])

    def __init__(self, level, camera, width, height, x, y):
        super().__init__(level, width, height, x, y)
        self.camera = camera
        self.collide_void = False

    def update(self):
        self._take_inputs()
        super().update()

    def _take_inputs(self):
        self.x_vel = 0
        self.y_vel = 0
        if self.left_key.is_held:
            self.x_vel -= 5
        if self.right_key.is_held:
            self.x_vel += 5
        if self.up_key.is_held:
            self.y_vel -= 5
        if self.down_key.is_held:
            self.y_vel += 5
示例#3
0
class Player(collision.PunchableGravityCollision):

    # Controls
    left_key = events.Keybind([pygame.K_LEFT])
    right_key = events.Keybind([pygame.K_RIGHT])
    jump_key = events.Keybind([pygame.K_z])
    respawn_key = events.Keybind([pygame.K_x])
    hard_respawn_key = events.Keybind([pygame.K_r])
    pause_key = events.Keybind([pygame.K_ESCAPE])

    # Physics/Gameplay constants
    TERMINAL_VELOCITY = 20.0

    COYOTE_TIME = 5
    JUMP_BUFFER = 5
    HORIZONTAL_PUNCH_BUFFER = 10

    MAX_HEALTH = 3
    JUMP_SPEED = 9
    MOVE_SPEED = 4.5
    MOVE_ACC = 0.8
    MOVE_DEC = 1.5

    HEALTH_SPACING = 5

    WIDTH = 20
    HEIGHT = 20

    # Graphics/Sprites
    RUN_LEFT = graphics.AnimColumn("run", 6, 2)
    RUN_LEFT.set_delay(2)
    RUN_LEFT_ID = 0
    RUN_RIGHT = graphics.flip_column(RUN_LEFT)
    RUN_RIGHT_ID = 1

    IDLE_LEFT = graphics.AnimColumn("idle", 4, 2)
    IDLE_LEFT.set_delays((60, 10, 45, 10))
    IDLE_LEFT_ID = 2
    IDLE_RIGHT = graphics.flip_column(IDLE_LEFT)
    IDLE_RIGHT_ID = 3

    TUMBLE_LEFT = graphics.AnimColumn("tumble", 8, 2)
    TUMBLE_LEFT.set_delay(3)
    TUMBLE_LEFT_ID = 4
    TUMBLE_RIGHT = graphics.flip_column(TUMBLE_LEFT)
    TUMBLE_RIGHT_ID = 5

    # 0xbeef is a joke.  Any other big number would work as well.
    DEAD_GROUNDED_LEFT = graphics.AnimColumn("dead_grounded", 1, 2)
    DEAD_GROUNDED_LEFT.set_delay(0xbeef)
    DEAD_GROUNDED_LEFT_ID = 6
    DEAD_GROUNDED_RIGHT = graphics.flip_column(DEAD_GROUNDED_LEFT)
    DEAD_GROUNDED_RIGHT_ID = 7

    DEAD_FALL_LEFT = graphics.AnimColumn("dead_fall", 12, 2)
    DEAD_FALL_LEFT.set_delay(0xbeef)
    DEAD_FALL_LEFT_ID = 8
    DEAD_FALL_RIGHT = graphics.flip_column(DEAD_FALL_LEFT)
    DEAD_FALL_RIGHT_ID = 9

    WALL_PUSH_LEFT = graphics.AnimColumn("wall_push", 1, 2)
    WALL_PUSH_LEFT.set_delay(0xbeef)
    WALL_PUSH_LEFT_ID = 10
    WALL_PUSH_RIGHT = graphics.flip_column(WALL_PUSH_LEFT)
    WALL_PUSH_RIGHT_ID = 11

    WALL_PUSH_JUMP_LEFT = graphics.AnimColumn("wall_push_jump", 7, 2)
    WALL_PUSH_JUMP_LEFT.set_delay(0xbeef)
    WALL_PUSH_JUMP_LEFT_ID = 12
    WALL_PUSH_JUMP_RIGHT = graphics.flip_column(WALL_PUSH_JUMP_LEFT)
    WALL_PUSH_JUMP_RIGHT_ID = 13

    WALL_PUSH_START_LEFT = graphics.AnimColumn("wall_push_start", 3, 2)
    WALL_PUSH_START_LEFT.set_delay(0xbeef)
    WALL_PUSH_START_LEFT_ID = 14
    WALL_PUSH_START_RIGHT = graphics.flip_column(WALL_PUSH_START_LEFT)
    WALL_PUSH_START_RIGHT_ID = 15

    WALL_PUSH_END_LEFT = graphics.AnimColumn("wall_push_end", 2, 2)
    WALL_PUSH_END_LEFT.set_delay(0xbeef)
    WALL_PUSH_END_LEFT_ID = 16
    WALL_PUSH_END_RIGHT = graphics.flip_column(WALL_PUSH_END_LEFT)
    WALL_PUSH_END_RIGHT_ID = 17

    WALL_PUSH_LAND_LEFT = graphics.AnimColumn("wall_push_land", 2, 2)
    WALL_PUSH_LAND_LEFT.set_delay(0xbeef)
    WALL_PUSH_LAND_LEFT_ID = 18
    WALL_PUSH_LAND_RIGHT = graphics.flip_column(WALL_PUSH_LAND_LEFT)
    WALL_PUSH_LAND_RIGHT_ID = 19

    JUMP_LEFT = graphics.AnimColumn("jump", 13, 2)
    JUMP_LEFT.set_delay(0xbeef)
    JUMP_LEFT_ID = 20
    JUMP_RIGHT = graphics.flip_column(JUMP_LEFT)
    JUMP_RIGHT_ID = 21

    LAND_LEFT = graphics.AnimColumn("land", 2, 2)
    LAND_LEFT.set_delay(0xbeef)
    LAND_LEFT_ID = 22
    LAND_RIGHT = graphics.flip_column(LAND_LEFT)
    LAND_RIGHT_ID = 23

    TURN_LEFT = graphics.AnimColumn("turn", 3, 2)
    TURN_LEFT.set_delay(0xbeef)
    TURN_LEFT_ID = 24
    TURN_RIGHT = graphics.flip_column(TURN_LEFT)
    TURN_RIGHT_ID = 25

    RUN_END_LEFT = graphics.AnimColumn("run_end", 4, 2)
    RUN_END_LEFT.set_delay(0xbeef)
    RUN_END_LEFT_ID = 26
    RUN_END_RIGHT = graphics.flip_column(RUN_END_LEFT)
    RUN_END_RIGHT_ID = 27

    ANIMSHEET = graphics.AnimSheet(
        (RUN_LEFT, RUN_RIGHT, IDLE_LEFT, IDLE_RIGHT, TUMBLE_LEFT, TUMBLE_RIGHT,
         DEAD_GROUNDED_LEFT, DEAD_GROUNDED_RIGHT, DEAD_FALL_LEFT,
         DEAD_FALL_RIGHT, WALL_PUSH_LEFT, WALL_PUSH_RIGHT, WALL_PUSH_JUMP_LEFT,
         WALL_PUSH_JUMP_RIGHT, WALL_PUSH_START_LEFT, WALL_PUSH_START_RIGHT,
         WALL_PUSH_END_LEFT, WALL_PUSH_END_RIGHT, WALL_PUSH_LAND_LEFT,
         WALL_PUSH_LAND_RIGHT, JUMP_LEFT, JUMP_RIGHT, LAND_LEFT, LAND_RIGHT,
         TURN_LEFT, TURN_RIGHT, RUN_END_LEFT, RUN_END_RIGHT))

    MAX_PUSH_FRAME = WALL_PUSH_START_LEFT.frame_count * 2
    MAX_UNPUSH_FRAME = WALL_PUSH_END_LEFT.frame_count * 2
    MAX_GROUND_FRAME = LAND_LEFT.frame_count * 2
    MAX_TURN_FRAME = TURN_LEFT.frame_count * 2
    MAX_RUN_END_FRAME = RUN_END_LEFT.frame_count * 2

    # Old unused heart graphics
    MIDDLE_HEART = graphics.AnimColumn("heart_middle", 2, 2)
    LEFT_HEART = graphics.AnimColumn("heart_left", 2, 2)
    RIGHT_HEART = graphics.flip_column(LEFT_HEART)
    MIDDLE_HEART.set_delays((62, 16))
    LEFT_HEART.set_delays((62, 16))
    RIGHT_HEART.set_delays((62, 16))

    HEART_SHEET = graphics.AnimSheet((MIDDLE_HEART, LEFT_HEART, RIGHT_HEART))

    MIDDLE_HEART_X = (const.SCRN_W - MIDDLE_HEART.frame_w) // 2
    HEART_X = [MIDDLE_HEART_X, MIDDLE_HEART_X - 50, MIDDLE_HEART_X + 50]
    HEART_Y = -3

    # Sounds
    RUN_SOUNDS = sound.load_numbers("run%i", 7)
    RUN_SOUNDS.set_volumes(0.3)

    WALL_PUSH_SOUNDS = sound.load_numbers("run%i", 7)
    WALL_PUSH_SOUNDS.set_volumes(0.35)

    REVIVE_SOUNDS = sound.load_numbers("revive%i", 3)
    REVIVE_SOUNDS.set_volumes(0.87)

    HIT_SOUNDS = sound.load_numbers("hit%i", 5)

    # ROOM_CHANGE_SOUNDS = sound.load_numbers("room_change%i", 1)

    JUMP_SOUNDS = sound.load_numbers("jump%i", 3)
    JUMP_SOUNDS.set_volumes(0.35)

    LAND_SOUNDS = sound.load_numbers("run%i", 7)
    LAND_SOUNDS.set_volumes(0.42)

    CHECKPOINT_CHANGE_SOUNDS = sound.load_numbers("checkpoint_change%i", 3)
    CHECKPOINT_CHANGE_SOUNDS.set_volumes(0.32)

    def __init__(self, level, camera):
        self.load_controls()

        x = grid.x_of(level.player_spawn.col)
        y = grid.y_of(level.player_spawn.row)
        super().__init__(level, self.WIDTH, self.HEIGHT,
                         self.TERMINAL_VELOCITY, x, y)
        self._health = self.MAX_HEALTH
        self.dead = False
        self.offscreen_direction = 0

        self.camera = camera

        self.tumble = False

        self.checkpoint = None

        self._coyote_timer = 0
        self._jump_buffer = 0
        self._horizontal_punch_buffer = 0
        self._horizontal_punch_direction = const.LEFT

        self.sprite = graphics.AnimInstance(self.ANIMSHEET)
        self.facing = const.LEFT

        self.heart_sprites = [
            graphics.AnimInstance(self.HEART_SHEET)
            for _ in range(self.MAX_HEALTH)
        ]
        for heart_sprite in range(1, self.MAX_HEALTH):
            self.heart_sprites[heart_sprite].set_anim(heart_sprite)

        self.hidden = False

        self.push_frames = 0
        self.unpush_frames = self.MAX_UNPUSH_FRAME

        self.turn_left_frames = self.MAX_TURN_FRAME
        self.turn_right_frames = self.MAX_TURN_FRAME

        self.ground_frames = 0
        self.run_end_frames = self.MAX_RUN_END_FRAME

        self._update_wall_push_success_flag = False

        self.prev_frame_checkpoint = None
        self.checkpoint_swapped = False

        self.just_died = False
        self.just_respawned = False

        self._prev_frame_x_vel = 0
        self._prev_frame_y_vel = 0

        self.dead_no_horizontal_frames = 0

    @property
    def respawn_x(self):
        if self.checkpoint:
            return grid.x_of(self.checkpoint.col)
        return self.hard_respawn_x

    @property
    def respawn_y(self):
        if self.checkpoint:
            return grid.y_of(self.checkpoint.row)
        return self.hard_respawn_y

    @property
    def hard_respawn_x(self):
        return grid.x_of(self.level.player_spawn.col)

    @property
    def hard_respawn_y(self):
        return grid.y_of(self.level.player_spawn.row)

    @property
    def health(self):
        return self._health

    @health.setter
    def health(self, value):
        self._health = value
        if self._health <= 0:
            self.dead = True
        else:
            self.dead = False

    def draw(self, surf, cam):
        self.sprite.update()

        if self.hidden:
            return

        x = self._gridbox.x - cam.x
        y = self._gridbox.y - cam.y
        self.sprite.draw_frame(surf, x, y)

    def update(self):
        self.collide_deathlock = not self.dead
        self.prev_frame_checkpoint = None
        self.checkpoint_swapped = False
        self.just_died = False
        self.just_respawned = False
        self._prev_frame_x_vel = self.x_vel + self.puncher_x_vel
        self._prev_frame_y_vel = self.y_vel
        self._update_timers()
        self._take_inputs()
        super().update()
        self._update_animation()
        self._collide_checkpoints()

        x_vel = self.x_vel + self.puncher_x_vel
        if -0.0001 < x_vel < 1.0 and self.dead:
            self.dead_no_horizontal_frames += 1
        else:
            self.dead_no_horizontal_frames = 0

    def _update_timers(self):
        if self.grounded:
            self._coyote_timer = self.COYOTE_TIME
        elif self._coyote_timer > 0:
            self._coyote_timer -= 1

        if self.jump_key.is_pressed and not self.dead:
            self._jump_buffer = self.JUMP_BUFFER
        elif self._jump_buffer > 0:
            self._jump_buffer -= 1

        if self._horizontal_punch_buffer > 0:
            self._horizontal_punch_buffer -= 1

    def _take_inputs(self):
        if not self.dead:
            if self.jump_key.is_pressed and self._coyote_timer > 0:
                self.jump()

            if self.grounded and self._jump_buffer > 0:
                self.jump()

            if self.left_key.is_held:
                self._move_left()

            elif self.right_key.is_held:
                self._move_right()

            # Decelerate when you stop moving
            else:
                self._stay_still()

            # Updates the added horizontal velocity from being punched
            self._puncher_x_vel_preservation()

        elif self.dead and self.grounded:
            self.x_vel = 0
            self.puncher_x_vel = 0

        if self.respawn_key.is_pressed:
            self.respawn()

    def _move_left(self):
        self.x_vel += -self.MOVE_ACC
        self.x_vel = max(self.x_vel, -self.MOVE_SPEED)

        if self.puncher_x_vel > 0:
            self.puncher_x_vel -= self.puncher_deceleration
            if self.puncher_x_vel < 0:
                self.puncher_x_vel = 0

    def _move_right(self):
        self.x_vel += self.MOVE_ACC
        self.x_vel = min(self.x_vel, self.MOVE_SPEED)

        if self.puncher_x_vel < 0:
            self.puncher_x_vel += self.puncher_deceleration
            if self.puncher_x_vel > 0:
                self.puncher_x_vel = 0

    def _puncher_x_vel_preservation(self):
        """Updates the added horizontal velocity from being punched"""
        x_vel = self.x_vel + self.puncher_x_vel
        if abs(x_vel) < self.MOVE_SPEED:
            if self.left_key.is_held or self.right_key.is_held:
                self.puncher_x_vel = 0

        if self._horizontal_punch_buffer:
            if self.left_key.is_held and self._horizontal_punch_direction == const.LEFT:
                self.puncher_x_vel = -self.PUNCHER_X_VEL
            elif self.right_key.is_held and self._horizontal_punch_direction == const.RIGHT:
                self.puncher_x_vel = self.PUNCHER_X_VEL

    def _stay_still(self):
        if self.x_vel < 0:
            self.x_vel += self.MOVE_DEC
            if self.x_vel > 0:
                self.x_vel = 0

        elif self.x_vel > 0:
            self.x_vel -= self.MOVE_DEC
            if self.x_vel < 0:
                self.x_vel = 0

    def jump(self):
        self._coyote_timer = 0
        self._jump_buffer = 0
        self.y_vel = -self.JUMP_SPEED
        self.JUMP_SOUNDS.play_random(0.3)
        self.tumble = False

    def respawn(self, make_sound=True):
        self.just_respawned = True
        self.health = self.MAX_HEALTH
        self.tumble = False
        self.x = self.respawn_x
        self.y = self.respawn_y

        self._horizontal_punch_buffer = 0

        if make_sound:
            self.REVIVE_SOUNDS.play_random(0.15)

    def hard_respawn(self, make_sound=True):
        self._coyote_timer = 0
        self._deactivate_checkpoint()
        self._stop_x()
        self._stop_y()
        self.respawn(make_sound)

    def _deactivate_checkpoint(self):
        self.checkpoint_swapped = True
        if self.checkpoint:
            self.prev_frame_checkpoint = self.checkpoint
            self.checkpoint.active = False
            self.checkpoint = None

    def _update_animation(self):
        if not self.dead:
            if not self.grounded:
                self._alive_air_anim()
            else:
                self.tumble = False

            self._update_wall_push_success_flag = False
            if self.left_key.is_held:
                self._move_left_anim()
            elif self.right_key.is_held:
                self._move_right_anim()
            else:
                self.push_frames = 0
                if self.grounded:
                    self._idle_anim()

            if self.grounded and self.ground_frames < self.MAX_GROUND_FRAME:
                self._landing_anim()

            # Plays running sound
            if self.grounded:
                if self.sprite.anim == self.RUN_LEFT_ID or self.sprite.anim == self.RUN_RIGHT_ID:
                    if self.sprite.frame == 0 and self.sprite.frame_delay == 0:
                        x_vel = self.x_vel + self.puncher_x_vel
                        if abs(x_vel) <= 4.6:
                            volume = random.random() / 8 + 0.375
                        else:
                            mult = abs(x_vel) / (self.PUNCHER_X_VEL +
                                                 self.MOVE_SPEED)
                            volume = mult * 0.25 + random.random() / 8 + 0.5
                        self.RUN_SOUNDS.play_random(volume)

        elif self.dead and self.grounded:
            self._dead_grounded_anim()

        elif self.dead:
            self._dead_air_anim()

        if self.grounded and self.y_vel == 0 and self._prev_frame_y_vel > 0:
            mult = abs(self._prev_frame_y_vel) / self.TERMINAL_VELOCITY
            volume = 0.2 + 0.7 * mult
            self.LAND_SOUNDS.play_random(volume)

    def _alive_air_anim(self):
        self.ground_frames = 0
        self.run_end_frames = self.MAX_RUN_END_FRAME

        if self.unpush_frames < self.MAX_UNPUSH_FRAME:
            self._unpush_anim()
            return

        if self.facing == const.LEFT:
            self.sprite.set_anim(self.JUMP_LEFT_ID)
        else:
            self.sprite.set_anim(self.JUMP_RIGHT_ID)

        if self.y_vel < -self.JUMP_SPEED:
            self.sprite.frame = 0
        elif self.y_vel < -self.JUMP_SPEED + 1.0:
            self.sprite.frame = 1
        elif self.y_vel < -self.JUMP_SPEED + 2.0:
            self.sprite.frame = 2
        elif self.y_vel < -self.JUMP_SPEED + 3.5:
            self.sprite.frame = 3
        elif self.y_vel < -self.JUMP_SPEED + 5:
            self.sprite.frame = 4
        elif self.y_vel < -self.JUMP_SPEED + 6.25:
            self.sprite.frame = 5
        elif self.y_vel < -self.JUMP_SPEED + 7.5:
            self.sprite.frame = 6
        elif self.y_vel < 0:
            self.sprite.frame = 7
        elif self.y_vel < 2.5:
            self.sprite.frame = 8
        elif self.y_vel < 10.0:
            self.sprite.frame = 9
        elif self.y_vel < 14.5:
            self.sprite.frame = 10
        else:
            if self.y_vel % 2.6 < 1.3:
                self.sprite.frame = 11
            else:
                self.sprite.frame = 12

    def _move_left_anim(self):
        self.turn_right_frames = 0
        self.run_end_frames = 0

        if self.grounded:
            if self.turn_left_frames < self.MAX_TURN_FRAME:
                self._turn_left_anim()
            else:
                self.sprite.set_anim(self.RUN_LEFT_ID)

        self.facing = const.LEFT
        self._update_wall_push(const.LEFT)

    def _move_right_anim(self):
        self.turn_left_frames = 0
        self.run_end_frames = 0

        if self.grounded:
            if self.turn_right_frames < self.MAX_TURN_FRAME:
                self._turn_right_anim()
            else:
                self.sprite.set_anim(self.RUN_RIGHT_ID)

        self.facing = const.RIGHT
        self._update_wall_push(const.RIGHT)

    def _idle_anim(self):
        if self.facing == const.LEFT:
            if self.run_end_frames < self.MAX_RUN_END_FRAME:
                self._run_end_anim()
            else:
                self.sprite.set_anim(self.IDLE_LEFT_ID)
        elif self.facing == const.RIGHT:
            if self.run_end_frames < self.MAX_RUN_END_FRAME:
                self._run_end_anim()
            else:
                self.sprite.set_anim(self.IDLE_RIGHT_ID)

        if self.unpush_frames < self.MAX_UNPUSH_FRAME:
            self._unpush_anim(
            )  # Priority over other animations in this method

    def _unpush_anim(self):
        if self.facing == const.LEFT:
            self.sprite.set_anim(self.WALL_PUSH_END_LEFT_ID)
            self.run_end_frames = self.MAX_RUN_END_FRAME
        if self.facing == const.RIGHT:
            self.sprite.set_anim(self.WALL_PUSH_END_RIGHT_ID)
            self.run_end_frames = self.MAX_RUN_END_FRAME

        self.sprite.frame = self.unpush_frames // 2
        self.unpush_frames += 1

    def _landing_anim(self):
        if self.facing == const.LEFT:
            if self._update_wall_push_success_flag:
                self.sprite.set_anim(self.WALL_PUSH_LAND_LEFT_ID)
            else:
                self.sprite.set_anim(self.LAND_LEFT_ID)
        else:
            if self._update_wall_push_success_flag:
                self.sprite.set_anim(self.WALL_PUSH_LAND_RIGHT_ID)
            else:
                self.sprite.set_anim(self.LAND_RIGHT_ID)

        self.sprite.frame = self.ground_frames // 2
        self.ground_frames += 1

    def _dead_grounded_anim(self):
        if self.facing == const.LEFT:
            self.sprite.set_anim(self.DEAD_GROUNDED_LEFT_ID)
        elif self.facing == const.RIGHT:
            self.sprite.set_anim(self.DEAD_GROUNDED_RIGHT_ID)

    def _dead_air_anim(self):
        if self.facing == const.LEFT:
            self.sprite.set_anim(self.DEAD_FALL_LEFT_ID)
        else:
            self.sprite.set_anim(self.DEAD_FALL_RIGHT_ID)

        if self.y_vel < -self.JUMP_SPEED:
            self.sprite.frame = 0
        elif self.y_vel < -self.JUMP_SPEED + 3.0:
            self.sprite.frame = 1
        elif self.y_vel < -self.JUMP_SPEED + 5.5:
            self.sprite.frame = 2
        elif self.y_vel < -self.JUMP_SPEED + 7.0:
            self.sprite.frame = 3
        elif self.y_vel < -self.JUMP_SPEED + 8.0:
            self.sprite.frame = 4
        elif self.y_vel < 1.5:
            self.sprite.frame = 5
        elif self.y_vel < 2.0:
            self.sprite.frame = 6
        elif self.y_vel < 4.0:
            self.sprite.frame = 7
        elif self.y_vel < 7.0:
            self.sprite.frame = 7
        elif self.y_vel < 12.0:
            self.sprite.frame = 8
        else:
            self.sprite.frame_delay += 1
            if self.sprite.frame_delay > 1:
                self.sprite.frame_delay = 0

                if self.sprite.frame == 5:
                    self.sprite.frame = 9
                else:
                    self.sprite.frame = 10

    def _run_end_anim(self):
        if self.facing == const.LEFT:
            self.sprite.set_anim(self.RUN_END_LEFT_ID)
        else:
            self.sprite.set_anim(self.RUN_END_RIGHT_ID)
        self.sprite.frame = self.run_end_frames // 2

        self.run_end_frames += 1

    def _turn_left_anim(self):
        self.sprite.set_anim(self.TURN_LEFT_ID)
        self.sprite.frame = self.turn_left_frames // 2
        self.turn_left_frames += 1

    def _turn_right_anim(self):
        self.sprite.set_anim(self.TURN_RIGHT_ID)
        self.sprite.frame = self.turn_right_frames // 2
        self.turn_right_frames += 1

    def _update_wall_push(self, direction):
        top_y = self.y
        bottom_y = top_y + self.HEIGHT - 1

        if direction == const.LEFT:
            x = self.x - 1
        elif direction == const.RIGHT:
            x = self.x + self.WIDTH
        else:
            return

        if self.level.collide_vert(x, top_y, bottom_y, not self.dead):
            self.unpush_frames = 0
            self._update_wall_push_success_flag = True

            if self.grounded:
                if direction == const.LEFT:
                    if self.push_frames < self.MAX_PUSH_FRAME:
                        self.sprite.set_anim(self.WALL_PUSH_START_LEFT_ID)
                    else:
                        self.sprite.set_anim(self.WALL_PUSH_LEFT_ID)
                elif direction == const.RIGHT:
                    if self.push_frames < self.MAX_PUSH_FRAME:
                        self.sprite.set_anim(self.WALL_PUSH_START_RIGHT_ID)
                    else:
                        self.sprite.set_anim(self.WALL_PUSH_RIGHT_ID)

                if self.push_frames < self.MAX_PUSH_FRAME:
                    self.sprite.frame = self.push_frames // 2
                    self.push_frames += 1
            else:
                if direction == const.LEFT:
                    if self.push_frames < self.MAX_PUSH_FRAME:
                        self.sprite.set_anim(self.WALL_PUSH_START_LEFT_ID)
                    else:
                        self.sprite.set_anim(self.WALL_PUSH_JUMP_LEFT_ID)
                elif direction == const.RIGHT:
                    if self.push_frames < self.MAX_PUSH_FRAME:
                        self.sprite.set_anim(self.WALL_PUSH_START_RIGHT_ID)
                    else:
                        self.sprite.set_anim(self.WALL_PUSH_JUMP_RIGHT_ID)

                if self.push_frames < self.MAX_PUSH_FRAME:
                    self.sprite.frame = self.push_frames // 2
                    self.push_frames += 1
                else:
                    if self.y_vel < -self.JUMP_SPEED + 0.5:
                        self.sprite.frame = 0
                    elif self.y_vel < -self.JUMP_SPEED + 1.0:
                        self.sprite.frame = 1
                    elif self.y_vel < -self.JUMP_SPEED + 3.0:
                        self.sprite.frame = 2
                    elif self.y_vel < -self.JUMP_SPEED + 6.0:
                        self.sprite.frame = 3
                    elif self.y_vel < 10.0:
                        self.sprite.frame = 4
                    elif self.y_vel < 14.5:
                        self.sprite.frame = 5
                    else:
                        self.sprite.frame = 6

            if self.push_frames == 1:
                if abs(self._prev_frame_x_vel) < 4.6:
                    volume = 0.45
                else:
                    volume = abs(self._prev_frame_x_vel) / 20 + 0.5
                self.WALL_PUSH_SOUNDS.play_random(volume)

        else:
            self.push_frames = 0
            self.unpush_frames = self.MAX_UNPUSH_FRAME
            self._update_wall_push_success_flag = False

    def _activate_punch_zone(self, col, row):
        # Exactly the same as the parent method, except _horizontal_punch_buffer
        # is updated when punched horizontally
        tile = self.level.get_tile(grid.PunchZone, col, row)
        if tile.direction == const.LEFT:
            self._get_hit()
            punchers.add(col, row, const.LEFT)
            self.puncher_x_vel = -self.PUNCHER_X_VEL

            if self.x_vel > 0:
                self.x_vel = 0

            self._horizontal_punch_buffer = self.HORIZONTAL_PUNCH_BUFFER
            self._horizontal_punch_direction = const.LEFT

        elif tile.direction == const.UP:
            self._get_hit()
            punchers.add(col, row, const.UP)
            self.y_vel = -self.PUNCHER_UP_VEL

        elif tile.direction == const.RIGHT:
            self._get_hit()
            punchers.add(col, row, const.RIGHT)
            self.puncher_x_vel = self.PUNCHER_X_VEL

            if self.x_vel < 0:
                self.x_vel = 0

            self._horizontal_punch_buffer = self.HORIZONTAL_PUNCH_BUFFER
            self._horizontal_punch_direction = const.RIGHT

        elif tile.direction == const.DOWN:
            self._get_hit()
            punchers.add(col, row, const.DOWN)
            self.y_vel = self.PUNCHER_DOWN_VEL

    def _get_hit(self):
        super()._get_hit()
        self.tumble = True
        self.health -= 1
        self.camera.shake(6, 1)
        if self.health == 0:
            self.just_died = True

    def _collide_checkpoints(self):
        col = grid.col_at(self.center_x)
        row = grid.row_at(self.center_y)
        if self.level.has_tile(grid.CheckpointRay, col, row):
            ray = self.level.get_tile(grid.CheckpointRay, col, row)

            if not (ray.checkpoint is self.checkpoint):
                self._deactivate_checkpoint()
                ray.checkpoint.active = True
                self.checkpoint = ray.checkpoint
                self.CHECKPOINT_CHANGE_SOUNDS.play_random()

    def _update_puncher_vel(self):
        if self.grounded:
            if self.puncher_x_vel < 0 and not self.left_key.is_held:
                self.puncher_x_vel += self.puncher_deceleration
                if self.puncher_x_vel > 0:
                    self.puncher_x_vel = 0

            elif self.puncher_x_vel > 0 and not self.right_key.is_held:
                self.puncher_x_vel -= self.puncher_deceleration
                if self.puncher_x_vel < 0:
                    self.puncher_x_vel = 0

    def load_controls(self):
        with open(os.path.join("data", "controls.txt")) as file:
            line = file.readline()
        controls = [int(control) for control in line.split()]

        self.left_key.list = [controls[0]]
        self.right_key.list = [controls[1]]
        self.jump_key.list = [controls[2]]
        self.respawn_key.list = [controls[3]]
        self.hard_respawn_key.list = [controls[4]]
        self.pause_key.list = [controls[5]]

    @property
    def touching_goal(self):
        col = grid.col_at(self.center_x)
        row = grid.row_at(self.center_y)
        return self.level.has_tile(grid.PlayerGoalZone, col, row)
示例#4
0
main_cam.base_x = 0
main_cam.base_y = 0

player = entities.player.Player(sequence.current, main_cam)

entity_handler = entities.handler.Handler()
entity_handler.list = [player]

static_level_surf = pygame.Surface((const.SCRN_W, const.SCRN_H))
static_level_surf.set_colorkey(const.TRANSPARENT)
draw_background(static_level_surf)
sequence.current.draw_static(static_level_surf, main_cam)

# sound.play_music()

editor_key = events.Keybind([pygame.K_e])

main_menu = menus.MainMenu()
pause_menu = menus.PauseMenu(player)
splash_screen = splash.SplashScreen()
credits_screen = menus.Credits()

# If we're not on the first level, change menu text from "start" to "continue"
if sequence.level_num != -1:
    main_menu.start_action = "continue"

GAME = 0
EDITOR = 1
MENU = 2
SPLASH_SCREEN = 3
PAUSE = 4
示例#5
0
class Editor:
    PLACE = 0
    RECT = 1

    left_key = events.Keybind([pygame.K_a])
    right_key = events.Keybind([pygame.K_d])
    up_key = events.Keybind([pygame.K_w])
    down_key = events.Keybind([pygame.K_s])
    save_key = events.Keybind([pygame.K_u])

    place_text_key = events.Keybind([pygame.K_t])

    shift_left_key = events.Keybind([pygame.K_LEFT])
    shift_right_key = events.Keybind([pygame.K_RIGHT])
    shift_up_key = events.Keybind([pygame.K_UP])
    shift_down_key = events.Keybind([pygame.K_DOWN])

    def __init__(self, sequence):
        self._sequence = sequence
        self.mode = self.PLACE
        self._direction = const.LEFT
        self._tile = None

        self.rect_start_col = 0
        self.rect_start_row = 0

    @property
    def level(self):
        return self._sequence.current

    @property
    def _mode_string(self):
        if self.mode == self.PLACE:
            return "PLACE"
        elif self.mode == self.RECT:
            return "RECT"

    def _input_direction(self):
        if self.left_key.is_pressed:
            self._direction = const.LEFT
        elif self.right_key.is_pressed:
            self._direction = const.RIGHT
        elif self.up_key.is_pressed:
            self._direction = const.UP
        elif self.down_key.is_pressed:
            self._direction = const.DOWN

    def _input_shift_level(self):
        if self.shift_left_key.is_pressed:
            self.level.shift_left()
        elif self.shift_right_key.is_pressed:
            self.level.shift_right()
        elif self.shift_up_key.is_pressed:
            self.level.shift_up()
        elif self.shift_down_key.is_pressed:
            self.level.shift_down()

    def _input_selected_tile(self):
        for key in events.keys.pressed_keys:
            if key in events.number_keys:
                number = int(pygame.key.name(key)) - 1
                if 0 <= number < len(selections):
                    self._tile = selections[number]

    def _input_place_block(self):
        if events.mouse.held:
            col = mouse_col()
            row = mouse_row()
            self.level.clear_point(col, row)
            if self._tile in basic_tiles:
                self.level.add_tile(col, row, self._tile())
            elif self._tile == grid.PunchBox:
                self.level.add_tile(col, row, self._tile(self._direction))
            elif self._tile == grid.Checkpoint:
                self.level.add_checkpoint(col, row, self._direction)
            elif self._tile == grid.PlayerSpawn:
                self.level.move_player_spawn(col, row)
            elif self._tile == grid.PlayerGoal:
                self.level.move_player_goal(col, row)

    def _input_switch_mode(self):
        if pygame.K_TAB in events.keys.pressed_keys:
            if self.mode == self.PLACE:
                self.mode = self.RECT
            elif self.mode == self.RECT:
                self.mode = self.PLACE

    def _input_place_rect(self):
        if events.mouse.clicked:
            self.rect_start_col = mouse_col()
            self.rect_start_row = mouse_row()
        if events.mouse.released:
            current_col = mouse_col()
            current_row = mouse_row()
            left = min(self.rect_start_col, current_col)
            top = min(self.rect_start_row, current_row)
            right = max(self.rect_start_col, current_col)
            bottom = max(self.rect_start_row, current_row)
            width = right - left + 1
            height = bottom - top + 1

            self.level.clear_rect(left, top, width, height)
            if self._tile in basic_tiles:
                self.level.add_rect(left, top, width, height, self._tile)
            elif self._tile == grid.PunchBox:
                constructor = lambda: grid.PunchBox(self._direction)
                self.level.add_rect(left, top, width, height, constructor)

            # These tiles shouldn't/can't be placed in a rect, so they are
            # placed as a single tile at the mouse's current position instead
            elif self._tile == grid.Checkpoint:
                tile = grid.Checkpoint(self._direction, current_col,
                                       current_row)
                self.level.add_tile(current_col, current_row, tile)
            elif self._tile == grid.PlayerSpawn:
                self.level.move_player_spawn(current_col, current_row)
            elif self._tile == grid.PlayerGoal:
                self.level.move_player_goal(current_col, current_row)

    def _input_place_text(self):
        if self._direction == const.LEFT or self._direction == const.UP:
            self.level.heart_direction = const.UP
        else:
            self.level.heart_direction = const.DOWN
        self.level.text_x = events.mouse.position[0]
        self.level.text_y = events.mouse.position[1]

    def _take_inputs(self):
        self._input_direction()
        self._input_shift_level()
        self._input_selected_tile()
        self._input_switch_mode()
        if self.mode == self.PLACE:
            self._input_place_block()
        elif self.mode == self.RECT:
            self._input_place_rect()

        if self.place_text_key.is_held:
            self._input_place_text()

        if self.save_key.is_pressed:
            self.level.save()

    def update(self):
        self._take_inputs()

    def _draw_selections(self, surf):
        mode = self._mode_string
        direction = const.direction_string(self._direction)
        if self._tile:
            tile = str(self._tile.__name__)
        else:
            tile = "Erase"
        string = "%-6s %-6s %s" % (mode, direction, tile)

        text = debug.TAHOMA_LARGE.render(string, False, const.WHITE,
                                         const.BLACK)
        surf.blit(text, (10, 10))

    def _draw_rect_marker(self, surf):
        x = grid.x_of(self.rect_start_col)
        y = grid.y_of(self.rect_start_row)
        rect = (x, y, grid.TILE_W, grid.TILE_H)
        pygame.draw.rect(surf, const.MAGENTA, rect)

    def _draw_mouse_marker(self, surf):
        x = grid.x_of(mouse_col())
        y = grid.y_of(mouse_row())
        rect = (x, y, grid.TILE_W, grid.TILE_H)
        pygame.draw.rect(surf, const.MAGENTA, rect)

    def draw(self, surf):
        self._draw_mouse_marker(surf)
        if self.mode == self.RECT and events.mouse.held:
            self._draw_rect_marker(surf)
        self._draw_selections(surf)