def __init__(self, win, win_scale, user_id, icons=None): """ Class for settings menu. At the moment it only lets you change the win_scale and reloads the pygame window when this is done. :param win: Window Scale (How large the window is - must be multiplied by all size related variables). :param win_scale: Window Scale (How large the window is - must be multiplied by all size related variables). :param user_id: UserID if the user has signed in (they don't have to be signed in to play Classic). :param icons: List of icon objects from the StartScreen. """ # Essential super().__init__(win, win_scale, user_id, icons) self.sub_program_name = 'settings' # Settings Title self.settings_title = gui.Word('Settings!', (178, 90), (255, 255, 30), 60, win_scale, centre=True) # Sliders self.music_slider = (gui.Slider( 'Music ', 168, 200, 200, 25, 20, (255, 255, 30), 3, win_scale, level=int(local_settings.get_setting('music_volume')), centre=True)) self.game_slider = (gui.Slider( 'Game Sound ', 168, 240, 200, 25, 20, (255, 255, 30), 3, win_scale, level=int(local_settings.get_setting('game_volume')), centre=True)) self.win_scale_slider = (gui.Slider( 'Win Scale ', 168, 280, 200, 25, 20, (255, 255, 30), 3, win_scale, level=int(local_settings.get_setting('win_scale')), centre=True, levels=5))
def run(self, win, events): """ Responsible for running each level by calling sprite objects and handling their updates. The class also controls other things, such as score, displaying maze etc. :param win: The current window, all objects must be blitted to this window to be displayed. :type win: Surface. :param events: Contains events from the pg.event.get() call containing all keyboard events. :type events: Tuple. :return: Boolean returns True if level is won, False if level is lost, None otherwise """ # Before the game starts (music) if self.start_clock < self.start_cap: self.start_clock += 1 / 60 self.one_up.display(win) self.score_indicator.display(win) self.highscore_text.display(win) self.highscore_indicator.display(win) self.game_maze.display(win) self.ready_text.display(win) for pellet in self.pellets: pellet.display(win) for power_pellet in self.power_pellets: power_pellet.display(win) for life_indicator in self.life_indicators: life_indicator.display(win) for ghost in self.ghosts: ghost.display(win) self.pac_man.display(win) # If there are no pellets the maze will flash elif len(self.pellets) == 0: self.flashing_map_clock += 1 / 60 if self.flashing_map_clock > 0.25: self.flashing_map_clock = 0 self.flashing_map_count += 1 self.game_maze.change_skin() if self.flashing_map_count == 7: self.finished = True self.won = True self.game_maze.display(win) self.one_up.display(win) self.score_indicator.display(win) self.highscore_text.display(win) self.highscore_indicator.display(win) for life_indicator in self.life_indicators: life_indicator.display(win) self.pac_man.display(win) # Mainloop of the level else: # Score Indicators # Controls flashing of one up self.one_up_clock += 1 / 60 if 0.4 > self.one_up_clock > 0.2: self.one_up.display(win) elif 0.4 < self.one_up_clock: self.one_up_clock = 0 self.score_indicator = gui.Word('{}'.format(self.score), self.score_position, (234, 234, 234), 24, self.win_scale) self.score_indicator.display(win) if self.score > self.highscore: self.highscore_indicator = gui.Word('{}'.format(self.score), self.highscore_position, (234, 234, 234), 24, self.win_scale) if not self.extra_life_claimed: if self.score > 10000: self.lives += 1 skin = pg.transform.scale( pg.image.load('Resources\\sprites\\pac-man\\w_0.png'), (22 * self.win_scale, 22 * self.win_scale)) for num in range(self.lives - 1): rect = skin.get_rect( center=((num * 24 * self.win_scale + 18 * self.win_scale), (35 * 12 * self.win_scale))) self.life_indicators.append(StaticSprite([skin], rect)) self.extra_life_claimed = True self.highscore_text.display(win) self.highscore_indicator.display(win) # Life indicators for life_indicator in self.life_indicators: life_indicator.display(win) # Maze self.game_maze.display(win) self.game_maze.display(win) # Pellets for pellet in self.pellets: pellet.update() pellet.display(win) if pellet.eaten: self.score += 10 self.level_score += 10 self.pellets_eaten += 1 self.pellets.remove(pellet) # Power pellets for power_pellet in self.power_pellets: power_pellet.update() power_pellet.display(win) if power_pellet.eaten: self.score += 50 self.level_score += 50 self.power_pellets_eaten += 1 if not self.large_pellet_channel.get_busy(): self.large_pellet_channel.play(self.large_pellet_sound, loops=-1) for ghost in self.ghosts: ghost.scare() self.ghosts_copy = [ ghost for ghost in self.ghosts if not ghost.dead ] self.power_pellets.remove(power_pellet) # Pac-Man self.pac_man.update(events) self.pac_man.display(win) # Checks whether the level has ended if self.pac_man.dead: if self.death_sound_playing: pass else: pg.mixer.stop() self.death_sound_playing = True if self.pac_man.death_animation_finished and not self.finished: self.finished = True if self.lives == 1: self.lives -= 1 self.game_over_text.display(win) pg.display.update() sleep(2) # Ghosts if all([not ghost.scared for ghost in self.ghosts]): self.large_pellet_channel.stop() for ghost in self.ghosts_copy: if ghost.dead: self.ghosts_eaten += 1 self.ghosts_copy.remove(ghost) for ghost_ in self.ghosts_copy: ghost_.display(win) points = 200 * 2**( (len(self.ghosts) - 1) - len(self.ghosts_copy)) self.score += points self.level_score += points win.blit( self.points_text['{}.png'.format(str(points))], (self.pac_man.x, self.pac_man.y - 8 * self.win_scale)) pg.display.update() sleep(1) if not self.pac_man.dead: for ghost in self.ghosts: if ghost.__class__.__name__ == 'Blinky': if len(self.pellets) < 20 + 2 * self.level_num: ghost.make_elroy() if len(self.pellets) < 10 + 2 * self.level_num: ghost.elroy_upgrade() ghost.update(events) ghost.display(win)
def __init__(self, win_scale, game_id, level_num, maze_id, pellets, power_pellets, lives, score, highscore, start_cap=2, extra_life_claimed=False): """ Responsible for storing information about sprite objects. The class stores other things, such as score, maze etc. :param win_scale: Window Scale (How large the window is - must be multiplied by all size related variables). :type win_scale: Integer. :param game_id: GameID given to the game by the database. :type game_id: Integer. :param level_num: This controls difficulty of the ghosts. The larger the level number, the more levels Pac-Man has completed and the harder the ghosts become. :type level_num: Integer. :param maze_id: ID given to each maze. This can be used by the database to return the 2D list associated with the ID. :type maze_id: Integer. :param pellets: A list of pellets. This is if Pac-Man dies and the level starts over. The pellets must be the same as the previous level instance so they are saved by the classic class. :type pellets: List. :param power_pellets: A list of power pellets. This is if Pac-Man dies and the level starts over. The power pellets must be the same as the previous level instance so they are saved by the classic class. :type power_pellets: List. :param lives: Number of lives remaining. :type lives: Integer. :param score: Current score that should be displayed at the top. :type score: Integer. :param highscore: Highscore that should be displayed at the top. :type highscore: Integer. :param start_cap: How long the level should wait to start. :type start_cap: Integer. :param extra_life_claimed: Whether or not the extra life has been given to the player. :type extra_life_claimed: Boolean. """ # Essential self._run = True self.win_scale = win_scale self.program = 'Classic' self.finished = False self.won = False # Variables # Level self.score = score self.highscore = highscore self.game_maze = Maze(maze_id, win_scale) self.lives = lives self.start_cap = start_cap self.extra_life_claimed = extra_life_claimed # Database self.level_num = level_num self.game_id = game_id self.level_score = 0 self.length = 0 self.pellets_eaten = 0 self.power_pellets_eaten = 0 self.ghosts_eaten = 0 # Length counting thread threading.Thread(target=self.second_count).start() # Indicators self.one_up = gui.Word('1UP', (6 * 12, 0.8 * 12), (234, 234, 234), 24, win_scale) self.score_position = (7 * 12, 2 * 12) self.score_indicator = gui.Word('{}'.format(self.score), self.score_position, (234, 234, 234), 24, win_scale) self.highscore_text_position = (19 * 12, 0.8 * 12) self.highscore_position = (17 * 12, 2 * 12) self.highscore_text = gui.Word('high score', self.highscore_text_position, (234, 234, 234), 24, win_scale) if self.score > self.highscore: self.highscore_indicator = gui.Word('{}'.format(self.score), self.highscore_position, (234, 234, 234), 24, win_scale) else: self.highscore_indicator = gui.Word('{}'.format(self.highscore), self.highscore_position, (234, 234, 234), 24, win_scale) self.life_indicators = [] skin = pg.transform.scale( pg.image.load('Resources\\sprites\\pac-man\\w_0.png'), (22 * win_scale, 22 * win_scale)) for num in range(lives - 1): rect = skin.get_rect(center=((num * 24 * win_scale + 18 * win_scale), (35 * 12 * win_scale))) self.life_indicators.append(StaticSprite([skin], rect)) # Start and ready text self.ready_text = gui.Word('ready!', (17.5 * 12, 20.5 * 12), (255, 255, 30), 23, win_scale, italic=True) self.game_over_text = gui.Word('game over', (18 * 12, 20.5 * 12), (255, 0, 0), 21, win_scale) # Points (displayed when Pac-Man eats a ghost). self.points_text = {} for text in os.listdir('Resources\\sprites\\{}'.format('points')): # noinspection PyUnresolvedReferences self.points_text.update({ text: pg.transform.scale( pg.image.load('Resources\\sprites\\{}\\{}'.format( 'points', text)), ((24 * win_scale), (10 * win_scale))) }) # Pac-Man self.pac_man = PacMan('pac-man', self.game_maze, win_scale) # Ghosts self.ghosts = [] self.ghosts_copy = self.ghosts[::] blinky = Blinky('blinky', self.pac_man, self.game_maze, win_scale, level_num) self.ghosts.append(blinky) self.ghosts.append( Pinky('pinky', self.pac_man, self.game_maze, win_scale, level_num)) self.ghosts.append( Clyde('clyde', self.pac_man, self.game_maze, win_scale, level_num)) self.ghosts.append( Inky('inky', self.pac_man, self.game_maze, win_scale, level_num, blinky)) # Pellets self.pellets = pellets self.power_pellets = power_pellets if pellets == [] and power_pellets == []: pellet_skin_path = os.path.join('Resources', 'sprites', 'pellets', 'pellet.png') pellet_skin = pg.transform.scale(pg.image.load(pellet_skin_path), (4 * win_scale, 4 * win_scale)) power_pellet_skin_path = os.path.join('Resources', 'sprites', 'pellets', 'power_pellet.png') power_pellet_skin = pg.transform.scale( pg.image.load(power_pellet_skin_path), (12 * win_scale, 12 * win_scale)) pellet_sound_channel = pg.mixer.Channel(2) pellet_sound_channel.set_volume( 0.5 * (local_settings.get_setting('game_volume') / 100)) power_pellet_death_sound_path = os.path.join( 'Resources', 'sounds', 'pellet', 'death.wav') pellet_death_sound = pg.mixer.Sound(power_pellet_death_sound_path) for row in self.game_maze.tiles: for tile in row: if tile.type == 'pellet': self.pellets.append( Pellet(pellet_skin, tile, self.pac_man, win_scale, pellet_death_sound, pellet_sound_channel)) elif tile.type == 'power_pellet': self.power_pellets.append( Pellet(power_pellet_skin, tile, self.pac_man, win_scale, pellet_death_sound, pellet_sound_channel, power_pellet=True)) else: for pellet in self.pellets: pellet.predator = self.pac_man for power_pellet in self.power_pellets: power_pellet.predator = self.pac_man # Sound self.large_pellet_channel = pg.mixer.Channel(3) self.large_pellet_channel.set_volume( 0.5 * (local_settings.get_setting('game_volume') / 100)) large_pellet_sound_path = os.path.join('Resources', 'sounds', 'large_pellet_loop.wav') self.large_pellet_sound = pg.mixer.Sound(large_pellet_sound_path) self.death_sound_playing = False self.started = False # Clocks and counts self.start_clock = 0 self.one_up_clock = 0 self.flashing_map_clock = 0 self.flashing_map_count = 0
def __init__(self, win, win_scale, user_id): """ Controls the running of each level and database queries. :param win: The current window, all objects must be blitted to this window to be displayed. :param win_scale: Window Scale (How large the window is - must be multiplied by all size related variables). :param user_id: UserID if the user has signed in (they don't have to be signed in to play Classic). """ # Essential self.win_scale = win_scale self.win = win self.program = 'Classic' self.user_id = user_id self.error_message = None self.game_finished = False # Music intro_music_channel = pg.mixer.Channel(7) intro_music_channel.set_volume( 0.5 * local_settings.get_setting('game_volume') / 100) intro_music_channel.play( pg.mixer.Sound('Resources\\sounds\\intro_music.wav')) # Highscore self.highscore = local_database.get_highscore() if self.highscore is None: self.highscore = 0 # Maze self.maze_id = 1 # Variables self.score = 0 self.pellets_eaten = 0 self.level_num = 1 self.lives = 3 # Database self.game_id = local_database.get_game_id(self.user_id, self.maze_id) # Level Info self.level_num = 1 self.extra_life_claimed = False # Level self.level = Level(self.win_scale, self.game_id, 1, self.maze_id, [], [], self.lives, self.score, self.highscore, start_cap=4) # Initials Input Box self.initials_input_box = gui.TransparentInputBox( 100, 30, 20, win_scale, 'Initials') self.word_1 = gui.Word('Enter 3 initials', (168, 180), (255, 255, 30), 20, win_scale, centre=True) self.word_2 = gui.Word('to save highscore', (168, 195), (255, 255, 30), 20, win_scale, centre=True)
def __init__(self, win, win_scale, user_id): """ Displays all the highscores that are saved in the database. :param win: The current window, all objects must be blitted to this window to be displayed. :param win_scale: Window Scale (How large the window is - must be multiplied by all size related variables). :param user_id: UserID if the user has signed in (they don't have to be signed in to play Classic). """ # Essential Information self.win = win self.win_scale = win_scale self.user_id = user_id self.clock = pg.time.Clock() self.program = 'Highscores' self.error_message = None # Title self.title = gui.Word('Highscores!', (175, 90), (255, 255, 30), 45, win_scale, centre=True) self.text = gui.Word('Press any key to return...', (326, 417), (255, 255, 30), 15, win_scale) # Highscores colour = (255, 255, 30) rank_word = gui.Word('Rank', (20, 140), colour, 20, win_scale, left=True) score_word = gui.Word('Score', (120, 140), colour, 20, win_scale, left=True) name_word = gui.Word('Name', (311, 140), colour, 20, win_scale) self.highscore_titles = [rank_word, score_word, name_word] self.highscores = [] place_details = { 0: { 'string': '1st', 'colour': (255, 215, 0) }, 1: { 'string': '2nd', 'colour': (220, 220, 220) }, 2: { 'string': '3rd', 'colour': (205, 127, 50) } } for num, (score, name) in enumerate(local_database.get_highscores()): if num <= 2: place_string = place_details[num]['string'] colour = place_details[num]['colour'] else: place_string = '{}th'.format(num + 1) colour = (169, 169, 169) self.highscores.append( gui.Word(place_string, (20, 160 + 25 * num), colour, 20, win_scale, left=True)) self.highscores.append( gui.Word(str(score), (120, 160 + 25 * num), colour, 20, win_scale, left=True)) self.highscores.append( gui.Word(name, (311, 160 + 25 * num), colour, 20, win_scale)) if num is 9: break
def __init__(self, win, win_scale, user_id, icons): # Essential super().__init__(win, win_scale, user_id, icons) self.sub_program_name = 'accounts' # Login Title self.accounts_title = gui.Word('Accounts!', (180, 90), (255, 255, 30), 60, win_scale, centre=True) # Logged in as self.user_name = gui.Word( 'Logged in as: {}'.format( local_database.get_username(user_id)), (310, 120), (255, 255, 30), 15, win_scale, ) # Statistics self.statistics = [] colour = (255, 255, 30) stats_dict = local_database.get_statistics(user_id) if stats_dict is None: string_1 = 'Statistics will appear' string_2 = 'once you play a game' self.statistics.append( gui.Word(string_1, (336 / 2, 250), colour, 25, win_scale, centre=True)) self.statistics.append( gui.Word(string_2, (336 / 2, 270), colour, 25, win_scale, centre=True)) else: for num, (stat_name, stat) in enumerate(stats_dict.items()): self.statistics.append( gui.Word(stat_name.replace('_', ' '), (20, 240 + 25 * num), colour, 20, win_scale, left=True)) self.statistics.append( gui.Word(str(stat), (311, 240 + 25 * num), colour, 20, win_scale)) # Log out button self.log_out_button = gui.Button('Log Out', (47, 400), (75, 20), 20, (255, 255, 30), 2, win_scale) # Stay logged in buttons self.remember_me = False self.remember_me_green = gui.Button('Remember me', (130, 400), (105, 20), 16, (0, 222, 222), 2, win_scale) self.remember_me_red = gui.Button('Remember me', (130, 400), (105, 20), 16, (222, 0, 0), 2, win_scale) self.remember_me_buttons = [ self.remember_me_green, self.remember_me_red ] if local_settings.get_setting('user_name') is None: self.remember_me_buttons.pop(0)
def __init__(self, win, win_scale, user_id, icons): """ Class for the login screen. :param win: The current window, all objects must be blitted to this window to be displayed. :param win_scale: Window Scale (How large the window is - must be multiplied by all size related variables). :param user_id: UserID if the user has signed in (they don't have to be signed in to play Classic). :param icons: List of icon objects from the StartScreen. """ # Essential super().__init__(win, win_scale, user_id, icons) self.sub_program_name = 'loginscreen' if user_id is None else 'accounts' self.enter_pressed = False # Login Title self.login_title = gui.Word('Login!', (188, 90), (255, 255, 30), 80, win_scale, centre=True) # Username Input Box self.username_input_box = gui.InputBox(168, 206, 150, 30, 30, win_scale, 'Username', centre=True) # Password Input Box self.password_input_box = gui.InputBox(168, 246, 150, 30, 30, win_scale, 'Password', centre=True, private=True) # Login Button self.login_button = gui.Button('Login', (168, 286), (160, 30), 30, (255, 255, 30), 2, win_scale, centre=True) # SignUp Button self.signup_button = gui.Button('SignUp', (168, 286), (160, 30), 30, (255, 255, 30), 2, win_scale, centre=True) self.boxes = [ self.username_input_box, self.password_input_box, self.signup_button ] # Remember me Buttons self.remember_me = False self.remember_me_green = gui.Button('Remember me', (168, 326), (160, 30), 24, (0, 222, 222), 2, win_scale, centre=True) self.remember_me_red = gui.Button('Remember me', (168, 326), (160, 30), 24, (222, 0, 0), 2, win_scale, centre=True) self.remember_me_buttons = [ self.remember_me_red, self.remember_me_green ]
def __init__(self, win, win_scale, user_id, icons): """ Uses words and input boxes to display a sign up screen. It also updates the input boxes and calls the local database to check whether the details are valid, then (if they are) asks the local database to save the details. :param win: The current window, all objects must be blitted to this window to be displayed. :param win_scale: Window Scale (How large the window is - must be multiplied by all size related variables). :param user_id: UserID if the user has signed in (they don't have to be signed in to play Classic). :param icons: List of icon objects from the StartScreen. """ super().__init__(win, win_scale, user_id, icons) self.sub_program_name = 'signupscreen' self.error_message = None self.enter_pressed = False # Sign Up Title self.signup_title = gui.Word('Sign Up!', (188, 90), (255, 255, 30), 80, win_scale, centre=True) # Username Input Box self.username_input_box = gui.InputBox(168, 206, 160, 30, 30, win_scale, 'Username', centre=True) # Password Input Box self.password_input_box = gui.InputBox(168, 246, 160, 30, 30, win_scale, 'Password', centre=True, private=True) # Password Confirm Box self.password_confirm_input_box = gui.InputBox(168, 286, 160, 30, 30, win_scale, 'Password', centre=True, private=True) # Sign Up Button self.signup_button = gui.Button('Sign Up', (168, 326), (160, 30), 30, (255, 255, 30), 2, win_scale, centre=True) self.boxes = [ self.username_input_box, self.password_input_box, self.password_confirm_input_box, self.signup_button ]
def run(self, win, events): """ This method is run from the Tutorial class and updates and displays by one frame. :param win: The current window, all objects must be blitted to this window to be displayed. :type win: Surface. :param events: Contains events from the pg.event.get() call containing all keyboard events. :type events: Tuple. :return: Boolean returns True if level is won, False if level is lost, None otherwise """ # Change to make sure there is a delay when there are no text boxes. if not self.start: # Score Indicators self.score_indicator.display(win) # Maze self.game_maze.display(win) self.ready_text.display(win) # Pellets for pellet in self.pellets: pellet.display(win) # Power pellets for power_pellet in self.power_pellets: power_pellet.display(win) # Ghosts for ghost in self.ghosts: ghost.display(win) # Pac-Man self.pac_man.display(win) elif self.paused: self.score_indicator.display(win) self.game_maze.display(win) for pellet in self.pellets: pellet.display(win) for power_pellet in self.power_pellets: power_pellet.display(win) for ghost in self.ghosts: ghost.display(win) self.pac_man.display(win) # If there are no pellets the maze will flash elif len(self.pellets) == 0: self.flashing_map_clock += 1/60 if self.flashing_map_clock > 0.25: self.flashing_map_clock = 0 self.flashing_map_count += 1 self.game_maze.change_skin() if self.flashing_map_count == 7: self.finished = True self.won = True self.game_maze.display(win) self.score_indicator.display(win) self.pac_man.display(win) # Mainloop of the level else: # Score Indicators self.score_indicator = gui.Word('{}'.format(self.score), self.score_position, (234, 234, 234), 24, self.win_scale ) self.score_indicator.display(win) # Maze self.game_maze.display(win) # Ghost Paths if self.show_paths: for ghost in self.ghosts: ghost.draw_path(win) # Pellets for pellet in self.pellets: pellet.update() pellet.display(win) if pellet.eaten: self.score += 10 self.level_score += 10 self.pellets_eaten += 1 self.pellets.remove(pellet) # Power pellets for power_pellet in self.power_pellets: power_pellet.update() power_pellet.display(win) if power_pellet.eaten: self.score += 50 self.level_score += 50 self.power_pellets_eaten += 1 if not self.large_pellet_channel.get_busy(): self.large_pellet_channel.play(self.large_pellet_sound, loops=-1) for ghost in self.ghosts: ghost.scare() self.ghosts_copy = [ghost for ghost in self.ghosts if not ghost.dead] self.power_pellets.remove(power_pellet) # Pac-Man self.pac_man.update(events) self.pac_man.display(win) # Checks whether the level has ended if self.pac_man.dead: if not self.death_sound_playing: pg.mixer.stop() self.death_sound_playing = True if self.pac_man.death_animation_finished and not self.finished: self.finished = True # Ghosts if all([not ghost.scared for ghost in self.ghosts]): self.large_pellet_channel.stop() for ghost in self.ghosts_copy: if ghost.dead: self.ghosts_eaten += 1 self.ghosts_copy.remove(ghost) for ghost_ in self.ghosts_copy: ghost_.display(win) points = 200 * 2 ** ((len(self.ghosts) - 1) - len(self.ghosts_copy)) self.level_score += points self.score += points win.blit(self.points_texts['{}.png'.format(str(points))], (self.pac_man.x, self.pac_man.y - 8 * self.win_scale)) pg.display.update() sleep(1) if not self.pac_man.dead: for ghost in self.ghosts: if ghost.__class__.__name__ == 'Blinky': if len(self.pellets) < 20 + 2 * self.level_num: ghost.make_elroy() if len(self.pellets) < 10 + 2 * self.level_num: ghost.elroy_upgrade() ghost.update(events) ghost.display(win)
def __init__(self, win_scale, game_id, level_num, maze_id, pellets, power_pellets, score, tutorial_boxes): """ Responsible for running each level by calling sprite objects and handling their updates. The class also controls other things, such as score, displaying maze etc. :param win_scale: Window Scale (How large the window is - must be multiplied by all size related variables). :type win_scale: Integer. :param game_id: GameID given to the game by the database. :type game_id: Integer. :param level_num: This controls difficulty of the ghosts. The larger the level number, the more levels Pac-Man has completed and the harder the ghosts become. :type level_num: Integer. :param maze_id: ID given to each maze. This can be used by the database to return the 2D list associated with the ID. :type maze_id: Integer. :param pellets: A list of pellets. This is if Pac-Man dies and the level starts over. The pellets must be the same as the previous level instance so they are saved by the classic class. :type pellets: List. :param power_pellets: A list of power pellets. This is if Pac-Man dies and the level starts over. The power pellets must be the same as the previous level instance so they are saved by the classic class. :type power_pellets: List. :param score: Current score that should be displayed at the top. :type score: Integer. """ # Essential self._run = True self.win_scale = win_scale self.program = 'Story' self.finished = False self.won = False self.start = False # Variables # Level self.score = score self.game_maze = datastructures.Maze(maze_id, win_scale) # Database self.level_num = level_num self.game_id = game_id self.level_score = 0 self.length = 0 self.pellets_eaten = 0 self.power_pellets_eaten = 0 self.ghosts_eaten = 0 # Tutorial Variables # Messages self.tutorial_boxes = tutorial_boxes self.paused = False # Paths self.show_paths = False # Length counting thread threading.Thread(target=self.second_count).start() # Indicators self.score_position = (7 * 12, 2 * 12) self.score_indicator = gui.Word('{}'.format(self.score), self.score_position, (234, 234, 234), 24, win_scale) # Start and ready text self.ready_text = gui.Word('ready!', (17.5 * 12, 20.5 * 12), (255, 255, 30), 23, win_scale, italic=True) self.game_over_text = gui.Word('game over', (18 * 12, 20.5 * 12), (255, 0, 0), 21, win_scale) # Points (displayed when Pac-Man eats a ghost). self.points_texts = {} for point_text in os.listdir(os.path.join('Resources', 'sprites', 'points')): # noinspection PyUnresolvedReferences self.points_texts.update({point_text: pg.transform.scale( pg.image.load( os.path.join('Resources', 'sprites', 'points', point_text)), ( (24 * win_scale), (10 * win_scale) ) ) }) # Pac-Man self.pac_man = sprites.PacMan('pac-man', self.game_maze, win_scale) # Ghosts self.ghosts = [] self.ghosts_copy = self.ghosts[::] blinky = sprites.Blinky('blinky', self.pac_man, self.game_maze, win_scale, level_num) pinky = sprites.Pinky('pinky', self.pac_man, self.game_maze, win_scale, level_num) clyde = sprites.Clyde('clyde', self.pac_man, self.game_maze, win_scale, level_num) inky = sprites.Inky('inky', self.pac_man, self.game_maze, win_scale, level_num, blinky) if level_num == 1: pass elif level_num == 2: self.ghosts.append(clyde) elif level_num == 3: self.ghosts.append(pinky) elif level_num == 4: self.ghosts.append(blinky) elif level_num == 5: self.ghosts.append(blinky) self.ghosts.append(inky) elif level_num == 6: self.ghosts.append(blinky) self.ghosts.append(inky) else: self.ghosts.append(blinky) self.ghosts.append(pinky) self.ghosts.append(inky) self.ghosts.append(clyde) # Pellets self.pellets = pellets self.power_pellets = power_pellets if pellets == [] and power_pellets == []: pellet_skin_path = os.path.join('Resources', 'sprites', 'pellets', 'pellet.png') pellet_skin = pg.transform.scale(pg.image.load(pellet_skin_path), (4 * win_scale, 4 * win_scale)) power_pellet_skin_path = os.path.join('Resources', 'sprites', 'pellets', 'power_pellet.png') power_pellet_skin = pg.transform.scale(pg.image.load(power_pellet_skin_path), (12 * win_scale, 12 * win_scale) ) pellet_sound_channel = pg.mixer.Channel(2) pellet_sound_channel.set_volume(0.5 * (local_settings.get_setting('game_volume')/100)) power_pellet_death_sound_path = os.path.join('Resources', 'sounds', 'pellet', 'death.wav') pellet_death_sound = pg.mixer.Sound(power_pellet_death_sound_path) for row in self.game_maze.tiles: for tile in row: if tile.type == 'pellet': self.pellets.append(sprites.Pellet(pellet_skin, tile, self.pac_man, win_scale, pellet_death_sound, pellet_sound_channel) ) elif tile.type == 'power_pellet': if level_num >= 5: self.power_pellets.append(sprites.Pellet(power_pellet_skin, tile, self.pac_man, win_scale, pellet_death_sound, pellet_sound_channel, power_pellet=True) ) else: self.pellets.append(sprites.Pellet(pellet_skin, tile, self.pac_man, win_scale, pellet_death_sound, pellet_sound_channel) ) else: for pellet in self.pellets: pellet.predator = self.pac_man for power_pellet in self.power_pellets: power_pellet.predator = self.pac_man # Sound self.large_pellet_channel = pg.mixer.Channel(3) self.large_pellet_channel.set_volume(0.5 * (local_settings.get_setting('game_volume')/100)) large_pellet_sound_path = os.path.join('Resources', 'sounds', 'large_pellet_loop.wav') self.large_pellet_sound = pg.mixer.Sound(large_pellet_sound_path) self.death_sound_playing = False self.started = False # Clocks and counts self.start_clock = 0 self.one_up_clock = 0 self.flashing_map_clock = 0 self.flashing_map_count = 0