def __init__(self, manager): super().__init__(manager) # PyDis logo self.image = ImageObject( self, (0, 0), Paths.splash / "pydis_logo.png", ) # Center the image image_width = self.image.surface.get_rect().width image_height = self.image.surface.get_rect().height center = ( (Window.width / 2) - (image_width / 2), (Window.height / 2) - (image_height / 2), ) # Move the logo to the right position, based on screen size. self.image.move_absolute(center) # What scene should be loaded after this finishes? self.next_scene = "jetbrains" # PyDis SFX self.sound = pygame.mixer.Sound(str(Paths.sfx / "pydis_desu.ogg")) self.sound.play()
class JetBrainsSplash(Splash): """ This shows "sponsored by Jetbrains", fading in an out splash screen style. """ name = "jetbrains" def __init__(self, manager): super().__init__(manager) # JetBrains logo self.image = ImageObject( self, (0, 0), Paths.splash / "jetbrains_logo.png", ) # Center the image image_width = self.image.surface.get_rect().width image_height = self.image.surface.get_rect().height center = ( (Window.width / 2) - (image_width / 2), (Window.height / 2) - (image_height / 2), ) # Move the logo to the right position, based on screen size. self.image.move_absolute(center) # What scene should be loaded after this finishes? self.next_scene = "enter_name" # JetBrains SFX self.sound = pygame.mixer.Sound(str(Paths.sfx / "jetbrains.ogg")) self.sound.play()
def __init__(self, manager): super().__init__(manager) self.max_bombs = 8 self.game_over_screen = None self.accuracy = None self.timer = None self.speed_multiplier = 3 self.explosions: List[Explosion] = [] self.texts: List[TextShootObject] = [] self.new_missile_timer = 200 self.new_jet_timer = random.randint(450, 1200) self.start_ticks = pygame.time.get_ticks() self.game_running = True self.sent_scores = False self.lock = None self.wpm = None self.letters_typed = 0 self.letters_missed = 0 self.pyjet = None self.restart_game_text = TextObject( self, (0, 0), "Play again", font_path=Paths.fonts / "ObelixPro-cyr.ttf", font_size=60 ) self.high_scores_text = TextObject( self, (0, 0), "High scores", font_path=Paths.fonts / "ObelixPro-cyr.ttf", font_size=60 ) self.restart_game_text.move_absolute(( (Window.width / 2) - (self.restart_game_text.size[0] / 2), 450 )) self.high_scores_text.move_absolute(( (Window.width / 2) - (self.high_scores_text.size[0] / 2), 550 )) self.wpm_text = None self.accuracy_text = None # Background image background_path = Paths.levels / random.choice(["level_bg.png", "level_bg_2.png"]) self.background = ImageObject( self, (0, 0), background_path, ) # SFX self.gunshot = pygame.mixer.Sound(str(Paths.sfx / "gunshot.ogg")) self.gunshot.set_volume(0.4) self.wrong = pygame.mixer.Sound(str(Paths.sfx / "wrong_letter.ogg")) self.you_lose_sfx = pygame.mixer.Sound(str(Paths.sfx / "you_lose.ogg")) self.you_win_sfx = pygame.mixer.Sound(str(Paths.sfx / "you_win.ogg")) # Some random NPCs number_of_npcs = 7 npc_slots = [ (123, 550), (211, 550), (284, 550), (450, 550), (570, 550), (800, 550), (990, 550), ] random.shuffle(npc_slots) self.npcs = [] for _ in range(number_of_npcs): self.npcs.append( NPC(self, npc_slots.pop(-1)) ) # Enemies self.flutterdude = Flutterdude( self, (0, 75), 1.5 ) # Play some music self.manager.play_music("pskov_loop.ogg", loop=True)
class Game(Scene): name = "game" def __init__(self, manager): super().__init__(manager) self.max_bombs = 8 self.game_over_screen = None self.accuracy = None self.timer = None self.speed_multiplier = 3 self.explosions: List[Explosion] = [] self.texts: List[TextShootObject] = [] self.new_missile_timer = 200 self.new_jet_timer = random.randint(450, 1200) self.start_ticks = pygame.time.get_ticks() self.game_running = True self.sent_scores = False self.lock = None self.wpm = None self.letters_typed = 0 self.letters_missed = 0 self.pyjet = None self.restart_game_text = TextObject( self, (0, 0), "Play again", font_path=Paths.fonts / "ObelixPro-cyr.ttf", font_size=60 ) self.high_scores_text = TextObject( self, (0, 0), "High scores", font_path=Paths.fonts / "ObelixPro-cyr.ttf", font_size=60 ) self.restart_game_text.move_absolute(( (Window.width / 2) - (self.restart_game_text.size[0] / 2), 450 )) self.high_scores_text.move_absolute(( (Window.width / 2) - (self.high_scores_text.size[0] / 2), 550 )) self.wpm_text = None self.accuracy_text = None # Background image background_path = Paths.levels / random.choice(["level_bg.png", "level_bg_2.png"]) self.background = ImageObject( self, (0, 0), background_path, ) # SFX self.gunshot = pygame.mixer.Sound(str(Paths.sfx / "gunshot.ogg")) self.gunshot.set_volume(0.4) self.wrong = pygame.mixer.Sound(str(Paths.sfx / "wrong_letter.ogg")) self.you_lose_sfx = pygame.mixer.Sound(str(Paths.sfx / "you_lose.ogg")) self.you_win_sfx = pygame.mixer.Sound(str(Paths.sfx / "you_win.ogg")) # Some random NPCs number_of_npcs = 7 npc_slots = [ (123, 550), (211, 550), (284, 550), (450, 550), (570, 550), (800, 550), (990, 550), ] random.shuffle(npc_slots) self.npcs = [] for _ in range(number_of_npcs): self.npcs.append( NPC(self, npc_slots.pop(-1)) ) # Enemies self.flutterdude = Flutterdude( self, (0, 75), 1.5 ) # Play some music self.manager.play_music("pskov_loop.ogg", loop=True) def _build_game_over_screen(self): """ Builds a screen that can be displayed when the game is over, showing WINNER or YOU LOSE graphics, score, a retry button and playing sfx. """ # Calculate WPM total_letters = self.letters_typed + self.letters_missed self.wpm = int((total_letters / 5) / self.timer.minutes_passed) self.wpm_text = TextObject( self, (1045, 15), f"WPM: {self.wpm}", font_path=Paths.fonts / "ObelixPro-cyr.ttf", font_size=35 ) # Calculate accuracy total_letters = self.letters_typed + self.letters_missed if total_letters: self.accuracy = int( 100 - ((self.letters_missed / total_letters) * 100) ) else: self.accuracy = 0 self.accuracy_text = TextObject( self, (938, 70), f"Accuracy: {self.accuracy}%", font_path=Paths.fonts / "ObelixPro-cyr.ttf", font_size=35 ) # Display the right images and play SFX if not self.npcs: self.game_over_screen = ImageObject( self, (0, 0), Paths.ui / "you_lose.png" ) move_height = 220 self.you_lose_sfx.play() else: self.game_over_screen = ImageObject( self, (0, 0), Paths.ui / "winner.png" ) move_height = 100 self.you_win_sfx.play() image_width = self.game_over_screen.size[0] center_x = (Window.width / 2) - (image_width / 2) self.game_over_screen.move_absolute((center_x, move_height)) # Play game over music self.manager.play_music("code_jam_full.ogg") def _draw_timer(self): """ Draws the timer that counts down from ten minutes in the top right corner """ self.timer = Timer( self, (1080, 20), self.start_ticks, speed_multiplier=self.speed_multiplier, font_path=Paths.fonts / "ObelixPro-Cry-cyr.ttf" ) self.timer.draw() def _draw_npcs(self): """ Draws all the NPCs to the play area. """ for npc in self.npcs: if npc.frames_until_turn <= 0: npc.flip() npc.frames_until_turn = random.randint(100, 3000) if npc.frames_until_walk <= 0: move = random.uniform(-3, 3) # Gotta make sure they don't walk off the screen if npc.location[0] > (Window.width - 300): move = -abs(move) elif npc.location[0] < 300: move = abs(move) npc.move(move, 0) npc.frames_until_walk = random.randint(10, 150) else: npc.frames_until_walk -= 1 npc.frames_until_turn -= 1 npc.draw() def _fly_pyjet(self): """ Flies the pyjet across the screen! Also handles dropping bombs from it. """ pyjet_x = self.pyjet.location[0] pyjet_width = self.pyjet.size[0] off_screen = ( (pyjet_x + pyjet_width) <= 0 and not self.pyjet.left_to_right or pyjet_x >= Window.width and self.pyjet.left_to_right ) if off_screen: self.pyjet = None else: if not self.pyjet.bombs_dropped == len(self.pyjet.bomb_drop_locations): drop_bomb_left = ( (pyjet_x + (pyjet_width / 2)) >= self.pyjet.bomb_drop_locations[self.pyjet.bombs_dropped] and self.pyjet.left_to_right ) drop_bomb_right = ( (pyjet_x - (pyjet_width / 2)) <= self.pyjet.bomb_drop_locations[-(self.pyjet.bombs_dropped + 1)] and not self.pyjet.left_to_right ) if drop_bomb_left or drop_bomb_right: new_missile = self.pyjet.create_bomb(random.uniform(0.6, 1.2)) self.texts.append( TextShootObject(self, (0, 0), new_missile, short=True) ) self.pyjet.bombs_dropped += 1 self.pyjet.draw() def _draw_missiles(self, text): """ Draws all the missiles that are currently in play, and explodes them and murders NPCs if they go too low. """ text_x, text_y = text.location y_loc = text_y + text.surface.get_rect().bottomleft[1] if y_loc > Window.height: return elif y_loc >= 550: # Murder the NPC, if he's nearby. closest_npc = None for npc in self.npcs: if not closest_npc: closest_npc = npc elif abs(npc.location[0] - text_x) < abs(closest_npc.location[0] - text_x): closest_npc = npc if closest_npc and abs(closest_npc.location[0] - text_x) < 100: self.npcs.remove(closest_npc) # Explode the missile! self._add_explosion( text.location, random.choice(Explosions.ban_text), size=250 ) self.texts.remove(text) # Remove it from lock if it was locked. if text == self.lock: self.lock = None text.draw() def _add_explosion(self, location: Tuple[int, int], text: str, size: int = 175): """ Adds an explosion with the provided text. Optionally takes a size argument to determine what size the graphics should scale to. """ explosion = Explosion( self, location, Paths.fonts / "ObelixPro-Cry-cyr.ttf", text, size, ) self.explosions.append(explosion) def _commit_score_to_api(self): """ Commits the users score to the database via the Megalomaniac API. """ if not self.sent_scores: requests.post( URLs.add_score_api, json={ "username": self.manager.player_name, "wpm": self.wpm, "accuracy": self.accuracy, } ) self.sent_scores = True def handle_events(self, events): """ Handles all game input events, such as mouse movement and keypresses. """ for event in events: if not self.game_running: for button in (self.restart_game_text, self.high_scores_text): if button.mouseover(): if not button.highlighted: button.highlight() if pygame.mouse.get_pressed()[0] and button.word == "High scores": self.manager.change_scene("high_score") elif pygame.mouse.get_pressed()[0] and button.word == "Play again": self.manager.change_scene("game") elif not self.game_running and not button.mouseover(): button.remove_highlight() if event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: self.manager.change_scene("main_menu") elif event.key == pygame.K_BACKSPACE and self.lock: if self.lock.typed > 0: self.lock.typed -= 1 else: self.lock = None if not self.lock: for text in self.texts: result = text.key_input(event.key) # If the user hit the right key, lock the word if result == TextShootState.SUCCESS: self.letters_typed += 1 self.gunshot.play() self.lock = text # Move the locked element to the end so it always renders on top of everything else. self.texts.append(self.texts.pop(self.texts.index(self.lock))) break elif result == TextShootState.WORD_END: self.letters_typed += 1 self.gunshot.play() self.texts.remove(text) self._add_explosion( text.location, random.choice(Explosions.destroy_text), size=125 ) self.lock = None else: result = self.lock.key_input(event.key) if result == TextShootState.SUCCESS: self.letters_typed += 1 self.gunshot.play() elif result == TextShootState.WORD_END: self.letters_typed += 1 self.gunshot.play() self.texts.remove(self.lock) self._add_explosion( self.lock.location, random.choice(Explosions.destroy_text), size=125 ) self.lock = None elif result == TextShootState.WRONG_KEY: self.letters_missed += 1 self.wrong.play() def draw(self): """ Draws everything to the screen. """ self.background.draw() if self.game_running: self._draw_timer() self._draw_npcs() self.flutterdude.draw() # Create new flutterdude missiles periodically if (self.new_missile_timer == 0 and len(self.texts) < self.max_bombs) or not self.texts: new_missile = self.flutterdude.create_bomb(random.uniform(0.1, 0.4)) self.texts.append( TextShootObject(self, (0, 0), new_missile) ) if self.new_missile_timer == 0: self.new_missile_timer = 200 else: self.new_missile_timer -= 1 # Create jet periodically if self.new_jet_timer == 0: self.pyjet = PyJet( self, left_to_right=random.choice((True, False)) ) self.new_jet_timer = random.randint(450, 1200) else: self.new_jet_timer -= 1 # Fly the jet! Rocket maaan! if self.pyjet: self._fly_pyjet() # Draw all the explosions for explosion in self.explosions.copy(): explosion.draw() if explosion.frame_count >= explosion.frame_length: self.explosions.remove(explosion) # Draw the missiles for text in self.texts: self._draw_missiles(text) # Check if we've lost yet if not self.npcs: self.game_running = False # Check if we've won (timer finished) if self.timer.milliseconds_left <= 0: self.game_running = False # Game is over, and we need to draw some UI. else: if not self.game_over_screen: self._build_game_over_screen() self.game_over_screen.draw() self._commit_score_to_api() self.restart_game_text.draw() self.high_scores_text.draw() self.wpm_text.draw() self.accuracy_text.draw()
def _build_game_over_screen(self): """ Builds a screen that can be displayed when the game is over, showing WINNER or YOU LOSE graphics, score, a retry button and playing sfx. """ # Calculate WPM total_letters = self.letters_typed + self.letters_missed self.wpm = int((total_letters / 5) / self.timer.minutes_passed) self.wpm_text = TextObject( self, (1045, 15), f"WPM: {self.wpm}", font_path=Paths.fonts / "ObelixPro-cyr.ttf", font_size=35 ) # Calculate accuracy total_letters = self.letters_typed + self.letters_missed if total_letters: self.accuracy = int( 100 - ((self.letters_missed / total_letters) * 100) ) else: self.accuracy = 0 self.accuracy_text = TextObject( self, (938, 70), f"Accuracy: {self.accuracy}%", font_path=Paths.fonts / "ObelixPro-cyr.ttf", font_size=35 ) # Display the right images and play SFX if not self.npcs: self.game_over_screen = ImageObject( self, (0, 0), Paths.ui / "you_lose.png" ) move_height = 220 self.you_lose_sfx.play() else: self.game_over_screen = ImageObject( self, (0, 0), Paths.ui / "winner.png" ) move_height = 100 self.you_win_sfx.play() image_width = self.game_over_screen.size[0] center_x = (Window.width / 2) - (image_width / 2) self.game_over_screen.move_absolute((center_x, move_height)) # Play game over music self.manager.play_music("code_jam_full.ogg")
class MainMenu(Scene): """ The screen that appears after the intro sequences. The game logo is displayed at the top. The user must press a button to start the game. """ name = "main_menu" def __init__(self, manager): super().__init__(manager) # Main game logo self.logo = ImageObject( self, (0, 0), Paths.ui / "logo.png", ) # Move the logo to the right position, based on screen size. image_width = self.logo.size[0] logo_location = ( (Window.width / 2) - (image_width / 2), 40, ) self.logo.move_absolute(logo_location) # How to play self.how_to_play_open = False self.how_to_play = ImageObject(self, (0, 0), Paths.ui / "how_to_play.png") self.close_how_to_play = ImageObject(self, (1060, 300), Paths.ui / "close_window.png") # Background image self.background = ImageObject( self, (0, 0), Paths.ui / "background.png", ) # Floaty dudes self.flutterdude = FloatingObject( self, (980, 260), Paths.enemies / "flutterdude.png", float_range=(260, 280), float_speed=4, ) self.brainmon = FloatingObject( self, (900, 400), Paths.enemies / "brainmon_firing.png", float_range=(390, 400), float_speed=3, ) # Text init self.start_game_text = TextObject( self, (90, 400), "Start game", font_path=Paths.fonts / "NANDA.TTF", font_size=60, ) self.how_to_play_text = TextObject( self, (90, 480), "How to play", font_path=Paths.fonts / "NANDA.TTF", font_size=60, ) self.high_scores_text = TextObject( self, (90, 560), "High scores", font_path=Paths.fonts / "NANDA.TTF", font_size=60, ) self.quit_text = TextObject( self, (90, 640), "Quit game", font_path=Paths.fonts / "NANDA.TTF", font_size=60, ) self.menu_items = { "start": self.start_game_text, "how_to_play": self.how_to_play_text, "high_scores": self.high_scores_text, "quit": self.quit_text, "close": self.close_how_to_play, } # SFX if self.manager.previous_scene.name == "jetbrains": self.sound = pygame.mixer.Sound(str(Paths.sfx / "megalomaniac.ogg")) self.sound.play() # Music self.manager.play_music("code_jam_loop.ogg", loop=True) def handle_events(self, events): for event in events: for name, item in self.menu_items.items(): if event.type == pygame.KEYDOWN: if self.how_to_play_open and event.key == pygame.K_ESCAPE: self.how_to_play_open = False break if item.mouseover(): if not item.highlighted: item.highlight() if not name == "close": item.move(15, 0) if pygame.mouse.get_pressed( )[0]: # Left mouse button pressed # Quit button if name == "quit": pygame.quit() sys.exit() # Start game elif name == "start": self.manager.change_scene("game") elif name == "high_scores": self.manager.change_scene("high_score") # How to play elif name == "how_to_play": self.how_to_play_open = True # Close "How to play" menu elif name == "close": self.how_to_play_open = False else: if item.highlighted: item.remove_highlight() if not name == "close": item.move(-15, 0) def draw(self): # Draw the background and the logo self.background.draw() self.logo.draw() if not self.how_to_play_open: # Draw the floaty entities self.brainmon.draw() self.flutterdude.draw() # Draw the menu self.start_game_text.draw() self.how_to_play_text.draw() self.high_scores_text.draw() self.quit_text.draw() else: self.how_to_play.draw() self.close_how_to_play.draw()
def __init__(self, manager): super().__init__(manager) # Main game logo self.logo = ImageObject( self, (0, 0), Paths.ui / "logo.png", ) # Move the logo to the right position, based on screen size. image_width = self.logo.size[0] logo_location = ( (Window.width / 2) - (image_width / 2), 40, ) self.logo.move_absolute(logo_location) # How to play self.how_to_play_open = False self.how_to_play = ImageObject(self, (0, 0), Paths.ui / "how_to_play.png") self.close_how_to_play = ImageObject(self, (1060, 300), Paths.ui / "close_window.png") # Background image self.background = ImageObject( self, (0, 0), Paths.ui / "background.png", ) # Floaty dudes self.flutterdude = FloatingObject( self, (980, 260), Paths.enemies / "flutterdude.png", float_range=(260, 280), float_speed=4, ) self.brainmon = FloatingObject( self, (900, 400), Paths.enemies / "brainmon_firing.png", float_range=(390, 400), float_speed=3, ) # Text init self.start_game_text = TextObject( self, (90, 400), "Start game", font_path=Paths.fonts / "NANDA.TTF", font_size=60, ) self.how_to_play_text = TextObject( self, (90, 480), "How to play", font_path=Paths.fonts / "NANDA.TTF", font_size=60, ) self.high_scores_text = TextObject( self, (90, 560), "High scores", font_path=Paths.fonts / "NANDA.TTF", font_size=60, ) self.quit_text = TextObject( self, (90, 640), "Quit game", font_path=Paths.fonts / "NANDA.TTF", font_size=60, ) self.menu_items = { "start": self.start_game_text, "how_to_play": self.how_to_play_text, "high_scores": self.high_scores_text, "quit": self.quit_text, "close": self.close_how_to_play, } # SFX if self.manager.previous_scene.name == "jetbrains": self.sound = pygame.mixer.Sound(str(Paths.sfx / "megalomaniac.ogg")) self.sound.play() # Music self.manager.play_music("code_jam_loop.ogg", loop=True)
def __init__(self, manager): super().__init__(manager) # Background image self.background = ImageObject( self, (0, 0), Paths.ui / "background.png", ) # High score overlay self.high_scores = ImageObject(self, (0, 0), Paths.ui / "high_scores.png") # High scores headline self.headline_text = TextObject(self, (0, 0), "High scores", font_path=Paths.fonts / "ObelixPro-cyr.ttf", font_size=50) self.headline_text.move_absolute( ((Window.width / 2) - (self.headline_text.size[0] / 2), 75)) # The icons that explain what each row is for self.score_headline = TextObject(self, (600, 200), "Score") self.wpm_headline = TextObject(self, (850, 200), "WPM") self.accuracy_headline = TextObject(self, (1000, 200), "Accuracy") # Add the close button self.close_button = ImageObject(self, (1120, 90), Paths.ui / "close_window.png") # Score attributes self.high_score_y = 270 self.high_score_number = 1 self.high_score_texts = [] # Get the scores r = requests.get(URLs.scores_api) high_scorers = r.json() # Sort by score and limit to 5 high_scorers = [{ "username": name, "wpm": data['wpm'], "accuracy": data['accuracy'], "score": data['score'] } for name, data in high_scorers.items()] high_scorers = sorted(high_scorers, key=itemgetter('score'), reverse=True)[:5] # Build the score text objects for score in high_scorers: points = score['score'] name = score['username'] accuracy = score['accuracy'] wpm = score['wpm'] self.high_score_texts.append(( TextObject(self, (180, self.high_score_y), f"{self.high_score_number}.", font_path=Paths.fonts / "NANDA.TTF", font_size=60), TextObject(self, (230, self.high_score_y), name, font_path=Paths.fonts / "NANDA.TTF", font_size=60), TextObject(self, (600, self.high_score_y), str(points), font_path=Paths.fonts / "NANDA.TTF", font_size=60), TextObject(self, (850, self.high_score_y), str(wpm), font_path=Paths.fonts / "NANDA.TTF", font_size=60), TextObject(self, (1000, self.high_score_y), f"{accuracy}%", font_path=Paths.fonts / "NANDA.TTF", font_size=60), )) self.high_score_y += 80 self.high_score_number += 1 self.start_game_text = TextObject( self, (90, 400), "Start game", font_path=Paths.fonts / "NANDA.TTF", font_size=60, ) # Music if self.manager.previous_scene and not self.manager.previous_scene.name == "main_menu": self.manager.play_music("code_jam_full.ogg")
class HighScore(Scene): """ The screen that appears after the intro sequences. The game logo is displayed at the top. The user must press a button to start the game. """ name = "high_score" def __init__(self, manager): super().__init__(manager) # Background image self.background = ImageObject( self, (0, 0), Paths.ui / "background.png", ) # High score overlay self.high_scores = ImageObject(self, (0, 0), Paths.ui / "high_scores.png") # High scores headline self.headline_text = TextObject(self, (0, 0), "High scores", font_path=Paths.fonts / "ObelixPro-cyr.ttf", font_size=50) self.headline_text.move_absolute( ((Window.width / 2) - (self.headline_text.size[0] / 2), 75)) # The icons that explain what each row is for self.score_headline = TextObject(self, (600, 200), "Score") self.wpm_headline = TextObject(self, (850, 200), "WPM") self.accuracy_headline = TextObject(self, (1000, 200), "Accuracy") # Add the close button self.close_button = ImageObject(self, (1120, 90), Paths.ui / "close_window.png") # Score attributes self.high_score_y = 270 self.high_score_number = 1 self.high_score_texts = [] # Get the scores r = requests.get(URLs.scores_api) high_scorers = r.json() # Sort by score and limit to 5 high_scorers = [{ "username": name, "wpm": data['wpm'], "accuracy": data['accuracy'], "score": data['score'] } for name, data in high_scorers.items()] high_scorers = sorted(high_scorers, key=itemgetter('score'), reverse=True)[:5] # Build the score text objects for score in high_scorers: points = score['score'] name = score['username'] accuracy = score['accuracy'] wpm = score['wpm'] self.high_score_texts.append(( TextObject(self, (180, self.high_score_y), f"{self.high_score_number}.", font_path=Paths.fonts / "NANDA.TTF", font_size=60), TextObject(self, (230, self.high_score_y), name, font_path=Paths.fonts / "NANDA.TTF", font_size=60), TextObject(self, (600, self.high_score_y), str(points), font_path=Paths.fonts / "NANDA.TTF", font_size=60), TextObject(self, (850, self.high_score_y), str(wpm), font_path=Paths.fonts / "NANDA.TTF", font_size=60), TextObject(self, (1000, self.high_score_y), f"{accuracy}%", font_path=Paths.fonts / "NANDA.TTF", font_size=60), )) self.high_score_y += 80 self.high_score_number += 1 self.start_game_text = TextObject( self, (90, 400), "Start game", font_path=Paths.fonts / "NANDA.TTF", font_size=60, ) # Music if self.manager.previous_scene and not self.manager.previous_scene.name == "main_menu": self.manager.play_music("code_jam_full.ogg") def handle_events(self, events): for event in events: # Escape goes back to the main menu if event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: self.manager.change_scene("main_menu") if self.close_button.mouseover(): if not self.close_button.highlighted: self.close_button.highlight() if pygame.mouse.get_pressed()[0]: self.manager.change_scene("main_menu") else: if self.close_button.highlighted: self.close_button.remove_highlight() def draw(self): # Draw the background and the logo self.background.draw() self.high_scores.draw() self.headline_text.draw() self.close_button.draw() # Draw the icons self.wpm_headline.draw() self.score_headline.draw() self.accuracy_headline.draw() for score in self.high_score_texts: for attribute in score: attribute.draw()
class EnterName(Scene): """ The screen that appears after the intro sequences, asking the player to enter their name so we can use it for high scores. """ name = "enter_name" def __init__(self, manager): super().__init__(manager) # Background image self.background = ImageObject( self, (0, 0), Paths.ui / "background.png", ) # Box overlay self.enter_name_box = ImageObject(self, (0, 0), Paths.ui / "enter_name_box.png") self.enter_name_box.move_absolute( ((Window.width / 2) - (self.enter_name_box.size[0] / 2), (Window.height / 2) - (self.enter_name_box.size[1] / 2))) # Instructions self.please_enter_name = TextObject(self, (0, 0), "Who are you?", font_path=Paths.fonts / "ObelixPro-cyr.ttf", font_size=50) self.please_enter_name.move_absolute( ((Window.width / 2) - (self.please_enter_name.size[0] / 2), 200)) # InputBox self.input_field = TextInputObject( self, (450, 315), font_path=Paths.fonts / "FiraMono-Regular.ttf", font_size=40, max_length=15, text_color=Colors.white, cursor_color=Colors.white, ) # Explanation text below input self.explanation_line_1 = TextObject( self, (0, 0), "We need this information for high scores.", font_path=Paths.fonts / "FiraMono-Regular.ttf", font_size=20) self.explanation_line_1.move_absolute( ((Window.width / 2) - (self.explanation_line_1.size[0] / 2), 400)) self.explanation_line_2 = TextObject( self, (0, 0), "Feel free to input a nickname, or a made-up name.", font_path=Paths.fonts / "FiraMono-Regular.ttf", font_size=20) self.explanation_line_2.move_absolute( ((Window.width / 2) - (self.explanation_line_2.size[0] / 2), 440)) # OK Button self.ok_button = TextObject(self, (880, 530), "OK", font_path=Paths.fonts / "ObelixPro-cyr.ttf", font_size=50, disabled=True) # Music self.manager.play_music("code_jam_loop.ogg", loop=True) def handle_events(self, events): return_event = self.input_field.update(events) # Check whether to enable the button if len(self.input_field.get_text()) >= 1 and self.ok_button.disabled: self.ok_button.enable() elif len(self.input_field.get_text() ) < 1 and not self.ok_button.disabled: self.ok_button.disable() # Handle the OK button if not self.ok_button.disabled: # User hit RETURN and has typed something if return_event: self.manager.player_name = self.input_field.get_text() self.manager.change_scene("main_menu") # Handle mouse interaction with OK button if self.ok_button.mouseover(): if not self.ok_button.highlighted: self.ok_button.highlight() if pygame.mouse.get_pressed()[0]: self.manager.player_name = self.input_field.get_text() self.manager.change_scene("main_menu") # No mouseover event else: if self.ok_button.highlighted: self.ok_button.remove_highlight() def draw(self): self.background.draw() self.enter_name_box.draw() self.please_enter_name.draw() self.explanation_line_1.draw() self.explanation_line_2.draw() self.ok_button.draw() self.input_field.draw()
def __init__(self, manager): super().__init__(manager) # Background image self.background = ImageObject( self, (0, 0), Paths.ui / "background.png", ) # Box overlay self.enter_name_box = ImageObject(self, (0, 0), Paths.ui / "enter_name_box.png") self.enter_name_box.move_absolute( ((Window.width / 2) - (self.enter_name_box.size[0] / 2), (Window.height / 2) - (self.enter_name_box.size[1] / 2))) # Instructions self.please_enter_name = TextObject(self, (0, 0), "Who are you?", font_path=Paths.fonts / "ObelixPro-cyr.ttf", font_size=50) self.please_enter_name.move_absolute( ((Window.width / 2) - (self.please_enter_name.size[0] / 2), 200)) # InputBox self.input_field = TextInputObject( self, (450, 315), font_path=Paths.fonts / "FiraMono-Regular.ttf", font_size=40, max_length=15, text_color=Colors.white, cursor_color=Colors.white, ) # Explanation text below input self.explanation_line_1 = TextObject( self, (0, 0), "We need this information for high scores.", font_path=Paths.fonts / "FiraMono-Regular.ttf", font_size=20) self.explanation_line_1.move_absolute( ((Window.width / 2) - (self.explanation_line_1.size[0] / 2), 400)) self.explanation_line_2 = TextObject( self, (0, 0), "Feel free to input a nickname, or a made-up name.", font_path=Paths.fonts / "FiraMono-Regular.ttf", font_size=20) self.explanation_line_2.move_absolute( ((Window.width / 2) - (self.explanation_line_2.size[0] / 2), 440)) # OK Button self.ok_button = TextObject(self, (880, 530), "OK", font_path=Paths.fonts / "ObelixPro-cyr.ttf", font_size=50, disabled=True) # Music self.manager.play_music("code_jam_loop.ogg", loop=True)