class NextLevel:
    audio = 4

    def __init__(self, screen, score_controller, transition_time=5000):
        self.screen = screen
        self.score_controller = score_controller
        self.sound = Sounds(['pacman-beginning.wav'],
                            keys=['transition'],
                            channel=NextLevel.audio,
                            volume=0.6)
        self.font = pygame.font.Font('fonts/LuckiestGuy-Regular.ttf', 32)
        self.ready_msg = self.font.render('Get Ready!', True, Scoreboard.white)
        self.ready_msg_rect = self.ready_msg.get_rect()
        ready_pos = screen.get_width() // 2, int(screen.get_height() * 0.65)
        self.ready_msg_rect.centerx, self.ready_msg_rect.centery = ready_pos
        self.level_msg = None
        self.level_msg_rect = None
        self.transition_time = transition_time
        self.transition_begin = None
        self.transition_show = False

    def prep_level_msg(self):
        text = 'level ' + str(self.score_controller.level)
        self.level_msg = self.font.render(text, True, Scoreboard.white)
        self.level_msg_rect = self.level_msg.get_rect()
        level_pos = self.screen.get_width() // 2, self.screen.get_height() // 2
        self.level_msg_rect.centerx, self.level_msg_rect.centery = level_pos

    def set_show_transition(self):
        self.prep_level_msg()
        self.transition_begin = pygame.time.get_ticks()
        self.transition_show = True
        self.sound.play('transition')

    def draw(self):
        if abs(self.transition_begin -
               pygame.time.get_ticks()) > self.transition_time:
            self.transition_show = False
        else:
            self.screen.fill((0, 0, 0))
            self.screen.blit(self.level_msg, self.level_msg_rect)
            if abs(self.transition_begin -
                   pygame.time.get_ticks()) >= self.transition_time // 2:
                self.screen.blit(self.ready_msg, self.ready_msg_rect)
Beispiel #2
0
class Pacman(Sprite):
    audio = 0
    yellow = (255, 255, 0)

    def __init__(self, screen, maze):
        super().__init__()
        self.screen = screen
        self.maze = maze
        self.dead = False
        self.direction = None
        self.event_map = {
            pygame.KEYDOWN: self.move,
            pygame.KEYUP: self.reset_movement
        }
        self.input_map = {
            pygame.K_UP: self.move_up,
            pygame.K_LEFT: self.move_left,
            pygame.K_DOWN: self.move_down,
            pygame.K_RIGHT: self.move_right,
            pygame.K_q: self.blue_portal,
            pygame.K_w: self.orange_portal
        }

        self.sound_manager = Sounds(sound_files=[
            'pacman-pellet-eat.wav', 'pacman-fruit-eat.wav',
            'pacman-killed.wav', 'pacman-portal.wav'
        ],
                                    keys=['eat', 'fruit', 'dead', 'portal'],
                                    channel=Pacman.audio)

        self.death_frames = ImageRect('pacman-death.png',
                                      sheet=True,
                                      pos_offsets=[(0, 0, 32, 32),
                                                   (32, 0, 32, 32),
                                                   (0, 32, 32, 32),
                                                   (32, 32, 32, 32),
                                                   (0, 64, 32, 32),
                                                   (32, 64, 32, 32)],
                                      resize=(self.maze.block_size,
                                              self.maze.block_size),
                                      animation_delay=150,
                                      repeat=False)

        self.pacmanx = ImageRect('pacman-horiz.png',
                                 sheet=True,
                                 pos_offsets=[(0, 0, 32, 32), (32, 0, 32, 32),
                                              (0, 32, 32, 32),
                                              (32, 32, 32, 32),
                                              (0, 64, 32, 32)],
                                 resize=(self.maze.block_size,
                                         self.maze.block_size),
                                 reversible=True)
        self.pacmany = ImageRect('pacman-vert.png',
                                 sheet=True,
                                 pos_offsets=[(0, 0, 32, 32), (32, 0, 32, 32),
                                              (0, 32, 32, 32),
                                              (32, 32, 32, 32),
                                              (0, 64, 32, 32)],
                                 resize=(self.maze.block_size,
                                         self.maze.block_size),
                                 reversible=True)
        self.spawn_set = self.maze.player_spawn[1]
        self.flip_mo = {'use_horiz': True, 'h_flip': False, 'v_flip': False}
        self.movement = False
        self.image, self.rect = self.pacmanx.get_image()
        self.portals = PortalController(screen, self, maze)

    def blue_portal(self):
        self.portals.fire_blue()

    def orange_portal(self):
        self.portals.fire_orange()

    def respawn(self):
        self.dead = False
        self.image, _ = self.pacmanx.get_image()
        self.death_frames.image_index = 0

    def eat(self):
        score = 0
        fruit_count = 0
        ppellet = None
        collision = pygame.sprite.spritecollideany(self, self.maze.pellets)
        if collision:
            collision.kill()
            score += 10
            self.sound_manager.play('eat')
        collision = pygame.sprite.spritecollideany(self, self.maze.fruits)
        if collision:
            collision.kill()
            score += (100 + (fruit_count * 200))
            fruit_count += 1
            self.sound_manager.play('fruit')
        collision = pygame.sprite.spritecollideany(self,
                                                   self.maze.power_pellets)
        if collision:
            collision.kill()
            score += 50
            ppellet = True
            self.sound_manager.play('eat')
        return score, fruit_count, ppellet

    def reset(self):
        self.rect.centerx, self.rect.centery = self.spawn_set

    def change_direction(self, event):
        if event.key in (pygame.K_UP, pygame.K_DOWN, pygame.K_LEFT,
                         pygame.K_RIGHT):
            self.moving = False

    def get_nearest_col(self):
        return (self.rect.x -
                (self.screen.get_width() // 5)) // self.maze.block_size

    def get_nearest_row(self):
        return (self.rect.y -
                (self.screen.get_height() // 12)) // self.maze.block_size

    def set_death(self):
        self.sound_manager.play('dead')
        self.dead = True
        self.image, _ = self.death_frames.get_image()

    def reset_portals(self):
        self.portals.clear_portals()

    def move(self, event):
        if event.key in self.input_map:
            self.input_map[event.key]()

    def move_up(self):
        if self.direction != 'u':
            self.direction = 'u'
            if self.flip_mo['v_flip']:
                self.pacmany.flip(False, True)
                self.flip_mo['v_flip'] = False
            self.flip_mo['use_horiz'] = False
        self.moving = True

    def move_left(self):
        if self.direction != 'l':
            self.direction = 'l'
            if not self.flip_mo['h_flip']:
                self.pacmanx.flip()
                self.flip_mo['h_flip'] = True
            self.flip_mo['use_horiz'] = True
        self.moving = True

    def move_down(self):
        if self.direction != 'd':
            self.direction = 'd'
            if not self.flip_mo['v_flip']:
                self.pacmany.flip(x_bool=False, y_bool=True)
                self.flip_mo['v_flip'] = True
            self.flip_mo['use_horiz'] = False
        self.movement = True

    def move_right(self):
        if self.direction != 'r':
            self.direction = 'r'
            if self.flip_mo['h_flip']:
                self.pacmanx.flip()
                self.flip_mo['h_flip'] = False
            self.flip_mo['use_horiz'] = True
        self.movement = True

    def reset_movement(self, event):
        if event.key in (pygame.K_UP, pygame.K_DOWN, pygame.K_LEFT,
                         pygame.K_RIGHT):
            self.movement = False

    def blit(self):
        self.portals.blit()
        self.screen.blit(self.image, self.rect)
Beispiel #3
0
class PortalController:
    PORTAL_AUDIO_CHANNEL = 3

    def __init__(self, screen, user, maze):
        self.screen = screen
        self.maze = maze
        self.user = user
        self.sounds = Sounds(
            sound_files=['portal-open.wav', 'portal-travel.wav'],
            keys=['open', 'travel'],
            channel=PortalController.PORTAL_AUDIO_CHANNEL)
        self.blue_portal = pygame.sprite.GroupSingle(
        )  # portals as GroupSingle, which only allows one per group
        self.blue_projectile = None
        self.orange_portal = pygame.sprite.GroupSingle()
        self.orange_projectile = None
        self.portal_directions = {'l': 'r', 'r': 'l', 'u': 'd', 'd': 'u'}

    def clear_portals(self):
        self.blue_portal.empty()
        self.orange_portal.empty()
        self.blue_projectile = None
        self.orange_projectile = None

    def fire_blue(self):
        if self.user.direction is not None:
            self.blue_projectile = PortalProjectile(
                screen=self.screen,
                source=self.user,
                direction=self.user.direction,
                p_type=Portal.P_TYPE_1)

    def fire_orange(self):
        if self.user.direction is not None:
            self.orange_projectile = PortalProjectile(
                screen=self.screen,
                source=self.user,
                direction=self.user.direction,
                p_type=Portal.P_TYPE_2)

    def create_blue(self, x, y, direction):
        if self.blue_portal:
            old_x, old_y = self.blue_portal.sprite.rect.x, self.blue_portal.sprite.rect.y
            self.maze.maze_blocks.add(
                Block(old_x, old_y, self.maze.block_size, self.maze.block_size,
                      self.maze.block_image))
        self.blue_portal.add(
            Portal(screen=self.screen,
                   x=x,
                   y=y,
                   direction=direction,
                   maze=self.maze,
                   p_type=Portal.P_TYPE_1))

    def create_orange(self, x, y, direction):
        if self.orange_portal:
            old_x, old_y = self.orange_portal.sprite.rect.x, self.orange_portal.sprite.rect.y
            self.maze.maze_blocks.add(
                Block(old_x, old_y, self.maze.block_size, self.maze.block_size,
                      self.maze.block_image))
        self.orange_portal.add(
            Portal(screen=self.screen,
                   x=x,
                   y=y,
                   direction=direction,
                   maze=self.maze,
                   p_type=Portal.P_TYPE_2))

    def update(self):
        self.blue_portal.update()
        self.orange_portal.update()
        if self.blue_projectile:
            self.blue_projectile.update()
            if pygame.sprite.spritecollideany(self.blue_projectile, self.blue_portal) or \
                    pygame.sprite.spritecollideany(self.blue_projectile, self.orange_portal):
                self.blue_projectile = None
                return
            collision = pygame.sprite.spritecollideany(self.blue_projectile,
                                                       self.maze.maze_blocks)
            if collision:
                x, y = collision.rect.x, collision.rect.y
                collision.kill()
                direction = self.portal_directions[
                    self.blue_projectile.direction]
                self.blue_projectile = None
                self.create_blue(x, y, direction)
                self.sounds.play('open')
            elif self.blue_projectile.is_off_screen():
                self.blue_projectile = None
        if self.orange_projectile:
            self.orange_projectile.update()
            if pygame.sprite.spritecollideany(self.orange_projectile, self.blue_portal) or \
                    pygame.sprite.spritecollideany(self.orange_projectile, self.orange_portal):
                self.orange_projectile = None
                return
            collision = pygame.sprite.spritecollideany(self.orange_projectile,
                                                       self.maze.maze_blocks)
            if collision:
                x, y = collision.rect.x, collision.rect.y
                collision.kill()
                direction = self.portal_directions[
                    self.orange_projectile.direction]
                self.orange_projectile = None
                self.create_orange(x, y, direction)
                self.sounds.play('open')
            elif self.orange_projectile.is_off_screen():
                self.orange_projectile = None

    def portables_usable(self):
        return self.blue_portal and self.orange_portal

    def collide_portals(self, other):
        return pygame.sprite.spritecollideany(other, self.blue_portal) or \
            pygame.sprite.spritecollideany(other, self.orange_portal)

    def check_portals(self, *args):
        for arg in args:
            if pygame.sprite.spritecollideany(
                    arg, self.blue_portal) and self.orange_portal:
                i, j = self.orange_portal.sprite.get_nearest_row(
                ), self.orange_portal.sprite.get_nearest_col()
                if self.orange_portal.sprite.direction == 'l':
                    j -= 1
                elif self.orange_portal.sprite.direction == 'r':
                    j += 1
                elif self.orange_portal.sprite.direction == 'u':
                    i -= 1
                else:
                    i += 1
                x, y = ((self.screen.get_width()) // 5 + (j * self.maze.block_size)), \
                       ((self.screen.get_height()) // 12 + (i * self.maze.block_size))
                arg.rect.x, arg.rect.y = x, y
                self.sounds.play('travel')
            elif pygame.sprite.spritecollideany(
                    arg, self.orange_portal) and self.blue_portal:
                i, j = self.blue_portal.sprite.get_nearest_row(
                ), self.blue_portal.sprite.get_nearest_col()
                if self.blue_portal.sprite.direction == 'l':
                    j -= 1
                elif self.blue_portal.sprite.direction == 'r':
                    j += 1
                elif self.blue_portal.sprite.direction == 'u':
                    i -= 1
                else:
                    i += 1
                x, y = ((self.screen.get_width() // 5) + (j * self.maze.block_size)), \
                       ((self.screen.get_height() // 12) + (i * self.maze.block_size))
                arg.rect.x, arg.rect.y = x, y
                self.sounds.play('travel')

    def blit(self):
        if self.blue_projectile:
            self.blue_projectile.blit()
        if self.orange_projectile:
            self.orange_projectile.blit()
        if self.blue_portal:
            self.blue_portal.sprite.blit()
        if self.orange_portal:
            self.orange_portal.sprite.blit()
Beispiel #4
0
class Game:
    def __init__(self, modes):
        GPIO.setmode(
            GPIO.BCM)  #set up to use gpio port numbers (instead of pin #s)

        self.buttons = Buttons()
        self.optos = Optos()
        self.lights = Lights()
        self.outlets = Outlets()
        self.sounds = Sounds()
        self.clock = Countdown(12)

        self.modes = modes
        self.last_time = time.localtime()

    def cleanup(self):
        self.lights.turn_off_all()
        GPIO.cleanup()  #clean exit of GPIO ports

    def time(self):
        return int(round(time.time() * 1000))

    def find_mode(self, name):
        return self.modes[name](self, name)

    def run(self, game_mode, state=None):
        start_state = game_mode.enter()
        state = state or start_state
        try:
            timer_start = self.time()
            while state:
                start_time = self.time()

                print("{}:{}".format(game_mode, state))
                new_state = game_mode.enter_state(state)
                if isinstance(new_state, Exit):
                    return new_state

                next_time = start_time + new_state.delay * 1000

                next_state = None
                while not next_state:
                    now = self.time()
                    if now > next_time:
                        next_state = new_state
                        next_state.delay = 0
                        break

                    state.timer = (now - timer_start) / 1000.0

                    ret = self.idle(game_mode)
                    if isinstance(ret, Exit):
                        return ret

                    ret = game_mode.idle(state)
                    if isinstance(ret, Exit):
                        return ret
                    if isinstance(ret, State):
                        next_state = ret

                if next_state.state != state.state:
                    game_mode.exit_state(state)
                    timer_start = now

                state = next_state

        finally:
            game_mode.exit()

    def idle(self, game_mode):
        # This is global stuff

        if self.buttons.switched(Button.BACK):
            self.sounds.play("beep")
            if self.buttons.back:
                return Exit("racing")
            else:
                self.sounds.play("gurble")
                return Exit("quiet")

        if self.buttons.check((Button.GREEN, Button.RED, Button.YELLOW)):
            return Exit("songs")

        if game_mode.name == "songs":
            if self.buttons.black:
                self.sounds.volume_up()
                self.sounds.play("beep")
            if self.buttons.blue:
                self.sounds.volume_down()
                self.sounds.play("beep")

        # Put in stuff for time check & volume changes, e.g.
        # if it was before 7am and now it's after 7am
        # then return Exit("songs")
        if self.check_time(0):  # At midnight
            self.sounds.set_volume(0.7)

        if self.check_time(2):  # At 2am
            self.sounds.set_volume(0.2)

        if self.check_time(4):  # At 4am
            return Exit("quiet")

        if self.check_time(8):  # At 8am (choose wisely)
            self.sounds.set_volume(1)
            return Exit("songs")

        self.last_time = time.localtime()

    def play(self, name):
        game_mode = self.find_mode(name)
        state = None
        print("Starting {}".format(game_mode))

        while True:
            result = self.run(game_mode, state)
            print("{} exited: {}".format(game_mode, result.value))
            game_mode, state = self.mode_exited(game_mode, result.value)
            print("Switching to {}".format(game_mode))

    def mode_exited(self, game_mode, value):
        return self.find_mode(value), None

    def check_time(self, hr):
        now = time.localtime()
        if hr == 0:
            return self.last_time.tm_hour > 20
        return self.last_time.tm_hour < hr and now.tm_hour == hr