def game_over(): pygame.mixer.stop() settings.wn.fill((0, 0, 0)) game_over_rect = pygame.Rect( utils.centre_offset( settings.SCREEN_RECT, (0, 0, settings.DISPLAY_WIDTH // 2, settings.DISPLAY_HEIGHT // 2)), (settings.DISPLAY_WIDTH // 2, settings.DISPLAY_HEIGHT // 2)) pygame.draw.rect(settings.wn, (127, 127, 127), game_over_rect) done = False font = pygame.font.SysFont("Arial", 64) game_over_text = font.render("Game Over", True, (255, 255, 255)) score_text = pygame.font.SysFont("Arial", 48).render(f"Score: {settings.SCORE}", True, (255, 255, 255)) restart_button = BorderButton( pygame.Rect(game_over_rect.x + 20, game_over_rect.bottom - 80, 150, 60), (0, 128, 0), (0, 192, 0), "restart", 28, (255, 255, 255), 2, None) exit_to_menu_button = BorderButton( pygame.Rect(game_over_rect.right - 170, game_over_rect.bottom - 80, 150, 60), (128, 0, 0), (192, 0, 0), "Exit to Menu", 28, (255, 255, 255), 2, None) while not done: settings.clock.tick(settings.FPS) pygame.draw.rect(settings.wn, (127, 127, 127), game_over_rect) restart_button.update() restart_button.draw(settings.wn) exit_to_menu_button.update() exit_to_menu_button.draw(settings.wn) settings.wn.blit(game_over_text, (utils.x_offset( game_over_rect, game_over_text.get_size()[0]), game_over_rect.y + 20)) settings.wn.blit( score_text, (utils.x_offset(game_over_rect, score_text.get_size()[0]), game_over_rect.y + 120)) if restart_button.is_hovering() and pygame.mouse.get_pressed()[0]: done = True settings.wn.fill((0, 0, 0)) settings.LEVEL = 0 settings.SCORE = 0 settings.TIMER = 0 elif exit_to_menu_button.is_hovering() and pygame.mouse.get_pressed( )[0]: settings.LEVEL = 0 settings.SCORE = 0 settings.TIMER = 0 menu() for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() pygame.display.flip()
def how_to_play(): settings.wn.fill((0, 0, 0)) header_font = pygame.font.SysFont("Arial", 70) body_font = pygame.font.SysFont("Arial", 28) how_to_play_text = header_font.render("How to Play", True, (255, 255, 255)) settings.wn.blit(how_to_play_text, (utils.x_offset(settings.SCREEN_RECT, how_to_play_text.get_size()[0]), 100)) body_text = [] body_text.append( body_font.render( f"Press {pygame.key.name(settings.keys['UP'])} to move up, " f"press {pygame.key.name(settings.keys['LEFT'])} to move left, " f"press {pygame.key.name(settings.keys['DOWN'])} to move down, " f"and press {pygame.key.name(settings.keys['RIGHT'])} to move right.", True, (255, 255, 255))) body_text.append( body_font.render( f"Press {pygame.key.name(settings.keys['SHOOT'])} to fire a projectile.", True, (255, 255, 255))) body_text.append( body_font.render( f"Press {pygame.key.name(settings.keys['BOMB'])} to clear all enemy projectiles. " f"There is a cooldown of 10 seconds between each use.", True, (255, 255, 255))) body_text.append( body_font.render( f"Killing an enemy grants score and has a chance to drop a powerup.", True, (255, 255, 255))) back_to_menu_rect = pygame.Rect(settings.WIDTH - 300, 100, 200, 100) back_to_menu_button = Button(back_to_menu_rect, (0, 0, 127), (0, 0, 192), "Back To Menu", 28, (255, 255, 255), None) for i, text in enumerate(body_text): settings.wn.blit(text, (50, 300 + body_font.get_height() * i)) pygame.display.flip() while True: back_to_menu_button.update() back_to_menu_button.draw(settings.wn) settings.clock.tick(settings.FPS) for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() if event.type == pygame.MOUSEBUTTONDOWN: if back_to_menu_button.is_hovering(): settings.wn.fill((0, 0, 0)) myfont = pygame.font.SysFont("Arial", 70) title_font = myfont.render("Space Game", True, (255, 255, 255)) title_rect = pygame.Rect((0, 0), myfont.size("Space Game")) settings.wn.blit(title_font, (utils.x_offset( settings.SCREEN_RECT, title_rect), 100)) pygame.display.flip() return pygame.display.update(back_to_menu_rect)
def menu(): settings.init() settings.wn.fill((0, 0, 0)) update_rects = [] buttons = [] myfont = pygame.font.SysFont("Arial", 70) title_font = myfont.render("Space Game", True, (255, 255, 255)) title_rect = pygame.Rect((0, 0), myfont.size("Space Game")) settings.wn.blit(title_font, (utils.x_offset(settings.SCREEN_RECT, title_rect), 100)) update_rects.append( pygame.Rect((utils.x_offset(settings.SCREEN_RECT, title_rect), 100), myfont.size("Space Game"))) b_width = 200 b_height = 100 b_x = utils.x_offset(settings.SCREEN_RECT, pygame.Rect(0, 0, b_width, b_height)) buttons.append( Button(pygame.Rect(b_x, 300, b_width, b_height), (0, 127, 127), (0, 192, 192), "Play", 40, (255, 255, 255), difficulty_menu)) buttons.append( Button(pygame.Rect(b_x, 500, b_width, b_height), (127, 127, 127), (192, 192, 192), "Settings", 40, (255, 255, 255), settings_menu)) buttons.append( Button(pygame.Rect(b_x, 700, b_width, b_height), (127, 127, 0), (192, 192, 0), "How to Play", 40, (255, 255, 255), how_to_play)) pygame.mixer.stop() settings.sounds["music"]["menu_music"].play(loops=-1) for button in buttons: button.draw(settings.wn) update_rects.append(button.rect) pygame.display.update() while True: settings.clock.tick(settings.FPS) for button in buttons: button.update() button.draw(settings.wn) update_rects.append(button.rect) for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() exit(1) pygame.display.update(update_rects) update_rects = []
def __init__(self, speed: float, x: int, y: int, health: int, fire_delay: float, projectile_speed: float, image: pygame.Surface, attack_imgs: list, anim_delay: int = 0, projectile_count: int = 1, projectile_spread: float = 15): pygame.sprite.DirtySprite.__init__(self) self.speed = speed self.x = x self.y = y self.image = image self.attack_imgs = attack_imgs self.anim_delay = anim_delay self.fire_delay = fire_delay self.projectile_speed = projectile_speed self.projectile_count = projectile_count self.projectile_spread = projectile_spread self.timer = 0 self.hit_timer = 9999 self.bomb_timer = 10000 self.invuln_delay = 200 # invincibility time after getting hit, in milliseconds self.health = health self.rect = pygame.Rect(x, y, self.image.get_width(), self.image.get_height()) hitbox_width = self.rect.w / 3 hitbox_height = self.rect.h / 3 hitbox_x = utils.x_offset(self.rect, hitbox_width) hitbox_y = utils.y_offset(self.rect, hitbox_height) self.hitbox = pygame.Rect(hitbox_x, hitbox_y, hitbox_width, hitbox_height) # game stats self.score = 0 self.p_speed_count = 0 self.p_spread_count = 0 self.p_firerate_count = 0 self.p_count_count = 0 self.invuln_count = 0 self.p_speed_incrs = [0, 50, 50, 50, 60, 75, 0] self.p_spread_incrs = [0, -1, -1, -2, -2, -3, 0] self.p_firerate_incrs = [0, -50, -50, -100, -200, -300, 0] self.p_count_incrs = [0, 1, 1, 1, 1, 2, 0] self.invuln_incrs = [0, 50, 50, 100, 100, 150, 0]
def update_keys(self, projectiles_group: pygame.sprite.Group, enemy_projectiles_group: pygame.sprite.Group): keys = pygame.key.get_pressed() # math.ceil to avoid integer truncation if keys[settings.keys["UP"]]: #print(self.rect.y) self.y -= (self.speed * settings.DELTA_T) #print(self.rect.y) self.dirty = 1 if keys[settings.keys["DOWN"]]: self.y += (self.speed * settings.DELTA_T) self.dirty = 1 if keys[settings.keys["LEFT"]]: self.x -= (self.speed * settings.DELTA_T) self.dirty = 1 if keys[settings.keys["RIGHT"]]: self.x += (self.speed * settings.DELTA_T) self.dirty = 1 if keys[settings.keys["BOMB"]]: if self.bomb_timer <= 0: enemy_projectiles_group.empty() self.bomb_timer = 10000 self.x = max(self.x, settings.LEFT_BOUND) self.x = min(self.x + self.rect.w, settings.RIGHT_BOUND) - self.rect.w self.y = max(self.y, settings.LOWER_BOUND) self.y = min(self.y + self.rect.h, settings.UPPER_BOUND) - self.rect.h self.rect.topleft = round(self.x), round(self.y) self.hitbox.topleft = utils.x_offset(self.rect, self.hitbox.w), utils.y_offset( self.rect, self.hitbox.h) if keys[settings.keys["SHOOT"]]: if self.timer > self.fire_delay: settings.sounds["effects"]["shoot"].play() self.fire(projectiles_group) self.timer = 0 self.dirty = 1
def difficulty_menu(): settings.wn.fill((0, 0, 0)) update_rects = [] buttons = [] myfont = pygame.font.SysFont("Arial", 70) text_font = pygame.font.SysFont("Arial", 48) diff_text = myfont.render("Select Difficulty", True, (255, 255, 255)) diff_rect = pygame.Rect((0, 0), myfont.size("Select Difficulty")) settings.wn.blit(diff_text, (utils.x_offset(settings.SCREEN_RECT, diff_rect), 50)) easy_im = utils.load_image("assets/images/easy_button.png", 75) medium_im = utils.load_image("assets/images/medium_button.png", 75) hard_im = utils.load_image("assets/images/hard_button.png", 75) extreme_im = utils.load_image("assets/images/extreme_button.png", 75) easy_text = text_font.render("Easy difficulty. 5 lives.", True, (255, 255, 255)) medium_text = text_font.render("Medium difficulty. 3 lives.", True, (255, 255, 255)) hard_text = text_font.render("Hard difficulty. 2 lives.", True, (255, 255, 255)) extreme_text = text_font.render("Extreme difficulty. 1 life.", True, (255, 255, 255)) rect_width = 600 rect_height = 100 rect_gap = 50 rect_x = utils.x_offset(settings.SCREEN_RECT, rect_width) easy_button = BorderButton( (rect_x, 150 + rect_gap, rect_width, rect_height), (0, 127, 0), (0, 192, 0), "", 40, (255, 255, 255), 5, None) medium_button = BorderButton( (rect_x, 250 + 2 * rect_gap, rect_width, rect_height), (176, 176, 0), (225, 225, 0), "", 40, (255, 255, 255), 5, None) hard_button = BorderButton( (rect_x, 350 + 3 * rect_gap, rect_width, rect_height), (127, 0, 0), (192, 0, 0), "", 40, (255, 255, 255), 5, None) extreme_button = BorderButton( (rect_x, 450 + 4 * rect_gap, rect_width, rect_height), (76, 0, 76), (127, 0, 127), "", 40, (255, 255, 255), 5, None) back_button = BorderButton( (utils.x_offset(settings.SCREEN_RECT, 200), 800, 200, 50), (127, 127, 127), (192, 192, 192), "Back To Menu", 36, (255, 255, 255), 3, menu) ''' for i, tup in enumerate(zip([easy_im, medium_im, hard_im, extreme_im], [easy_text, medium_text, hard_text, extreme_text])): y_offset = utils.y_offset((rect_x, 150 + 100 * i + (i + 1) * rect_gap, rect_width, rect_height), text_font.get_linesize()) settings.wn.blit(tup[0], (rect_x+12, 150+100*i+(i+1)*rect_gap+12)) settings.wn.blit(tup[1], (rect_x+112, 150+100*i+(i+1)*rect_gap+y_offset)) for i in range(1, 5, 1): pygame.draw.rect(settings.wn, (192, 192, 192), (rect_x+7, 150+(i-1)*100+i*rect_gap+7, 85, 85)) ''' buttons.append(easy_button) buttons.append(medium_button) buttons.append(hard_button) buttons.append(extreme_button) buttons.append(back_button) pygame.display.update() while True: settings.clock.tick(settings.FPS) for button in buttons: update_rects.append(button.rect) button.draw(settings.wn) back_button.update() for i in range(1, 5, 1): pygame.draw.rect(settings.wn, (192, 192, 192), (rect_x + 7, 150 + (i - 1) * 100 + i * rect_gap + 7, 85, 85)) for i, tup in enumerate( zip([easy_im, medium_im, hard_im, extreme_im], [easy_text, medium_text, hard_text, extreme_text])): y_offset = utils.y_offset( (rect_x, 150 + 100 * i + (i + 1) * rect_gap, rect_width, rect_height), text_font.get_linesize()) settings.wn.blit(tup[0], (rect_x + 12, 150 + 100 * i + (i + 1) * rect_gap + 12)) settings.wn.blit(tup[1], (rect_x + 112, y_offset)) for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() exit() if event.type == pygame.MOUSEBUTTONDOWN: if easy_button.is_hovering(): settings.LIVES = 5 pygame.mixer.stop() settings.sounds["music"]["easy_level_music"].play(loops=-1) play() elif medium_button.is_hovering(): settings.LIVES = 3 pygame.mixer.stop() settings.sounds["music"]["medium_level_music"].play( loops=-1) play() elif hard_button.is_hovering(): settings.LIVES = 2 pygame.mixer.stop() settings.sounds["music"]["hard_level_music"].play(loops=-1) play() elif extreme_button.is_hovering(): settings.LIVES = 1 pygame.mixer.stop() settings.sounds["music"]["extreme_level_music"].play( loops=-1) play() pygame.display.update(update_rects) update_rects = []
def settings_menu(): """ Let the user change volume, keybinds and fullscreen """ print("In settings") update_rects = [settings.SCREEN_RECT] buttons = [] key_boxes = [] key_buttons = [] settings.wn.fill((0, 0, 0)) volume = settings.VOLUME keys = settings.keys fullscreen = settings.FULLSCREEN # this is spaghetti code def seek_key(button): temp_hover_col = button.hover_col button.hover_col = button.col while True: settings.clock.tick(settings.FPS) pressed = pygame.key.get_pressed() count = 0 for val in pressed: if val != 0: button.hover_col = temp_hover_col return count count += 1 for event2 in pygame.event.get(): if event2.type == pygame.QUIT: pygame.quit() exit() button.draw(settings.wn) pygame.display.update(button.rect) def save(button): button.text = "Saved!" res = dict( (("VOLUME", volume), ("keys", keys), ("FULLSCREEN", fullscreen))) settings.change_settings(res) for key10 in settings.sounds: for key20 in settings.sounds[key10]: settings.sounds[key10][key20].set_volume(settings.VOLUME) settings_rect = pygame.Rect( utils.x_offset(settings.SCREEN_RECT, pygame.Rect(0, 0, 400, 100)), 25, 400, 100) settings_box = Button(settings_rect, (128, 128, 0), (128, 128, 0), "Settings", 56, (255, 255, 255), None) volume_str = f"Volume: {round(volume * 100)}%" volume_box_rect = pygame.Rect( utils.x_offset(settings.SCREEN_RECT, (0, 0, 200, 75)), 175, 200, 75) volume_box = Button(volume_box_rect, (128, 128, 128), (128, 128, 128), volume_str, 32, (255, 255, 255), None) volume_button_minus_rect = pygame.Rect( volume_box_rect.x - volume_box_rect.h * 2, volume_box_rect.y, volume_box_rect.h, volume_box_rect.h) volume_button_minus = Button(volume_button_minus_rect, (128, 128, 128), (192, 192, 192), "-", 32, (255, 255, 255), None) volume_button_plus_rect = pygame.Rect( volume_box_rect.right + volume_box_rect.h, volume_box_rect.y, volume_box_rect.h, volume_box_rect.h) volume_button_plus = Button(volume_button_plus_rect, (128, 128, 128), (192, 192, 192), "+", 32, (255, 255, 255), None) fullscreen_str = "Fullscreen: On" if fullscreen else "Fullscreen: Off" fullscreen_on_col = (0, 175, 0) fullscreen_on_hover_col = (0, 225, 0) fullscreen_off_col = (175, 0, 0) fullscreen_off_hover_col = (225, 0, 0) fullscreen_rect = pygame.Rect( utils.x_offset(settings.SCREEN_RECT, (0, 0, 300, 75)), 300, 300, 75) fullscreen_box = Button((fullscreen_rect.x, fullscreen_rect.y, 200, 75), (128, 128, 128), (128, 128, 128), fullscreen_str, 32, (255, 255, 255), None) fullscreen_button_rect = pygame.Rect( fullscreen_rect.right + (300 - fullscreen_rect.w - fullscreen_rect.h), fullscreen_rect.y, fullscreen_rect.h, fullscreen_rect.h) if fullscreen: fullscreen_button = Button(fullscreen_button_rect, fullscreen_on_col, fullscreen_on_hover_col, "On", 32, (255, 255, 255), None) else: fullscreen_button = Button(fullscreen_button_rect, fullscreen_off_col, fullscreen_off_hover_col, "Off", 32, (255, 255, 255), None) bounding_key_rect = pygame.Rect( utils.x_offset(settings.SCREEN_RECT, (0, 0, 450, 300)), 460, 780, 360) elems = len(keys) + 1 space = bounding_key_rect.h // elems gap = 20 for i, key in enumerate({**{"Keybinds (click to change):": 0}, **keys}): if i == 0: key_rect = pygame.Rect( bounding_key_rect.x, bounding_key_rect.y - (80 - (space - gap)) + i * space, 450, 60) key_box = Button(key_rect, (127, 127, 127), (127, 127, 127), key, 36, (255, 255, 255), None) else: key_rect = pygame.Rect(bounding_key_rect.x, bounding_key_rect.y + i * space, 200, space - gap) key_box = Button(key_rect, (127, 127, 127), (127, 127, 127), key, 24, (255, 255, 255), None) key_boxes.append(key_box) key_button_rect = pygame.Rect(bounding_key_rect.x + 200 + 50, bounding_key_rect.y + i * space, 200, space - gap) if i != 0: key_button = Button(key_button_rect, (127, 127, 127), (192, 192, 192), pygame.key.name(keys[key]), 24, (255, 255, 255), None) buttons.append(key_button) key_buttons.append(key_button) update_rects.append(key_rect) buttons.append(key_box) cancel_rect = pygame.Rect( utils.x_offset(settings.SCREEN_RECT, (0, 0, 650, 25)), 825, 150, 50) save_rect = pygame.Rect(cancel_rect.right + 100, 825, 150, 50) reset_defaults_rect = pygame.Rect(save_rect.right + 100, 825, 150, 50) cancel_box = Button(cancel_rect, (127, 0, 0), (192, 0, 0), "Cancel", 28, (255, 255, 255), None) save_box = Button(save_rect, (0, 127, 0), (0, 192, 0), "Save", 28, (255, 255, 255), None) reset_defaults_box = Button(reset_defaults_rect, (127, 0, 127), (192, 0, 192), "Reset", 28, (255, 255, 255), None) update_rects.append(settings_rect) update_rects.append(volume_box_rect) update_rects.append(volume_button_minus_rect) update_rects.append(volume_button_plus_rect) update_rects.append(fullscreen_rect) update_rects.append(fullscreen_button_rect) update_rects.append(cancel_rect) update_rects.append(save_rect) update_rects.append(reset_defaults_rect) buttons.append(settings_box) buttons.append(volume_box) buttons.append(volume_button_minus) buttons.append(volume_button_plus) buttons.append(fullscreen_box) buttons.append(fullscreen_button) buttons.append(cancel_box) buttons.append(save_box) buttons.append(reset_defaults_box) while True: settings.clock.tick(settings.FPS) for button in buttons: button.draw(settings.wn) update_rects.append(button.rect) for event in pygame.event.get(): if event.type == pygame.MOUSEBUTTONDOWN: if pygame.mouse.get_pressed()[0]: if volume_button_plus.is_hovering(): save_box.text = "Save" volume += 0.05 elif volume_button_minus.is_hovering(): save_box.text = "Save" volume -= 0.05 volume = round(volume, 2) volume = min(max(0, volume), 1) volume_box.text = f"Volume: {round(volume * 100)}%" if fullscreen_button.is_hovering(): save_box.text = "Save" fullscreen = not fullscreen if fullscreen: fullscreen_button.col = fullscreen_on_col fullscreen_button.hover_col = fullscreen_on_hover_col fullscreen_button.text = "On" fullscreen_box.text = "Fullscreen: On" else: fullscreen_button.col = fullscreen_off_col fullscreen_button.hover_col = fullscreen_off_hover_col fullscreen_button.text = "Off" fullscreen_box.text = "Fullscreen: Off" for i, button in enumerate(key_buttons): if button.is_hovering(): save_box.text = "Save" temp_key_text = key_buttons[i].text key_buttons[i].text = "Press a key to record" new = seek_key(button) # check if new is in the keybinds if new not in keys.values(): key_buttons[i].text = pygame.key.name(new) keys[key_boxes[i].text] = new else: key_buttons[i].text = temp_key_text if cancel_box.is_hovering(): settings.wn.fill((0, 0, 0)) myfont = pygame.font.SysFont("Arial", 70) title_font = myfont.render("Space Game", True, (255, 255, 255)) title_rect = pygame.Rect((0, 0), myfont.size("Space Game")) settings.wn.blit(title_font, (utils.x_offset( settings.SCREEN_RECT, title_rect), 100)) pygame.display.flip() return if save_box.is_hovering(): save(save_box) if reset_defaults_box.is_hovering(): save_box.text = "Save" volume = settings.defaults["VOLUME"] keys = settings.defaults["keys"] fullscreen = settings.defaults["FULLSCREEN"] volume_box.text = f"Volume: {round(volume * 100)}%" for i, button in enumerate(key_buttons): key_buttons[i].text = pygame.key.name( keys[key_boxes[i].text]) if fullscreen: fullscreen_button.col = fullscreen_on_col fullscreen_button.hover_col = fullscreen_on_hover_col fullscreen_button.text = "On" fullscreen_box.text = "Fullscreen: On" else: fullscreen_button.col = fullscreen_off_col fullscreen_button.hover_col = fullscreen_off_hover_col fullscreen_button.text = "Off" fullscreen_box.text = "Fullscreen: Off" if event.type == pygame.QUIT: print(volume, keys, fullscreen) for key in keys: print(key, pygame.key.name(keys[key])) pygame.quit() exit() pygame.display.update(update_rects) update_rects = []