def OfflinePauseMenu(mainGame, screen, clock): save_file_box = TextBox( (340, 300, 560, 50), clear_on_enter=False, inactive_on_enter=False, active=False, active_color=pygame.Color( "red")) #Create text box for storing save file path save_file_box.buffer = list( mainGame.save_path ) #list() is used to convert string into array of characters music_box = pygame.Rect(100, 200, 40, 40) font_48 = pygame.font.SysFont( 'Arial', 48) #Fonts used for texts, of various sizings font_60 = pygame.font.SysFont('Arial', 60) font_40 = pygame.font.SysFont('Arial', 40) font_28 = pygame.font.SysFont('Arial', 28) enable_txt = "Enable" if mainGame.autosave: enable_txt = "Disable" pause_buts = [ Button(150, 425, 300, 80, "Save and Exit", font_40), Button(600, 425, 300, 80, "Exit Without Saving", font_40), Button(75, 620, 400, 80, "Save and Restart", font_40), Button(550, 620, 400, 80, "Restart Without Saving", font_40), Button(750, 10, 200, 80, "Resume", font_60), Button(910, 300, 90, 50, "Change", font_28), Button(910, 360, 90, 50, enable_txt, font_28) ] msgBox = None #Will become MessageBox object as required pause_title = font_60.render("The Game is Paused", True, (0, 0, 0)) #Generate text for titles settings_txt = font_60.render("Settings:", True, (0, 0, 0)) #Settings sub-heading toggle_txt = font_48.render("Toggle Background Music", True, (0, 0, 0)) #Text next to check box save_txt = font_60.render("Save Game:", True, (0, 0, 0)) #Save Game sub-heading save_file_txt = font_48.render("Save File Path:", True, (0, 0, 0)) #Title of save path text box new_txt = font_60.render("New Game:", True, (0, 0, 0)) #New game sub-heading autosave_txt = [ font_48.render("Autosave is currently off", True, (0, 0, 0)), font_48.render("Autosave is currently on", True, (0, 0, 0)) ] music_box_click = False pause_menu_running = True while pause_menu_running: for event in pygame.event.get(): for but in pause_buts: but.handle_input_event(event) if msgBox != None: #If a MessageBox has been created msgBox.handle_input_event(event) if msgBox.should_exit == False: break #Exit for loop; do not register any other objects if event.type == pygame.QUIT: pause_menu_running = False gotoScreen = -1 if event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: #Escape key exits the game pause_menu_running = False #This screen will no longer run gotoScreen = -1 #Game will completely exit if event.type == pygame.MOUSEBUTTONDOWN: if event.button == 1: #Left mouse button if music_box.collidepoint( event.pos ): #Check box for toggling background music music_box_click = True save_file_box.get_event( event ) #Function that allows each textbox to register key presses and the like screen.fill((255, 255, 255)) #Clear the screen pygame.draw.rect(screen, (0, 0, 0), pygame.Rect(50, 20, 20, 60)) #Rectangles for pause symbol pygame.draw.rect(screen, (0, 0, 0), pygame.Rect(80, 20, 20, 60)) screen.blit(pause_title, [120, 10]) screen.blit(settings_txt, [10, 110]) pygame.draw.rect(screen, (0, 0, 0), music_box, 2) #Display blank check box if not mainGame.pause: #If music is unpaused, check box needs to be checked pygame.draw.line( screen, (0, 0, 0), [102, 220], [115, 238], 4) #Display two lines corresponding to the two parts of a tick pygame.draw.line(screen, (0, 0, 0), [115, 238], [145, 195], 4) screen.blit(toggle_txt, [150, 190]) screen.blit(save_txt, [10, 240]) screen.blit(save_file_txt, [30, 300]) screen.blit(new_txt, [10, 550]) save_file_box.update() #Update the textbox based on events save_file_box.draw(screen) #Draw the text box and contents on screen screen.blit(autosave_txt[int(mainGame.autosave)], [30, 360]) if pause_buts[5].clicked(): #Button for updating save file path valid = True #Whether the file path entered is valid if save_file_box.getContents()[-3:].lower( ) != "dfo": #Must have correct file ending, or invalid msgBox = MessageBox( screen, 'Invalid file. Please ensure the entered file has the correct .dfo file ending.', 'File Error') valid = False #Path is not valid as wrong file ending if valid: try: os.makedirs(os.path.dirname(save_file_box.getContents()), exist_ok=True) f = open(save_file_box.getContents(), 'w+') except: #Any error occurs in creating the directory or file msgBox = MessageBox( screen, 'Invalid save file entered. Please ensure the path entered exists and you have permissions to access it (the file does not have to)', 'Invalid Save File') valid = False #Path is not valid as cannot be created without error if valid: mainGame.save_path = save_file_box.getContents( ) #Update save file within the Game object mainGame.saveGame() #Save the game in the newly entered file if pause_buts[6].clicked( ): #Button for toggling autosave feature on/off mainGame.autosave = not mainGame.autosave #Toggle the boolean value of autosave if mainGame.autosave: pause_buts[6].updateCap("Disable") else: pause_buts[6].updateCap("Enable") if pause_buts[0].clicked(): #Save and Exit mainGame.saveGame() #Save game pause_menu_running = False #This screen no longer running gotoScreen = -1 #Don't go to any other screen (i.e. exit completely) if pause_buts[1].clicked(): #Exit without saving pause_menu_running = False #This screen no longer running gotoScreen = -1 #Don't go to any other screen (i.e. exit completely) if pause_buts[2].clicked(): #Save and restart mainGame.saveGame() #Save the game pause_menu_running = False #This screen no longer running gotoScreen = 0 if pause_buts[3].clicked(): #Restart without saving pause_menu_running = False #This screen no longer running gotoScreen = 0 #Goto new game screen if pause_buts[4].clicked(): #Resume pause_menu_running = False gotoScreen = 1 if music_box_click: #Check box for background music if mainGame.pause: #Music is currently paused pygame.mixer.music.unpause() #Unpause music else: #Music is currently unpaused pygame.mixer.music.pause() #Pause music mainGame.pause = not mainGame.pause #Toggle state of pause in Game class if msgBox != None: #If a MessageBox has been created msgBox.update() #Update message box with relevant events if msgBox.should_exit == False: #If message box should be showing msgBox.draw(screen) #Draw message box on screen for but in pause_buts: but.render(screen) music_box_click = False clock.tick(10) #10 fps pygame.display.flip() #Refresh screen return mainGame, gotoScreen #Pass the Game object and the integer storing where the game will go to next back out to the main game loop
def NewNet(screen, clock): font_48 = pygame.font.SysFont('Arial', 48) font_40 = pygame.font.SysFont('Arial', 40) font_28 = pygame.font.SysFont('Arial', 28) pieces_x = 350 pieces_y = 450 name_box = TextBox((320, 400, 380, 50), clear_on_enter=False, inactive_on_enter=True, active=True, active_color=pygame.Color("red")) name_text = font_48.render("Enter your Name (max 12 characters):", True, (0, 0, 0)) n_width, n_height = font_48.size("Enter your Name (max 12 characters):") name_button = Button(400, 460, 200, 80, "Confirm", font_48) ready_up_but = Button(400, 460, 200, 80, "Ready Up", font_48) start_game_but = Button(400, 460, 200, 80, "Start Game", font_48) ready_up_but.hideBut() start_game_but.hideBut() piece_rects = [None] * 6 piece_imgs_lobby = [None] * 6 for n in range(6): piece_rects[n] = pygame.Rect(pieces_x + 110 * (n % 3), pieces_y + 110 * int(n / 3), 100, 100) piece_imgs_lobby[n] = pygame.transform.smoothscale( pygame.image.load("img/Pieces/" + str(n + 1) + ".png"), [30, 30]) choose_text = font_40.render("Choose Your Piece:", True, (0, 0, 0)) pieces_large = np.array([None] * 6) #Load 6 available player pieces for p_counter in range(6): pieces_large[p_counter] = pygame.transform.smoothscale( pygame.image.load("img/Pieces/" + str(p_counter + 1) + ".png"), [100, 100]) #Load image into pygame and resize # Read in host (server) IP and port from file. # This means that the server IP and port do not have to be hard-coded. f = open("data/Host_Data.txt", "r") host_dat = f.readline().split(",") # Some setup code that was previously run while the screen was active. # Having it here instead streamlines things a bit. ip_text = font_48.render( "Your IP: " + socket.gethostbyname(socket.gethostname()), True, (0, 0, 0)) lobby = Pyro4.Proxy("PYRO:dfo.game@" + host_dat[0] + ":" + host_dat[1]) # Okay, this is actually a Game() class object, but the Lobby() part is the only part actually used here, # and I wrote everything here with lobby separate first, so why bother changing it? ready_up_texts = [ font_48.render("Waiting for players to ready up.", True, (0, 0, 0)), font_48.render("Waiting for players to ready up..", True, (0, 0, 0)), font_48.render("Waiting for players to ready up...", True, (0, 0, 0)) ] waiting_texts = [ font_48.render("Waiting to start.", True, (0, 0, 0)), font_48.render("Waiting to start..", True, (0, 0, 0)), font_48.render("Waiting to start...", True, (0, 0, 0)) ] newnet_running = True piece_choice = -1 piece_chosen = False name_chosen = False ready_up = False start_game = False while newnet_running: for event in pygame.event.get(): if name_box.visible: name_box.get_event(event) name_button.handle_input_event(event) ready_up_but.handle_input_event(event) start_game_but.handle_input_event(event) if event.type == pygame.QUIT: newnet_running = False gotoScreen = -1 if event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: #Escape key exits the game newnet_running = False #This screen will no longer run gotoScreen = -1 #Game will completely exit if event.type == pygame.MOUSEBUTTONDOWN: if event.button == 1: #Left mouse button if not piece_chosen and name_chosen: for n in range(6): if piece_rects[n].collidepoint(event.pos): piece_choice = n screen.fill((255, 255, 255)) if not name_box.visible: #Player has entered name; show lobby and following game setup screen.blit(ip_text, [10, 10]) screen.blit(host_text, [10, 60]) renderLobby(screen, lobby, 10, 110, font_40, font_28, piece_imgs_lobby) if not piece_chosen: renderPieces(screen, pieces_large, lobby, pieces_x, pieces_y, choose_text) ready_up_but.render(screen) start_game_but.render(screen) if ready_up and not start_game and not lobby.allReadyUp(): screen.blit( ready_up_texts[int(pygame.time.get_ticks() / 500) % 3], [235, 460]) if start_game and not lobby.allReadyToStart(): screen.blit( waiting_texts[int(pygame.time.get_ticks() / 500) % 3], [375, 460]) if name_box.visible: #Player is entering name name_box.update() name_box.draw(screen) name_button.render(screen) screen.blit(name_text, [(1024 - n_width) / 2, 335]) if name_button.clicked(): #Determine if the name entered is valid. Will try and do something to prevent duplicate naming... if len(name_box.getContents()) <= 12 and len( name_box.getContents()) != 0: #Name is valid #Display your IP and name, and connect to server using Pyro4 module host_text = font_48.render( "Your Name: " + name_box.getContents(), True, (0, 0, 0)) lobby.connect(socket.gethostbyname(socket.gethostname()), name_box.getContents()) name_box.hide() name_chosen = True name_button.hideBut() if piece_choice != -1 and name_chosen: if not (piece_choice + 1 in lobby.getUsedPieces()): lobby.setPiece(socket.gethostbyname(socket.gethostname()), piece_choice + 1) piece_chosen = True ready_up_but.showBut() piece_choice = -1 if ready_up_but.clicked(): lobby.readyUp(socket.gethostbyname(socket.gethostname())) ready_up = True ready_up_but.hideBut() if start_game_but.clicked(): lobby.readyToStart(socket.gethostbyname(socket.gethostname())) start_game = True start_game_but.hideBut() if not start_game and name_chosen and not start_game_but.visible and ready_up: if lobby.allReadyUp() and dim( lobby.getLobby() )[0] >= 2: #May not proceed until at least two players have joined start_game_but.showBut() if start_game and name_chosen and ready_up: if lobby.allReadyToStart() and dim(lobby.getLobby( ))[0] >= 2: #At least two players required for a game (duh!) #Creation of localGame object first players = createLocalPlayers( pieces_large, lobby.getLobby()) #Create array of LocalPlayer objects prop_arr = createLocalProperties( "data/Property Values.txt" ) #Create array of Property objects Pot_Luck_Deck = createLocalDeck("Pot Luck", "img/PL/Pot Luck ", "data/Card_Texts.txt", "data/PL Master.txt", 16) #Create Card_Deck object Council_Chest_Deck = createLocalDeck( "Council Chest", "img/CC/Council Chest ", "data/Card_Texts.txt", "data/CC Master.txt", 16) #Create Card_Deck object game_board = createLocalBoard("data/Board_Data.txt", prop_arr, Pot_Luck_Deck, Council_Chest_Deck, "img/Board.png", 600) #Create Board object this_player_num = findPlayerNum(lobby) localGame = createLocalGame( players, game_board, "img/Dice/", this_player_num ) #Finally create the single, cohesive Game object that is the sole purpose of this screen/part of the game if lobby.getGameSetup() == False: fh = open("data/Property Values.txt", "r") prop_data = fh.read() lobby.setupGame(prop_data) newnet_running = False gotoScreen = 6 clock.tick(10) #10 fps pygame.display.flip() #Refresh screen return lobby, localGame, gotoScreen