def __init__(self, x, y, screen_size, title, level=0): super().__init__(x, y, "assets/ui/upgrades_bar.png", screen_size, convert_alpha=True) self.title_text = title self.level = level self.price = (self.level + 1) * 100 self.font = pygame.font.SysFont("cambriacambriamath", 32) self.title = self.font.render( f"{title} ({self.price if self.level < 5 else 'max'})", True, (0, 0, 0)) self.title_pos = [ x + (self.image.get_width() - self.title.get_width()) // 2, y ] self.rect.y = y + self.title.get_height() + 10 self.plus_button = StaticGameObject(x, y, "assets/ui/plus_button.png", screen_size, convert_alpha=True) self.plus_button.set_pos((self.rect.right - self.plus_button.rect.w, y + self.title.get_height() + 11)) self.colors = ((253, 245, 66), (251, 216, 8), (255, 144, 5), (249, 83, 11), (255, 0, 0)) if level > 0: self.progress_rect = pygame.Rect( self.x + 12, self.y + 11, 20 * self.level + 9 * (self.level - 1), 30)
class Slider(StaticGameObject): """Класс для создания слайдера""" def __init__(self, x, y, screen_size): super().__init__(x, y, "assets/ui/slider_bg.png", screen_size) self.handle = StaticGameObject(self.rect.center[0] - 20, y - 2, "assets/ui/slider_fg.png", screen_size) self.value = 1 # [0; 2] def clicked(self, pos: tuple[int, int]): return self.handle.collidepoint(pos) def process_drag(self, drag: tuple[int, int]): if self.x < self.handle.x + drag[ 0] < self.x + self.rect.w - self.handle.rect.w: self.handle.set_pos((self.handle.x + drag[0], self.handle.y)) self.value = (self.handle.rect.center[0] + drag[0] - self.x) / self.rect.w * 2 def draw(self, win: pygame.Surface): win.blit(self.image, self.rect) win.blit(self.handle.image, self.handle.rect) def set_value(self, new_value: float): if 0 <= new_value <= 2: self.value = new_value x_pos = int(self.rect.w / 2 * new_value + self.handle.rect.w / 2) self.handle.set_pos((x_pos, self.handle.y))
def __init__(self, display: pygame.Surface, manager, fps=60): super(ShopMenu, self).__init__(display, manager, fps) self.load_upgrades_levels() self.update_sound_volume() self.font = pygame.font.SysFont("cambriacambriamath", 32) self.menu_button = StaticGameObject(50, 525, "assets/ui/menu_button.png", self.size, convert_alpha=True) self.items = ((ShopItem(75, 25, self.size, "Magnet", level=self.magnet_level), self.MAGNET_KEY), (ShopItem(75, 150, self.size, "Shield", level=self.shield_level), self.SHIELD_KEY), (ShopItem(75, 275, self.size, "Hat", level=self.hat_level), self.HAT_KEY), (ShopItem(75, 400, self.size, "Jetpack", level=self.jetpack_level), self.JETPACK_KEY), (ShopItem(325, 25, self.size, "Damage", level=self.damage_level), self.DAMAGE_KEY), (ShopItem(325, 150, self.size, "Reload", level=self.reload_level), self.RELOAD_KEY), (ShopItem(325, 275, self.size, "Jump", level=self.jump_level), self.JUMP_KEY), (ShopItem(325, 400, self.size, "Rocket", level=self.rocket_level), self.ROCKET_KEY)) self.click_sound = pygame.mixer.Sound("assets/sounds/button_press.wav") self.upgrade_sound = pygame.mixer.Sound( "assets/sounds/upgrade_unlock.wav") self.background = pygame.image.load("assets/ui/shop_bg.jpg").convert() self.click_sound.set_volume(0.4 * self.volume_ratio) self.upgrade_sound.set_volume(0.3 * self.volume_ratio)
class ShopItem(StaticGameObject): """Класс для создания предметов магазина""" def __init__(self, x, y, screen_size, title, level=0): super().__init__(x, y, "assets/ui/upgrades_bar.png", screen_size, convert_alpha=True) self.title_text = title self.level = level self.price = (self.level + 1) * 100 self.font = pygame.font.SysFont("cambriacambriamath", 32) self.title = self.font.render( f"{title} ({self.price if self.level < 5 else 'max'})", True, (0, 0, 0)) self.title_pos = [ x + (self.image.get_width() - self.title.get_width()) // 2, y ] self.rect.y = y + self.title.get_height() + 10 self.plus_button = StaticGameObject(x, y, "assets/ui/plus_button.png", screen_size, convert_alpha=True) self.plus_button.set_pos((self.rect.right - self.plus_button.rect.w, y + self.title.get_height() + 11)) self.colors = ((253, 245, 66), (251, 216, 8), (255, 144, 5), (249, 83, 11), (255, 0, 0)) if level > 0: self.progress_rect = pygame.Rect( self.x + 12, self.y + 11, 20 * self.level + 9 * (self.level - 1), 30) def draw(self, win: pygame.Surface): if self.level > 0: pygame.draw.rect(win, self.colors[self.level - 1], self.progress_rect) win.blit(self.title, self.title_pos) win.blit(self.image, self.rect) win.blit(self.plus_button.image, self.plus_button.rect) def add_level(self): if self.level < 5: self.level += 1 self.price = (self.level + 1) * 100 self.title = self.font.render( f"{self.title_text} ({self.price if self.level < 5 else 'max'})", True, (0, 0, 0)) self.title_pos[0] = self.x + (self.image.get_width() - self.title.get_width()) // 2 self.progress_rect = pygame.Rect( self.x + 12, self.y + 11, 20 * self.level + 9 * (self.level - 1), 30) def clicked(self, position): """метод для проверки нажатия на кнопку""" return self.plus_button.collidepoint(position)
def __init__(self, display, manager, fps): super(PauseMenu, self).__init__(display, manager, fps) self.background = pygame.image.load("assets/ui/pause_bg.png").convert() self.continue_button = StaticGameObject( 228, 300, "assets/ui/continue_button.png", self.size) self.menu_button = StaticGameObject(228, 375, "assets/ui/menu_button.png", self.size) self.update_sound_volume() self.click_sound = pygame.mixer.Sound("assets/sounds/click.wav") self.click_sound.set_volume(min(0.6 * self.volume_ratio, 1))
class MainMenu(GameScene): """Класс для создания главного меню (пока пустой)""" def __init__(self, display: pygame.Surface, manager, fps=60): super(MainMenu, self).__init__(display, manager, fps) self.update_sound_volume() self.background = pygame.image.load( "assets/ui/main_menu_bg.jpg").convert() self.play_button = StaticGameObject(400, 125, "assets/ui/play_button.png", self.size) self.shop_button = StaticGameObject(400, 200, "assets/ui/shop_button.png", self.size) self.settings_button = StaticGameObject( 400, 275, "assets/ui/settings_button.png", self.size) self.click_sound = pygame.mixer.Sound("assets/sounds/button_press.wav") self.click_sound.set_volume(0.4 * self.volume_ratio) def redraw(self, win): win.blit(self.background, (0, 0)) win.blit(self.play_button.image, self.play_button.rect) win.blit(self.shop_button.image, self.shop_button.rect) win.blit(self.settings_button.image, self.settings_button.rect) def handle_events(self): for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() exit() if event.type == pygame.MOUSEBUTTONDOWN: if self.play_button.collidepoint(event.pos): self.manager.load_scene(1) self.click_sound.play() self.close() if self.shop_button.collidepoint(event.pos): self.manager.load_scene(4) self.click_sound.play() self.close() if self.settings_button.collidepoint(event.pos): self.manager.load_scene(6) self.click_sound.play() self.close() def show(self): self.update_sound_volume() self.click_sound.set_volume(0.4 * self.volume_ratio) super().show()
def __init__(self, display, manager, fps): super().__init__(display, manager, fps) self.update_sound_volume() self.background = pygame.image.load("assets/ui/shop_bg.jpg").convert() self.menu_button = StaticGameObject(50, 525, "assets/ui/menu_button.png", self.size) self.sliders = (Slider(50, 75, self.size), Slider(50, 195, self.size), Slider(50, 315, self.size)) self.font = pygame.font.SysFont("cambriacambriamath", 38) self.volume_text = self.font.render("Volume", True, (0, 0, 0)) self.music_text = self.font.render("Music", True, (0, 0, 0)) self.particles_text = self.font.render("Particles", True, (0, 0, 0)) self.active_slider = 0 self.is_drag = False self.PARTICLES_KEY = "particles" self.VOLUME_KEY = "volume" self.MUSIC_KEY = "music" self.click_sound = pygame.mixer.Sound("assets/sounds/button_press.wav") self.click_sound.set_volume(0.4 * self.volume_ratio)
def __init__(self, display: pygame.Surface, manager, fps=60): super(GameOverMenu, self).__init__(display, manager, fps) self.score = 0 self.highscore = 0 self.font = pygame.font.SysFont("cambriacambriamath", 40) self.sub_font = pygame.font.SysFont("cambriacambriamath", 30) self.restart_button = StaticGameObject(228, 230, "assets/ui/restart_button.png", self.size, convert_alpha=True) self.menu_button = StaticGameObject(228, 300, "assets/ui/menu_button.png", self.size, convert_alpha=True) self.continue_button = StaticGameObject( 210, 480, "assets/ui/continue_button.png", self.size, convert_alpha=True) self.background = pygame.image.load( "assets/ui/game_over_bg.jpg").convert() self.revive_dialog = pygame.image.load( "assets/ui/revive_dialog.png").convert_alpha() self.update_sound_volume() self.click_sound = pygame.mixer.Sound("assets/sounds/click.wav") self.click_sound.set_volume(min(0.6 * self.volume_ratio, 1)) self.revive_price = 250 self.revive_countdown = 5 * self.FPS self.revive_happened = False self.draw_revive = False self.money_collected = 0
class PauseMenu(GameOverMenu): """Класс для создания меню паузы""" def __init__(self, display, manager, fps): super(PauseMenu, self).__init__(display, manager, fps) self.background = pygame.image.load("assets/ui/pause_bg.png").convert() self.continue_button = StaticGameObject( 228, 300, "assets/ui/continue_button.png", self.size) self.menu_button = StaticGameObject(228, 375, "assets/ui/menu_button.png", self.size) self.update_sound_volume() self.click_sound = pygame.mixer.Sound("assets/sounds/click.wav") self.click_sound.set_volume(min(0.6 * self.volume_ratio, 1)) def handle_events(self): for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() exit() if event.type == pygame.MOUSEBUTTONDOWN: if self.continue_button.collidepoint(event.pos): self.manager.load_scene(3, clear_groups=False) self.close() if self.menu_button.collidepoint(event.pos): self.manager.load_scene(0) self.close() def redraw(self, win: pygame.Surface): win.blit(self.background, (50, 50)) win.blit(self.continue_button.image, self.continue_button.rect) win.blit(self.menu_button.image, self.menu_button.rect) def show(self): self.update_sound_volume() self.click_sound.set_volume(min(0.6 * self.volume_ratio, 1)) super().show()
def __init__(self, display: pygame.Surface, manager, fps=60): super(MainMenu, self).__init__(display, manager, fps) self.update_sound_volume() self.background = pygame.image.load( "assets/ui/main_menu_bg.jpg").convert() self.play_button = StaticGameObject(400, 125, "assets/ui/play_button.png", self.size) self.shop_button = StaticGameObject(400, 200, "assets/ui/shop_button.png", self.size) self.settings_button = StaticGameObject( 400, 275, "assets/ui/settings_button.png", self.size) self.click_sound = pygame.mixer.Sound("assets/sounds/button_press.wav") self.click_sound.set_volume(0.4 * self.volume_ratio)
def __init__(self, x, y, screen_size): super().__init__(x, y, "assets/ui/slider_bg.png", screen_size) self.handle = StaticGameObject(self.rect.center[0] - 20, y - 2, "assets/ui/slider_fg.png", screen_size) self.value = 1 # [0; 2]
class SettingsMenu(GameScene): """Класс для создания меню настроек""" def __init__(self, display, manager, fps): super().__init__(display, manager, fps) self.update_sound_volume() self.background = pygame.image.load("assets/ui/shop_bg.jpg").convert() self.menu_button = StaticGameObject(50, 525, "assets/ui/menu_button.png", self.size) self.sliders = (Slider(50, 75, self.size), Slider(50, 195, self.size), Slider(50, 315, self.size)) self.font = pygame.font.SysFont("cambriacambriamath", 38) self.volume_text = self.font.render("Volume", True, (0, 0, 0)) self.music_text = self.font.render("Music", True, (0, 0, 0)) self.particles_text = self.font.render("Particles", True, (0, 0, 0)) self.active_slider = 0 self.is_drag = False self.PARTICLES_KEY = "particles" self.VOLUME_KEY = "volume" self.MUSIC_KEY = "music" self.click_sound = pygame.mixer.Sound("assets/sounds/button_press.wav") self.click_sound.set_volume(0.4 * self.volume_ratio) def handle_events(self): for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() exit() if event.type == pygame.MOUSEBUTTONDOWN: for index, slider in enumerate(self.sliders): if slider.clicked(event.pos): self.is_drag = True self.active_slider = index break if self.menu_button.collidepoint(event.pos): self.click_sound.play() self.manager.load_scene(0) self.close() if event.type == pygame.MOUSEBUTTONUP and self.is_drag: self.is_drag = False self.apply_settings(self.sliders[self.active_slider].value) if event.type == pygame.MOUSEMOTION and self.is_drag: self.sliders[self.active_slider].process_drag(event.rel) def redraw(self, win): win.blit(self.background, (0, 0)) win.blit(self.volume_text, (50, 15)) win.blit(self.music_text, (50, 140)) win.blit(self.particles_text, (50, 265)) for slider in self.sliders: slider.draw(win) win.blit(self.menu_button.image, self.menu_button.rect) def apply_settings(self, new_value): if self.active_slider == 0: self.set_game_value(self.VOLUME_KEY, new_value) elif self.active_slider == 1: self.set_game_value(self.MUSIC_KEY, new_value) elif self.active_slider == 2: self.set_game_value(self.PARTICLES_KEY, new_value) def show(self): for index, key in enumerate( (self.VOLUME_KEY, self.MUSIC_KEY, self.PARTICLES_KEY)): if (value := self.get_game_value(key)) != -1: self.sliders[index].set_value(value) self.update_sound_volume() self.click_sound.set_volume(0.4 * self.volume_ratio) super().show()
class ShopMenu(GameScene): """Класс для создания магазина""" def __init__(self, display: pygame.Surface, manager, fps=60): super(ShopMenu, self).__init__(display, manager, fps) self.load_upgrades_levels() self.update_sound_volume() self.font = pygame.font.SysFont("cambriacambriamath", 32) self.menu_button = StaticGameObject(50, 525, "assets/ui/menu_button.png", self.size, convert_alpha=True) self.items = ((ShopItem(75, 25, self.size, "Magnet", level=self.magnet_level), self.MAGNET_KEY), (ShopItem(75, 150, self.size, "Shield", level=self.shield_level), self.SHIELD_KEY), (ShopItem(75, 275, self.size, "Hat", level=self.hat_level), self.HAT_KEY), (ShopItem(75, 400, self.size, "Jetpack", level=self.jetpack_level), self.JETPACK_KEY), (ShopItem(325, 25, self.size, "Damage", level=self.damage_level), self.DAMAGE_KEY), (ShopItem(325, 150, self.size, "Reload", level=self.reload_level), self.RELOAD_KEY), (ShopItem(325, 275, self.size, "Jump", level=self.jump_level), self.JUMP_KEY), (ShopItem(325, 400, self.size, "Rocket", level=self.rocket_level), self.ROCKET_KEY)) self.click_sound = pygame.mixer.Sound("assets/sounds/button_press.wav") self.upgrade_sound = pygame.mixer.Sound( "assets/sounds/upgrade_unlock.wav") self.background = pygame.image.load("assets/ui/shop_bg.jpg").convert() self.click_sound.set_volume(0.4 * self.volume_ratio) self.upgrade_sound.set_volume(0.3 * self.volume_ratio) def redraw(self, win): win.blit(self.background, (0, 0)) win.blit(self.menu_button.image, self.menu_button.rect) for item, _ in self.items: item.draw(win) money = self.font.render(f"{self.get_game_value(self.MONEY_KEY)}$", True, (0, 0, 0)) win.blit(money, (self.size[0] - money.get_width() - 50, 535)) def handle_events(self): for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() exit() if event.type == pygame.MOUSEBUTTONDOWN: if self.menu_button.collidepoint(event.pos): self.manager.load_scene(0) self.click_sound.play() self.close() for item, key in self.items: if item.clicked(event.pos): self.purchase_upgrade(key, item) def purchase_upgrade(self, key, item): """метод для покупки улучшения""" if (money := self.get_game_value(self.MONEY_KEY)) != -1: if money >= item.price and item.level < 5: self.set_game_value(self.MONEY_KEY, money - item.price) item.add_level() self.set_game_value(key, item.level) self.upgrade_sound.play()
class GameOverMenu(GameScene): """Класс для создание меню после проигрыша""" def __init__(self, display: pygame.Surface, manager, fps=60): super(GameOverMenu, self).__init__(display, manager, fps) self.score = 0 self.highscore = 0 self.font = pygame.font.SysFont("cambriacambriamath", 40) self.sub_font = pygame.font.SysFont("cambriacambriamath", 30) self.restart_button = StaticGameObject(228, 230, "assets/ui/restart_button.png", self.size, convert_alpha=True) self.menu_button = StaticGameObject(228, 300, "assets/ui/menu_button.png", self.size, convert_alpha=True) self.continue_button = StaticGameObject( 210, 480, "assets/ui/continue_button.png", self.size, convert_alpha=True) self.background = pygame.image.load( "assets/ui/game_over_bg.jpg").convert() self.revive_dialog = pygame.image.load( "assets/ui/revive_dialog.png").convert_alpha() self.update_sound_volume() self.click_sound = pygame.mixer.Sound("assets/sounds/click.wav") self.click_sound.set_volume(min(0.6 * self.volume_ratio, 1)) self.revive_price = 250 self.revive_countdown = 5 * self.FPS self.revive_happened = False self.draw_revive = False self.money_collected = 0 def redraw(self, win): win.blit(self.background, (50, 50)) highscore = self.font.render(f"Highscore: {self.highscore}", True, "black") current_score = self.font.render(f"Score: {self.score}", True, "black") money = self.font.render(f"Money collected: {self.money_collected}", True, "black") win.blit(highscore, ((self.size[0] - highscore.get_width()) // 2, 65)) win.blit(current_score, ((self.size[0] - current_score.get_width()) // 2, 115)) win.blit(money, ((self.size[0] - money.get_width()) // 2, 165)) win.blit(self.restart_button.image, self.restart_button.rect) win.blit(self.menu_button.image, self.menu_button.rect) if self.draw_revive: self.draw_revive_dialog(win) def handle_events(self): for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() exit() if event.type == pygame.MOUSEBUTTONDOWN: if self.restart_button.collidepoint(event.pos): self.manager.load_scene(1) self.click_sound.play() self.revive_happened = False self.close() if self.menu_button.collidepoint(event.pos): self.manager.load_scene(0) self.click_sound.play() self.revive_happened = False self.close() if self.draw_revive and self.continue_button.collidepoint( event.pos): self.manager.load_scene(3) self.update_money(-self.revive_price) self.revive_happened = True self.click_sound.play() self.close() def set_score(self, score: int): """Метод для установки счета игры""" self.score = score self.update_highscore(score) def update_highscore(self, new_highscore: int): """метод для обновления рекорда по окончанию игры""" if (score := self.get_game_value( self.HIGHSCORE_KEY)) != -1 and new_highscore > score: self.set_game_value(self.HIGHSCORE_KEY, new_highscore) self.highscore = new_highscore else: