def start(self, screen): if self.already_loaded: return # Spawn a new thread to load all resources Thread(target=self.load_assets).start() width = screen.get_width() height = screen.get_height() # Meanwhile create a label to show that the game is loading text_rect = pygame.rect.Rect(width / 2 - 100, height / 2 - 25, 200, 50) self.loading_text = Label(text_rect, "Loading...", { Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.BORDER_WIDTH: 0, }) # Also create an image to display a rotate animation image_rect = pygame.rect.Rect(width / 2 - 50, height / 2 + 50, 75, 75) self.loading_circle = Image(image_rect, None, { Options.BACKGROUND: (82, 173, 200) }) self.already_loaded = True
def get_hp_bar(self): hp_parts = int(self.hp / self.max_hp * 20) left = Back.RED + " " * hp_parts lost = Back.WHITE + " " * (20 - hp_parts) hp_bar = f"HP:{left}{lost}" return Image([hp_bar, ])
def start(self, screen): if not self.already_loaded: width = screen.get_width() height = screen.get_height() self.header = Label(pygame.Rect(width / 2 - 75, height * 1 / 5 + 10, 150, 50), "Game Paused", options={ Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.BORDER_WIDTH: 0, }) self.back_btn = Button( pygame.Rect(width * 1 / 5 + 10, height * 1 / 5 + 10, 60, 40), "Back", { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.FONT: pygame.font.SysFont("Comic Sans MS", 15) }) self.forfeit_btn = Button( pygame.Rect(width / 2 - 75, height / 2, 150, 40), "Forfeit", { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.FONT: pygame.font.SysFont("Comic Sans MS", 25) }) settings_gear_image = Resources.get("gear") settings_gear_rect = pygame.rect.Rect(width * 4 / 5 - 100, height * 4 / 5 - 100, 75, 75) self.settings_btn = Image( settings_gear_rect, settings_gear_image, { Options.BACKGROUND: (20, 61, 89), Options.HOVERED_BACKGROUND: (10, 30, 45) }) self.already_loaded = True if self.last_scene_id != Scene.scene_stack[-2]: self.last_scene_id = Scene.scene_stack[-2] self.underlay_screen = screen.copy() dark_cover = pygame.Surface( self.underlay_screen.get_size()).convert_alpha( self.underlay_screen) dark_cover.fill((0, 0, 0, 0.6 * 255)) self.underlay_screen.blit(dark_cover, (0, 0))
def start(self, screen): if self.already_loaded: return width = screen.get_width() height = screen.get_height() self.title = Label(pygame.rect.Rect(width / 2 - 200, height / 7, 400, 60), "Python Penfight!", options={ Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.BORDER_WIDTH: 4, Options.FONT: pygame.font.SysFont("Comic Sans MS", 40, bold=True, italic=False) }) btn_rect = pygame.rect.Rect(width / 2 - 125, height / 2 - 50, 250, 30) btn_options = { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.FONT: pygame.font.SysFont("Comic Sans MS", 25), } self.play_btn = Button(btn_rect, "Play", btn_options) self.stats_btn = Button(btn_rect.copy().move(0, 75), "Stats", btn_options) self.about_btn = Button(btn_rect.copy().move(0, 150), "About", btn_options) settings_gear_image = Resources.get("gear") settings_gear_rect = pygame.rect.Rect(width - 100, height - 100, 75, 75) self.settings_btn = Image( settings_gear_rect, settings_gear_image, { Options.BACKGROUND: (20, 61, 89), Options.HOVERED_BACKGROUND: (10, 30, 45) }) close_image = Resources.get("close") close_rect = pygame.rect.Rect(width - 75, 25, 50, 50) self.close_btn = Image( close_rect, close_image, { Options.BACKGROUND: (200, 0, 0), Options.HOVERED_BACKGROUND: (100, 0, 0) }) self.back_btn = Button( pygame.rect.Rect(10, 10, 60, 40), "Back", { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.FONT: pygame.font.SysFont("Comic Sans MS", 15) }) self.already_loaded = True
gravity = 0.98 - altitude / 1000 minGravity = 0.1 maxGravity = 1.1 minItemSpawnRate = 0.2 maxItemSpawnRate = 4 # for spawning enemies after a certain number of frames enemyFrameCount = 0 itemFrameCount = 0 maxAltitude = 0 # GUI items # title screen and help screen titleRect = SIZE[0] // 2 - 200, 100, 400, 100 titleBanner = Image(titleRect, titleImage) playButton = Image((200, 200, 240, 240), sprites[21]) playHitRect = playButton.rect[0], playButton.rect[1] + 40, playButton.rect[ 2], playButton.rect[3] - 60 quitButton = Image((SIZE[0] - 200 - 240, 200, 240, 240), sprites[23]) quitHitRect = quitButton.rect[0], quitButton.rect[1] + 40, quitButton.rect[ 2], quitButton.rect[3] - 60 helpImage = Image((0, 0, SIZE[0], SIZE[1]), helpScreenImage) okButton = Image((550, SIZE[1] - 240, 240, 240), sprites[25]) okHitRect = okButton.rect[0], okButton.rect[1] + 40, okButton.rect[ 2], okButton.rect[3] - 60 numTitleClouds = 20
def start(self, screen): width = screen.get_width() height = screen.get_height() if self.already_loaded: btn_options = { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), } del_btn_options = { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (200, 20, 40), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (150, 5, 20), } original_names = [btn.text for btn in self.account_btns] account_names = Account.get_account_names() for name in original_names: if name not in account_names: btn_to_delete = self.account_btns[[ idx for idx, btn in enumerate(self.account_btns) if btn.text == name ][0]] self.account_btns.remove(btn_to_delete) self.delete_btns.pop(btn_to_delete) for name in account_names: if name not in original_names: btn = Button(pygame.rect.Rect(0, 0, 0, 0), name, btn_options) self.account_btns.append(btn) del_btn = Button(pygame.rect.Rect(0, 0, 30, 30), "X", del_btn_options) self.delete_btns[btn] = del_btn self.account_btns.sort(key=(lambda btn: btn.text)) else: self.header = Label(pygame.rect.Rect(width / 2 - 200, 10, 400, 30), "Select account to load", options={ Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.BORDER_WIDTH: 0, }) close_image = Resources.get("close") close_rect = pygame.rect.Rect(width - 75, 25, 50, 50) self.close_btn = Image( close_rect, close_image, { Options.BACKGROUND: (200, 0, 0), Options.HOVERED_BACKGROUND: (100, 0, 0) }) self.no_account_text = Label( pygame.rect.Rect(width / 2 - 350, height / 2, 550, 30), "No account created. Click the New button to make one.", options={ Options.BACKGROUND: (82, 173, 200), Options.FOREGROUND: (20, 61, 89), Options.BORDER_WIDTH: 0, }) self.first_offset = pygame.rect.Rect(width / 2 - 125, 75, 250, 30) btn_options = { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), } del_btn_options = { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (200, 20, 40), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (150, 5, 20), } account_names = Account.get_account_names() for name in account_names: btn = Button(pygame.rect.Rect(0, 0, 0, 0), name, btn_options) self.account_btns.append(btn) del_btn = Button(pygame.rect.Rect(0, 0, 30, 30), "X", del_btn_options) self.delete_btns[btn] = del_btn btn_options = { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.FONT: pygame.font.SysFont("Comic Sans MS", 15) } self.up_btn = Button( pygame.rect.Rect(width * 5 / 6, height * 2 / 6, 60, 40), "Up", btn_options) self.create_btn = Button( pygame.rect.Rect(width * 5 / 6, height * 3 / 6 - 20, 60, 40), "New", btn_options) self.down_btn = Button( pygame.rect.Rect(width * 5 / 6, height * 4 / 6 - 40, 60, 40), "Down", btn_options) self.already_loaded = True Account.current_account = None self.btn_index = 0 self.reposition_buttons()
class LoadingScene(Scene): loaded = False loading_text = None circle_image = None loading_circle = None circle_angle = 0 def start(self, screen): if self.already_loaded: return # Spawn a new thread to load all resources Thread(target=self.load_assets).start() width = screen.get_width() height = screen.get_height() # Meanwhile create a label to show that the game is loading text_rect = pygame.rect.Rect(width / 2 - 100, height / 2 - 25, 200, 50) self.loading_text = Label(text_rect, "Loading...", { Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.BORDER_WIDTH: 0, }) # Also create an image to display a rotate animation image_rect = pygame.rect.Rect(width / 2 - 50, height / 2 + 50, 75, 75) self.loading_circle = Image(image_rect, None, { Options.BACKGROUND: (82, 173, 200) }) self.already_loaded = True def load_assets(self): # Load the circle loading animation Resources.add("loading", pygame.image.load("assets/loading.png")) self.circle_image = Resources.get("loading") # Load the settings gear icon Resources.add("gear", pygame.image.load("assets/gear.png")) # Load the close icon Resources.add("close", pygame.image.load("assets/close.png")) # Load the coin image Resources.add("coin", pygame.image.load("assets/coin.png")) # Load the random pen image Resources.add("random_pen", pygame.image.load("assets/random_pen.png")) # Load the pen data and images Resources.add("all_pens", Resources.load_text("assets/pens.json")) Resources.add("pencil", pygame.image.load("assets/pencil.png")) Resources.add("ball_pen", pygame.image.load("assets/ball_pen.png")) Resources.add("blue_gel_pen", pygame.image.load("assets/blue_gel_pen.png")) Resources.add("black_gel_pen", pygame.image.load("assets/black_gel_pen.png")) Resources.add("mech_pencil", pygame.image.load("assets/mech_pencil.png")) Resources.add("marker", pygame.image.load("assets/marker.png")) self.loaded = True def update(self, event): # If the circle loading image has been loaded then use it for the animation if (self.loading_circle.image is None) and (self.circle_image is not None): self.loading_circle.image = self.circle_image def draw(self, screen): screen.fill((82, 173, 200)) # Wait if the loading has not finished if not self.loaded: self.loading_text.draw(screen) # Rotate the image to show a loading animation self.loading_circle.draw(screen) if self.loading_circle.image is not None: self.loading_circle.image = pygame.transform.rotate(self.circle_image, self.circle_angle) self.circle_angle = -(pygame.time.get_ticks() % 360) # If loading has finished, then go to account loading else: Scene.push_scene(1)
def start(self, screen): if not self.already_loaded: PenData.load_all_pens(Resources.get("all_pens")) width = screen.get_width() height = screen.get_height() self.back_btn = Button( pygame.Rect(10, 10, 60, 40), "Back", { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.FONT: pygame.font.SysFont("Comic Sans MS", 15) }) label_options = { Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.BORDER_WIDTH: 0, } self.header = Label(pygame.Rect(width / 2 - 200, 10, 400, 30), "Select your weapon!", label_options) self.coins_text = Label( pygame.Rect(width - 110, height - 55, 100, 40), "0", label_options) label_options = { Options.BACKGROUND: (82, 173, 200), Options.FOREGROUND: (20, 61, 89), Options.BORDER_WIDTH: 0, Options.FONT: pygame.font.SysFont("Comic Sans MS", 18) } self.density_text = Label(pygame.Rect(width / 5, 110, 100, 20), "Density: ", label_options) self.restitution_text = Label(pygame.Rect(width / 5, 130, 100, 20), "Restitution: ", label_options) self.name_text = Label( pygame.Rect(width / 2 - 45, height - 125, 90, 50), "", label_options) self.description_lines = [ Label(pygame.Rect(width * 2 / 3, 100 + i * 25, 100, 20), "", label_options) for i in range(0, 3) ] self.coins_image = Image( pygame.Rect(width - 175, height - 60, 50, 50), Resources.get("coin"), {Options.BACKGROUND: (82, 173, 200)}) btn_options = { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.FONT: pygame.font.SysFont("Comic Sans MS", 25) } self.left_btn = Button(pygame.Rect(10, height / 2 - 20, 20, 30), "<", btn_options) self.right_btn = Button( pygame.Rect(width - 30, height / 2 - 20, 20, 30), ">", btn_options) self.select_btn = Button( pygame.Rect(width / 2 - 45, height - 75, 90, 50), "Select", btn_options) self.purchase_btn = Button( pygame.Rect(width / 2 - 125, height - 75, 250, 40), "", btn_options) self.center_pos = pygame.Rect(width / 2 - 50, height / 2 - 50, 100, 100) for pen in PenData.all_pens: self.pen_images.append( Image(self.center_pos, Resources.get(pen.image_file), {Options.BACKGROUND: (82, 173, 200)})) self.already_loaded = True self.reposition_images() self.update_shop_data() self.reset_coin_text()
def start(self, screen): if not self.already_loaded: PenData.load_all_pens() width = screen.get_width() height = screen.get_height() self.back_btn = Button( pygame.Rect(10, 10, 60, 40), "Back", { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.FONT: pygame.font.SysFont("Comic Sans MS", 15) }) self.header = Label( pygame.Rect(width / 2 - 200, 10, 400, 30), "Choose your opponent!", { Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.BORDER_WIDTH: 0, }) self.name_text = Label( pygame.Rect(width / 2 - 45, height - 125, 90, 50), "", { Options.BACKGROUND: (82, 173, 200), Options.FOREGROUND: (20, 61, 89), Options.BORDER_WIDTH: 0, Options.FONT: pygame.font.SysFont("Comic Sans MS", 18) }) btn_options = { Options.BORDER_WIDTH: 0, Options.BACKGROUND: (20, 61, 89), Options.FOREGROUND: (244, 180, 26), Options.HOVERED_BACKGROUND: (10, 30, 45), Options.FONT: pygame.font.SysFont("Comic Sans MS", 25) } self.left_btn = Button(pygame.Rect(10, height / 2 - 20, 20, 30), "<", btn_options) self.right_btn = Button( pygame.Rect(width - 30, height / 2 - 20, 20, 30), ">", btn_options) self.select_btn = Button( pygame.Rect(width / 2 - 45, height - 75, 90, 50), "Select", btn_options) btn_options[Options.TOGGLED_BACKGROUND] = (5, 20, 30) self.random_diff_btn = ToggleButton( pygame.Rect(width * 1 / 5 - 50, 100, 100, 30), "Random", btn_options) self.easy_btn = ToggleButton( pygame.Rect(width * 2 / 5 - 50, 100, 100, 30), "Easy", btn_options) self.normal_btn = ToggleButton( pygame.Rect(width * 3 / 5 - 50, 100, 100, 30), "Normal", btn_options) self.hard_btn = ToggleButton( pygame.Rect(width * 4 / 5 - 50, 100, 100, 30), "Hard", btn_options) toggle_group = [ self.random_diff_btn, self.easy_btn, self.normal_btn, self.hard_btn ] for elt in toggle_group: elt.set_group(toggle_group) self.easy_btn.toggle() self.center_pos = pygame.Rect(width / 2 - 50, height / 2 - 50, 100, 100) self.random_pen_data = PenData.dict_to_pen({ "name": "Random", "image_file": "random_pen" }) for pen in [self.random_pen_data] + PenData.all_pens: self.pen_images.append( Image(self.center_pos, Resources.get(pen.image_file), {Options.BACKGROUND: (82, 173, 200)})) self.already_loaded = True self.reposition_images() self.update_enemy_data()