def getUsername(screen, backgroundColor, settings): done = False clock = pygame.time.Clock() oldWidth = screen.get_rect().width oldHeight = screen.get_rect().height nameBox = TextBox(fontName = settings['fontName']) screen = pygame.display.set_mode((nameBox.width, nameBox.height), 0, 32) while not done: clock.tick(60) events = pygame.event.get() for event in events: if event.type == pygame.QUIT: pygame.quit() quit() if event.type == pygame.KEYDOWN: if event.key == pygame.K_RETURN: done = True nameBox.update(events) screen.fill(backgroundColor) nameBox.render(screen) pygame.display.flip() screen = pygame.display.set_mode((oldWidth, oldHeight), 0, 32) return nameBox.inputString
class Stopwatch: def __init__(self, resources: Resources) -> None: self.ticks = -1 self.last_finish = -1 self.best_finish = -1 font = FontManager(resources.get_path("DejaVuSans.ttf"), size=28) white = Color(r=255, g=255, b=255) self.timer_textbox = TextBox(font, 50, 100, white) self.best_time_textbox = TextBox(font, 50, 150, white) def reset(self) -> None: self.ticks = -1 self.last_finish = -1 def start(self) -> None: self.ticks = 0 def stop(self) -> None: if self.ticks >= 0: self.last_finish = self.ticks self.ticks = -1 if self.best_finish < 0 or self.last_finish < self.best_finish: self.best_finish = self.last_finish def step(self) -> None: if self.ticks >= 0: self.ticks += 1 def render(self, renderer: Renderer) -> None: if self.ticks >= 0: self.timer_textbox.text = format_time_exact(self.ticks) self.timer_textbox.render(renderer) elif self.last_finish >= 0: self.timer_textbox.text = "Finished in: " + format_time_exact( self.last_finish) self.timer_textbox.render(renderer) if self.best_finish >= 0: self.best_time_textbox.text = "Best time: " + format_time_exact( self.best_finish) self.best_time_textbox.render(renderer)
class Interface: # Initialisation de l'interface graphique def __init__(self, name, width, height): self.width = width self.height = height screen_size = (width, height) pygame.init() pygame.display.set_caption(name) self.screen = pygame.display.set_mode(screen_size) self.clock = pygame.time.Clock() self.running = False self.row = 10 self.column = 10 self.pad = 100 self.maze_screen = 500 self.cell_size = min(self.maze_screen / self.row, self.maze_screen / self.column) self.maze = Maze(self.row, self.column) self.text_box = TextBox(675, 150, 250, 100, '10x10') self.generate_button = Button(gray, 675, 300, 250, 100, "Generate") self.solve_button = Button(gray, 675, 450, 250, 100, "Solve") self.player = Player(0, 0) # Permet de faire démarrer le programme et de faire exécuter le code a chaque frame (évenements, graphisme...) def start(self): self.running = True while self.running: self.clock.tick(30) self.event() self.render() # Permet de quitter le programme def stop(self): self.running = False pygame.quit() # Met à jour la taille du labyrinthe par rapport à l'input de l'utilisateur def update_maze(self): text = self.text_box.text x, y = text.split('x') self.row = int(x) self.column = int(y) # Un écouteur d'évenements (listener) pour exécuter des actions spécifiques def event(self): for event in pygame.event.get(): if event.type == pygame.QUIT: self.stop() if event.type == pygame.MOUSEBUTTONUP: if event.button == pygame.BUTTON_LEFT: if self.generate_button.is_hovering( pygame.mouse.get_pos()): self.update_maze() self.cell_size = min(self.maze_screen / self.row, self.maze_screen / self.column) self.maze = Maze(self.row, self.column) self.maze.generate_maze() self.player = Player() if self.solve_button.is_hovering(pygame.mouse.get_pos()): self.maze.solve_maze() if event.type == pygame.KEYDOWN: point = self.maze.get_point(self.player.get_x(), self.player.get_y()) if event.key == pygame.K_DOWN and not point.have_wall('S'): self.player.down() if event.key == pygame.K_UP and not point.have_wall('N'): self.player.up() if event.key == pygame.K_LEFT and not point.have_wall('W'): self.player.left() if event.key == pygame.K_RIGHT and not point.have_wall('E'): self.player.right() if event.key == pygame.K_BACKSPACE: self.text_box.text = self.text_box.text[:-1] else: self.text_box.text += event.unicode # Permet de rendre le programme graphiquement en général def render(self): if self.running: self.screen.fill(white) self.render_button() self.render_text_box() self.render_maze() pygame.draw.circle( self.screen, green, (self.cell_size * self.player.get_x() + self.pad + self.cell_size / 2, self.cell_size * self.player.get_y() + self.pad + self.cell_size / 2), 8) pygame.display.flip() # Permet de rendre graphiquement le labyrinthe uniquement def render_maze(self): for point in self.maze.get_solution(): pygame.draw.circle( self.screen, blue, (self.cell_size * point.get_x() + self.pad + self.cell_size / 2, self.cell_size * point.get_y() + self.pad + self.cell_size / 2), 8) rows_size = len(self.maze.get_grid()) for rows in range(rows_size): for point in self.maze.get_grid()[rows]: start_x, start_y = point.get_x( ) * self.cell_size + self.pad, point.get_y( ) * self.cell_size + self.pad end_x, end_y = ( point.get_x() + 1) * self.cell_size + self.pad, ( point.get_y() + 1) * self.cell_size + self.pad if point.have_wall('S'): self.draw_wall(start_x, end_y, end_x, end_y) if point.have_wall('E'): self.draw_wall(end_x, start_y, end_x, end_y) if point.is_start_point(): pygame.draw.circle( self.screen, green, (self.cell_size * point.get_x() + self.pad + self.cell_size / 2, self.cell_size * point.get_y() + self.pad + self.cell_size / 2), 10) if point.is_exit_point(): pygame.draw.circle( self.screen, red, (self.cell_size * point.get_x() + self.pad + self.cell_size / 2, self.cell_size * point.get_y() + self.pad + self.cell_size / 2), 10) self.draw_wall(self.pad, self.pad, self.cell_size * self.row + self.pad, self.pad) self.draw_wall(self.pad, self.pad, self.pad, self.cell_size * self.column + self.pad) # Permet de rendre les boutons uniquement def render_button(self): self.generate_button.render(self.screen, (0, 0, 0)) self.solve_button.render(self.screen, (0, 0, 0)) mouse_pos = pygame.mouse.get_pos() if self.generate_button.is_hovering(mouse_pos): self.generate_button.color = light_blue else: self.generate_button.color = gray if self.solve_button.is_hovering(mouse_pos): self.solve_button.color = light_blue else: self.solve_button.color = gray # Permet de rendre l'entrée de texte uniquement def render_text_box(self): self.text_box.render(self.screen) # Permet de dessiner un mur pour plus de simplicité lors de la génération du labyrinthe def draw_wall(self, start_x, start_y, end_x, end_y, thickness=5): start_point = (start_x, start_y) end_point = (end_x, end_y) pygame.draw.line(self.screen, black, start_point, end_point, thickness)
class DateChoose(): def __init__(self, font_name=None, desc_font_size=25, desc_font_color=(255,255,255), exit_pos=(540,500), bg_img=None, textbox_pos=(0, 530), textbox_size=(500, 50) ): """Select from 6 tiled pictures of locations where a date can take place. \ Displays gold cost under each tile. Deducts gold and initiates dating sequence when \ player clicks on a valid tile.""" self.bg_img = bg_img or None self.font_name = font_name self.desc_font_size = desc_font_size self.desc_font_color = desc_font_color self.desc_font = pygame.font.Font(font_name, desc_font_size) self.tiles = pygame.sprite.Group() tileStartX, tileStartY = 10, 0 positions = ([[tileStartX + i*Tile.SIZE_X, tileStartY] for i in range(3)] + [[tileStartX + i*Tile.SIZE_X, tileStartY + Tile.SIZE_Y] for i in range(3)]) def make_tile(name, cost, img_key, loc_key): pos = positions.pop(0) tile = Tile(name, cost, img_key, loc_key, pos) self.tiles.add(tile) def on_click(): print("You clicked on {}".format(tile.name)) self.done = True self.success = True self.loc_name = tile.name self.cost = tile.cost self.loc_key = tile.loc_key def on_hover(): self.changeText("{} -- cost: {} gold".format(name, cost)) def on_unhover(): self.changeText("") tile.on_click = on_click tile.on_hover = on_hover tile.on_unhover = on_unhover make_tile("Beach of the East", 500, "TILE_beach_east", "beach_east") make_tile("Beach of the West", 500, "TILE_beach_west", "beach_west") make_tile("Arcade", 1000, "TILE_arcade", "arcade") make_tile("Hot Springs", 2000, "TILE_springs", "springs") def on_click(): self.done = True self.exit_btn = BlockButton(on_click, datingsim.COLOR_D, (110, 50), exit_pos, "Back") self.textbox = TextBox("", textbox_pos, textbox_size, frame_color=(230, 40, 0)) # TODO: note that frame_color here isn't doing anything. self.buttons = pygame.sprite.Group() self.buttons.add(self.exit_btn) self.all_sprites = pygame.sprite.Group() self.all_sprites.add(self.tiles) self.all_sprites.add(self.textbox) self.all_sprites.add(self.buttons) self.main_surface = pygame.display.get_surface() self.done = False self.curr_tile = None self.success = False # whether a choice was made def changeText(self, text): """render changed text if necessary""" self.textbox.text = text self.textbox.render() print("Text changed to {}.".format(text)) def main_loop(self): while not self.done: for e in pygame.event.get(): if e.type is pygame.QUIT: pygame.quit() datingsim.quit() quit() elif e.type is pygame.MOUSEMOTION: for tile in self.tiles: if tile.rect.collidepoint(e.pos): if (tile != self.curr_tile): tile.on_hover() self.curr_tile = tile elif tile == self.curr_tile: # didn't collide with curr_tile tile.on_unhover() self.curr_tile = None elif e.type is pygame.MOUSEBUTTONDOWN: if self.curr_tile != None: self.curr_tile.on_click() for button in self.buttons: if button.rect.collidepoint(e.pos): button.on_click() if self.bg_img: self.main_surface.blit(self.bg_img, [0,0]) else: self.main_surface.fill((0, 0, 0)) self.all_sprites.update() self.all_sprites.draw(self.main_surface) pygame.display.flip() pygame.time.wait(1000//20) self.ath() def ath(self): pass @staticmethod def test(): instance = DateChoose() instance.main_loop() if instance.success: print("You chose {}.".format(instance.loc_name)) print("The location key of your choice is {}.".format(instance.loc_key)) print("The cost of this location is {}.".format(instance.cost)) else: print("No choice of location was made.")
class MeetScene: def __init__(self, gurl, bg_img=None, gurl_img_pos=(300, 300), textPos=(0,400), textSize=(180,280), use_default_buttons=True): self.gurl = gurl self.bg_img = bg_img self.gurl_img_pos = gurl_img_pos self.mood = "default" self.meet_advisor = MeetAdvisor(gurl) self.gurl_textbox = TextBox("filler", textPos, textSize) self.all_sprites = pygame.sprite.Group(self.meet_advisor, self.gurl_textbox) self.buttons = pygame.sprite.Group() prevx, prevy = None, 300 def make_button(name, on_click, size=(110, 50), color=datingsim.COLOR_A, dx=20): nonlocal prevx if prevx == None: x = dx else: x = prevx + dx + size[0] y = prevy b = BlockButton(on_click, color, pos=(x,y), size=size, text=name) prevx = x self.buttons.add(b) self.all_sprites.add(b) self.add_button = make_button if use_default_buttons: self.add_default_buttons() # make an exit button def on_exit_click(): import kitchen kitchen.remove_scene(self) print("exit click") self.done = True self.exit_button = BlockButton(on_exit_click, datingsim.COLOR_A, pos=(680,500), size=(110, 50), text="go back") self.buttons.add(self.exit_button) self.all_sprites.add(self.exit_button) self.done = False; self.main_surface = pygame.display.get_surface() def add_default_buttons(self): b_data = [("talk", self.select_talk), ("ask", self.select_ask), ("date", self.select_date), ("give", self.select_give)] clicked_status = [] i = 0 def make_one_time_button_action(on_first_click): nonlocal clicked_status, i # clicked_status[i] = False #==> list assignment out of range :P clicked_status.append(False) my_id = i i += 1 def on_click(): nonlocal clicked_status if clicked_status[my_id]: return else: # clicked_status[my_id] = True return on_first_click() return on_click for name, on_first_click in b_data: self.add_button(name, make_one_time_button_action(on_first_click)) def select_talk(self): msg = self.gurl.do_talk() self.update_conversation(msg) def select_ask(self): msg = self.gurl.do_ask() self.update_conversation(msg) def select_date(self): """This is a special case, because do_date() will either return a message to be shown, \ or return an instance of datechoose. """ result = self.gurl.do_date() if isinstance(result, str): self.update_conversation(result) elif isinstance(result, DateChoose): msg = "Wow, I sure will be excited to go to the {} when that feature \ is implemented!".format(result.loc_name) self.update_conversation(msg) import kitchen date_scene = DateScene(self.gurl, bg_img=datingsim.locs[result.curr_tile.loc_key].bg_img) kitchen.push_scene(date_scene) self.done = True else: raise Error("Invalid result {} from gurl.do_date()!".format(result)) def select_give(self): msg = self.gurl.do_give() self.update_conversation(msg) def ath(self): for s in self.all_sprites: s.kill() def get_gurl_img(self): if self.mood in self.gurl.img_dict: return self.gurl.img_dict[self.mood] elif 'default' in self.gurl.img_dict: return self.gurl.img_dict['default'] else: # just return any image for img in self.gurl.img_dict.values(): return img def change_mood(self, new_mood): if new_mood in self.gurl.img_dict: self.mood = new_mood def update_conversation(self, text): self.gurl_textbox.text = text; self.gurl_textbox.render() def main_loop(self): while not self.done: for event in pygame.event.get(): if event.type is pygame.QUIT: self.done = True # datingsim.quit() # pygame.quit() # implement button fade on mouse hover # make this part of button class default?? elif event.type is pygame.MOUSEBUTTONDOWN: for button in self.buttons: if button.rect.collidepoint(event.pos): button.on_click() if self.bg_img: self.main_surface.blit(self.bg_img, (0, 0)) else: self.main_surface.fill((0, 0, 0)) self.main_surface.blit(self.get_gurl_img(), self.gurl_img_pos) self.all_sprites.update() self.all_sprites.draw(self.main_surface) pygame.display.flip() pygame.time.wait(1000//20) @staticmethod def test_instantiate(): pygame.init() datingsim.init() gurl = Gurl("Rudy", None, None) gurl.exp = 2000 d = MeetScene(gurl) @staticmethod def test_run_test_buttons(): pygame.init() datingsim.init() gurl_imgs = {} gurl_imgs['askance'] = datingsim.assets.get_img_safe('GURL_kanaya_askance') gurl_imgs['happy'] = datingsim.assets.get_img_safe('GURL_kanaya_smile') gurl = Gurl("Kanaya", gurl_imgs, None) gurl.exp = 3998 d = MeetScene(gurl, use_default_buttons=False) d.add_button("test button", lambda: print("test 1")) def finish(): d.done = True d.add_button("end", finish) d.add_button("update conv", lambda: d.update_conversation("changed")) def increase_exp(): d.gurl.exp += 1 d.add_button("increase exp", increase_exp) d.add_button("happy", lambda: d.change_mood("happy")) d.add_button("askance", lambda: d.change_mood("askance")) d.main_loop() d.ath() datingsim.quit() pygame.quit() @staticmethod def test_run(): pygame.init() datingsim.init() gurl_imgs = {} gurl_imgs['askance'] = datingsim.assets.get_img_safe('GURL_kanaya_askance') gurl_imgs['happy'] = gurl_imgs['default'] = datingsim.assets.get_img_safe('GURL_kanaya_smile') ask_data = None quiz_data = None gurl = Isadora() gurl.exp = 3998 d = MeetScene(gurl) d.main_loop() d.ath() datingsim.quit() pygame.quit()