class CarShape(): """Defines a shape object to be used for drawing the corresponding Car object with the same index""" def __init__(self, index, window, car): self.index = index self.window = window self.x = car.x self.y = car.y self.color = "white" self.height = car.height self.width = car.width self.direction = 0 # car shape must be a polygon because rectangles are represented as two points # which prevents proper rotations and translations center = Point(self.x, self.y) p1 = (self.x - (self.width / 2), self.y - (self.height / 2)) p2 = (self.x + (self.width / 2), self.y - (self.height / 2)) p3 = (self.x + (self.width / 2), self.y + (self.height / 2)) p4 = (self.x - (self.width / 2), self.y + (self.height / 2)) points = [p1, p2, p3, p4] self.shape = Polygon(center, points) self.shape.setFill(self.color) def draw(self): self.shape.draw(self.window) def render(self): dx = self.x - self.shape.center.x dy = self.y - self.shape.center.y self.rotate(dx, dy) self.shape.move(dx, dy) def rotate(self, dx, dy): if dx == 0 and dy == 0: return new_direction = math_utils.degrees_clockwise(dx, dy) degrees = float(self.direction - new_direction) if abs(degrees) > 5: self.shape.rotate(degrees) self.direction = new_direction def clicked(self, p): x_points = [point[0] for point in self.shape.points] y_points = [point[1] for point in self.shape.points] xmin = min(x_points) xmax = max(x_points) ymin = min(y_points) ymax = max(y_points) return (xmin <= p.getX() <= xmax and ymin <= p.getY() <= ymax)
def pause_menu(right): start = 500 if right else 0 prior = len(gw.items) pause_overlay = Image(Point(500, 250), MAP / "pause_overlay.png") pause_overlay.draw(gw) # Everything for the Character Information info_box = Rectangle(Point(551 - start, 100), Point(959 - start, 400)) info_box.setFill(color_rgb(50, 50, 50)) info_box.setWidth(3) info_box.draw(gw) # The Character Icon info_icon = Image(Point(613 - start, 163), MAPS / "characters" / f"{player.character_class}_portrait.png") info_icon.draw(gw) # Shows the Header that includes the player's name and level. info_header = Text(Point(572 - start, 179)) info_header.setAnchor("w") info_header.setSize(22) info_header.setText(f" {player.name + f'LV: {player.lvl}'.rjust(16)[len(player.name):]}\n HP:\n EXP:\nItems:") info_header.draw(gw) # Draw the HP bar. hp_bar = Bar(player.current_HP, player.base_HP, "red", Point(750 - start, 149), Point(948 - start, 173)) hp_bar.show() # Draws the EXP bar exp_bar = Bar(player.current_EXP, player.next_EXP, "green", Point(750 - start, 179), Point(948 - start, 203)) exp_bar.show() # Lists off the player's current inventory. info_header_underline = Line(Point(573 - start, 240), Point(937 - start, 240)) info_header_underline.setWidth(1) info_header_underline.setOutline("white") info_header_underline.draw(gw) info_footer = Text(Point(573 - start, 246)) info_footer.setAnchor("nw") info_footer.setSize(14) info_footer.setText(inventory()) info_footer.draw(gw) # Lists off the pause menu options. choice_box = Rectangle(Point(start + 125, 165), Point(start + 370, 335)) choice_box.setFill(color_rgb(50, 50, 50)) choice_box.setWidth(3) choice_box.draw(gw) choice_text = Text(Point(start + 260, 250)) choice_text.setAnchor("c") choice_text.setSize(20) choice_text.setText("Resume\nDrink Potion\nEat Apple\nSave Game\nQuit Game") choice_text.draw(gw) selector = Polygon(Point(start + 137, 183), Point(start + 137, 195), Point(start + 154, 189)) selector.setFill("red") selector.draw(gw) selection = 0 saved = False while True: while True: key = gw.checkKey().lower() if key != "": if key in ["space", "return"]: break elif key in ["escape"]: while selection > 0: selector.move(0, -30) selection -= 1 if key in ["up", "w", "left", "a"]: selection = (selection - 1) % 5 if selection != 4: selector.move(0, -30) else: selector.move(0, 120) elif key in ["down", "s", "right", "d"]: selection = (selection + 1) % 5 if selection != 0: selector.move(0, 30) else: selector.move(0, -120) # Resume Game if selection == 0: for i in gw.items[prior:]: i.undraw() return # Drink Potion if selection == 1: if player.items["Potions"] == 0: dialogue("You have no more potions to drink.", right=right) elif player.current_HP == player.base_HP: dialogue("You are already at max HP", right=right) else: player.items["Potions"] -= 1 player.current_HP += round(randint(4, 10) * 4.2) if player.current_HP > player.base_HP: player.current_HP = player.base_HP hp_bar.update(player.current_HP, player.base_HP) # Eat Apple if selection == 2: if player.items["Apples"] == 0: dialogue("You have no more apples to eat.", right=right) elif player.current_HP == player.base_HP: dialogue("You are already at max HP", right=right) else: player.items["Apples"] -= 1 player.current_HP += randint(1, 4) if player.current_HP > player.base_HP: player.current_HP = player.base_HP hp_bar.update(player.current_HP, player.base_HP) # Save Game if selection == 3: saved = True save_state = open("save_state.txt", "w") stats_to_save = [player.character_class, player.name, player.lvl, player.attack, player.defense, player.current_HP, player.base_HP, player.current_SP, player.base_SP, player.current_EXP, player.next_EXP, player.gold, player.items, game_stats ] line_to_save = '' for i in stats_to_save: line_to_save = line_to_save + str(i) + "\n" save_state.write(b64encode(line_to_save.encode("UTF-8")).decode("UTF-8")) save_state.close() dialogue("Game saved.", right=right) # Quit Game if selection == 4: if not saved: dialogue(f"You have not saved recently.") if dialogue("Are you sure you want to quit?", ["Yes", "No"], right=right) == 0: raise GameOver('Town Quit') info_footer.setText(inventory())
def dialogue(line, choices = [], color=["white"], return_arg=False, right=False, speed=.02, type_length=0): # Initialize variables that will be used later. start = 500 if right else 0 selection = 0 prior = len(gw.items) if type(color) == str: color=[color] # Create the dialogue box dialogue_box = Rectangle(Point(start + 11, 403), Point(start + 489, 488)) dialogue_box.setFill(color_rgb(50, 50, 50)) dialogue_box.setWidth(3) dialogue_box.draw(gw) # Create the Text objects that will display dialogue. texts = [] for i in color: text = Text(Point(start + 25, 418), "") text.setTextColor(i) text.setSize(20) text.setAnchor("nw") text.draw(gw) texts.append(text) line = line.split() text_num = 0 num_texts = len(texts) line_length = 0 overflow = 0 skip = False for word in line: word_length = len(word) if line_length + word_length + 1 > 29: word = '\n' + word line_length = 0 overflow += 1 line_length += word_length + 1 if overflow > 1: for j in texts: j.setText(j.getText()[j.getText().index("\n") + 1:]) overflow = 1 for j in word + ' ': if j == '`': text_num += 1 else: for k in range(num_texts): key = gw.checkKey().lower() if key in ["return", "space", "escape"]: skip = True if k == text_num: texts[k].setText(texts[k].getText() + j) elif j == '\n': texts[k].setText(texts[k].getText() + '\n') else: texts[k].setText(texts[k].getText() + ' ') if not skip: sleep(speed) # If type_length is 0 and the array of choices that is passed in isn't empty, the player is supposed # to make a selection from a list of choices. length_choices = len(choices) if type_length == 0: center = 374 - (30 * (length_choices - 1)) selector = Polygon(Point(start + 478, center - 6), Point(start + 478, center + 6), Point(start + 461, center)) selector.setFill("red") if length_choices > 0: answer = "" longest_answer = 0 for i in choices: answer += f"{i}\n" longest_answer = max(longest_answer, len(i)) answer = answer[:-1] choice_box = Rectangle(Point(start + 473 - (16 * (longest_answer + 2)), 382 - (30 * length_choices)), Point(start + 489, 395)) choice_box.setFill(color_rgb(50, 50, 50)) choice_box.setWidth(3) choice_box.draw(gw) choice_text = Text(Point(start + 453, 390), "") choice_text.setAnchor("se") choice_text.setJustification("right") choice_text.setSize(20) choice_text.draw(gw) choice_text.setText(answer) selector.draw(gw) while True: key = gw.checkKey().lower() if key != "": if key in ["space", "return"]: break elif key in ["escape"]: while selection < length_choices - 1: selector.move(0, 30) selection += 1 elif key in ["m", "shift_l"]: pause_menu(not right) elif length_choices > 0: if key in ["up", "w", "left", "a"]: selection = (selection - 1) % length_choices if selection != length_choices - 1: selector.move(0, -30) else: selector.move(0, 30 * (length_choices - 1)) elif key in ["down", "s", "right", "d"]: selection = (selection + 1) % length_choices if selection != 0: selector.move(0, 30) else: selector.move(0, -30 * (length_choices - 1)) # Else, the player is typing in some response. # This is only used a couple times in play_game.py elif type_length > 0: selection = "" shown_name = Text(Point(250 - (16 * type_length) // 2, 467)) shown_name.setText("") shown_name.draw(gw) text_underline = shown_name.clone() text_underline.setText("-" * type_length) text_underline.move(0, 13) text_underline.draw(gw) bar = shown_name.clone() bar.move(-7, 0) bar.setText('|') bar.draw(gw) bar_flash = 0 bar_shown = True while True: key = gw.checkKey() if key: if len(selection) < type_length and key in alphabet + punctuation: if key == 'space': selection += ' ' else: selection += key bar.move(16, 0) elif len(selection) > 0 and key == 'BackSpace': selection = selection[:-1] bar.move(-16, 0) elif key == 'Return': break bar_flash = 0 if not bar_shown: bar_shown = True bar.draw(gw) shown_name.setText(selection) else: bar_flash += 1 if bar_flash == 40000: bar_flash = 0 if bar_shown: bar_shown = False bar.undraw() else: bar_shown = True bar.draw(gw) gw.clear(prior) if length_choices == 0 and type_length == 0: return -1 elif return_arg: return choices[selection].split(":")[0] else: return selection
def endGame(field, game_panel, player_name, score): # Let the user know the game is finished end_game_text = Text(Point(200, 200), "Finished! Click to close") end_game_text.draw(field) # Draw graphic objects at different places that represent balloons with a # string connected to it. balloon_1 = Circle(Point(145, 110), 18) balloon_1.setFill("red") balloon_1.setOutline("red") balloon_1.draw(field) triangle_1 = Polygon(Point(137, 135), Point(145, 128), Point(153, 135)) triangle_1.setFill("red") triangle_1.setOutline('red') triangle_1.draw(field) string_1 = Line(Point(145, 135), Point(145, 180)) string_1.draw(field) balloon_2 = Circle(Point(340, 300), 18) balloon_2.setFill("red") balloon_2.setOutline("red") balloon_2.draw(field) triangle_2 = Polygon(Point(332, 325), Point(340, 318), Point(348, 325)) triangle_2.setFill("red") triangle_2.setOutline('red') triangle_2.draw(field) string_2 = Line(Point(340, 325), Point(340, 370)) string_2.draw(field) balloon_3 = Circle(Point(75, 275), 18) balloon_3.setFill("red") balloon_3.setOutline("red") balloon_3.draw(field) triangle_3 = Polygon(Point(67, 300), Point(75, 293), Point(83, 300)) triangle_3.setFill("red") triangle_3.setOutline('red') triangle_3.draw(field) string_3 = Line(Point(75, 300), Point(75, 345)) string_3.draw(field) # Create a while loop that moves the objets every 0.05 seconds upwards to # make it appear as if they are floating while True: sleep(0.05) balloon_1.move(0, -10) triangle_1.move(0, -10) string_1.move(0, -10) balloon_2.move(0, -10) triangle_2.move(0, -10) string_2.move(0, -10) balloon_3.move(0, -10) triangle_3.move(0, -10) string_3.move(0, -10) # If a click is detetced in the field, the window will close even if the # balloons are still moving in the while loop click = field.checkMouse() if click != None: break # Add player score to top_scores.txt writeScores(player_name, score) # Set close condition to True close = True # Return close condition return close