def message_box(self, title, text, on_close=None, font_size=22): def modal_done(on_close): if self.modal and on_close: on_close(self.modal) self.modal = None if not self.modal: self.modal = MessageBox(title, text, on_close=lambda *_: modal_done(on_close), font_size=font_size)
def MainScreen(mainGame, screen, clock): mainGame.prop_thumbs = pygame.transform.smoothscale( CreateThumbs(mainGame.board, mainGame.cur_player), [385, 170]) roll_dice_button = pygame.Rect( 180, 610, 150, 70) #Create rectangle for roll dice/end turn button buy_prop_button = pygame.Rect( 675, 690, 250, 70 ) #Create rectangle for property buying button (also used for mortgaging and unmortgaging buy_upgrade_button = pygame.Rect(350, 700, 150, 50) sell_upgrade_button = pygame.Rect(520, 700, 150, 50) in_jail_button = pygame.Rect(350, 610, 150, 70) TB_img = pygame.transform.smoothscale( pygame.image.load("img/Tower Block.png"), [75, 75]) CH_img = pygame.transform.smoothscale( pygame.image.load("img/Council House.png"), [75, 75]) font_40 = pygame.font.SysFont('Arial', 40) #Font object for button captions font_28 = pygame.font.SysFont( 'Arial', 28) #font object for displaying whose turn it is (among other things) font_20 = pygame.font.SysFont('Arial', 20) #Font for the upgrade buttons main_buts = [ Button(10, 690, 150, 70, "Leaderboards", font_28), Button(10, 610, 150, 70, "Pause", font_40), Button(900, 160, 100, 50, "Details", font_28) ] dice_but_click = False #Booleans tracking whether the roll dice, end turn and but property buttons have been clicked yet this turn turn_but_click = False buy_but_click = False mort_but_click = False buy_upgrade_but_click = False sell_upgrade_but_click = False leave_bogside_but_click = False use_card_but_click = False msgBox = None exitOnBoxClose = False advanceOnBoxClose = False fps = 10 #Used to determine the waiting between updating the game display main_screen_running = True while main_screen_running: for event in pygame.event.get(): for but in main_buts: but.handle_input_event(event) if msgBox != None: msgBox.handle_input_event(event) if exitOnBoxClose and msgBox.should_exit: main_screen_running = False gotoScreen = -1 if advanceOnBoxClose and msgBox.should_exit: mainGame.advancePlayer() mainGame.prop_thumbs = pygame.transform.smoothscale( CreateThumbs(mainGame.board, mainGame.cur_player), [385, 170] ) #Generate thumbnails for new player (here so it is only done when the player changes, not every frame change) advanceOnBoxClose = False if msgBox.should_exit == False: break if event.type == pygame.QUIT: main_screen_running = False gotoScreen = -1 if event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: #Escape key exits the game main_screen_running = False gotoScreen = -1 if event.type == pygame.MOUSEBUTTONDOWN: if event.button == 1: #Left mouse button mouse_pos = event.pos #Position of the cursor when nouse was clicked if buy_prop_button.collidepoint(mouse_pos): if mainGame.getCurProp( ).prop_owner == -1: #Property is unowned buy_but_click = True elif mainGame.getCurProp( ).prop_owner == mainGame.cur_player: #If owned by current player, it may be mortgaged mort_but_click = True if roll_dice_button.collidepoint(mouse_pos): if mainGame.controller.card_used == False: use_card_but_click = True #Roll dice button was clicked elif mainGame.controller.player_rolled == False: dice_but_click = True #End turn button was clicked else: turn_but_click = True #Button to apply card effects was clicked if in_jail_button.collidepoint( mouse_pos ): #Button to pay £50 to get out of bogside was clicked leave_bogside_but_click = True if buy_upgrade_button.collidepoint(mouse_pos): buy_upgrade_but_click = True if sell_upgrade_button.collidepoint(mouse_pos): sell_upgrade_but_click = True #Clear screen and display main board displayScreenAndBoard(screen, mainGame.board.board_img) if dice_but_click: #If Roll Dice button was clicked #Roll dice, move the piece accordingly, and display the dice rolls mainGame.getDie(0).roll() mainGame.getDie(1).roll() dice_total = mainGame.getDiceTotal() if mainGame.getCurPlayer().player_inJail == False: mainGame.getCurPlayer().movePlayer(dice_total, mainGame.board) elif mainGame.getDie(0).cur_score == mainGame.getDie( 1 ).cur_score: #Doubles rolled, so player gets out of bogside mainGame.getCurPlayer().leaveJail() mainGame.getCurPlayer().movePlayer(dice_total, mainGame.board) #Player does not move otherwise, as they must be lost in bogside #Generate the dice images mainGame.controller.roll_img1 = pygame.transform.smoothscale( mainGame.getDie(0).getImg(), [70, 70]) mainGame.controller.roll_img2 = pygame.transform.smoothscale( mainGame.getDie(1).getImg(), [70, 70]) if mainGame.getDie(0).cur_score != mainGame.getDie( 1 ).cur_score: #If a double has not been rolled (rolling a double gives the player another turn) mainGame.controller.player_rolled = True #So player only gets another turn if they rolled doubles mainGame.controller.may_buy = True if mainGame.getDie(0).cur_score == mainGame.getDie(1).cur_score: mainGame.controller.cur_doubles += 1 if mainGame.controller.cur_doubles >= 3: #If player rolls 3 consecutive doubles, they go to Bogside mainGame.sendCurPlayerToBog() mainGame.controller.player_rolled = True #Will not get to roll again #Determine rent if applicable mainGame.controller.turn_rent = mainGame.determineRent() if mainGame.controller.turn_rent != 0: mainGame.getCurPlayer().spendMoney( mainGame.controller.turn_rent ) #Decrease the player's money and credit the owner of the property that amount if mainGame.getCurProp().prop_type != Prop_Type.PAYMENT: mainGame.getPlayer( mainGame.getCurProp().prop_owner).addMoney( mainGame.controller.turn_rent) #If the current space returns a card if mainGame.getCurProp().prop_type == Prop_Type.POT_LUCK: mainGame.controller.cur_card = mainGame.board.PL_Deck.getNextCard( ) elif mainGame.getCurProp().prop_type == Prop_Type.COUNCIL_CHEST: mainGame.controller.cur_card = mainGame.board.CC_Deck.getNextCard( ) #If card will have just been returned, render the text that will show its effects if mainGame.getCurProp( ).prop_type == Prop_Type.POT_LUCK or mainGame.getCurProp( ).prop_type == Prop_Type.COUNCIL_CHEST: #Card will have been returned mainGame.controller.card_effs, mainGame.controller.card_texts = renderCardTexts( font_28, mainGame.controller.cur_card) mainGame.controller.card_used = False #If the player lands on the 'Go To Bogside' space if mainGame.getCurProp().prop_type == Prop_Type.GO_TO_BOGSIDE: mainGame.sendCurPlayerToBog() #Display whose turn it is, how much money this player has, and show their property overview displayWhoseTurn(screen, font_28, mainGame.getCurPlayer()) displayPlayerMoney(screen, font_28, mainGame.getCurPlayer().player_money) displayPlayerToken(screen, mainGame.getCurPlayer()) displayPropThumbs(screen, mainGame.prop_thumbs, 610, 50) displayDiceScore(screen, mainGame.controller.roll_img1, mainGame.controller.roll_img2) #Show each of the player's pieces at its requisite position on the board displayPieces(screen, mainGame) #Show the Roll Dice/End Turn button, and the appropriate caption if mainGame.controller.card_used == False: displayButtonRect(screen, roll_dice_button, (100, 100, 100), font_40, 'Use Card', (0, 0, 0)) elif mainGame.controller.player_rolled == False: displayButtonRect(screen, roll_dice_button, (100, 100, 100), font_40, 'Roll Dice', (0, 0, 0)) else: displayButtonRect(screen, roll_dice_button, (100, 100, 100), font_40, 'End Turn', (0, 0, 0)) if mainGame.getCurPlayer().player_inJail and mainGame.getCurPlayer( ).player_hasBogMap: #If player is lost in bogside, but they have the equivelant of a "Get out of Jail Free" card displayButtonRect(screen, in_jail_button, (100, 100, 100), font_28, 'Use Map', (0, 0, 0)) elif mainGame.getCurPlayer().player_inJail: #Don't have card displayButtonRect(screen, in_jail_button, (100, 100, 100), font_28, 'Buy Map (£50)', (0, 0, 0)) #Display title deed for property currently on if mainGame.getCurProp( ).prop_type == Prop_Type.NORMAL or mainGame.getCurProp( ).prop_type == Prop_Type.SCHOOL or mainGame.getCurProp( ).prop_type == Prop_Type.STATION: #If property actually will have a title deed to display title_deed = pygame.transform.smoothscale( mainGame.getCurProp().getTitleDeed(), [270, 400]) screen.blit(title_deed, [665, 230]) if mainGame.getCurProp().prop_type == Prop_Type.NORMAL: #Normal properties are the only ones that can have Council Houses and Tower Blocks on them displayUpgrades(screen, CH_img, TB_img, mainGame.getCurProp(), font_40) if mainGame.getCurProp().prop_owner == mainGame.cur_player: if mainGame.board.wholeGroupOwned( mainGame.cur_player, mainGame.getCurPlayer().player_pos ): #May only be bought if the property is owned by the current player and the entire colour group is owned if mainGame.getCurProp().C_Houses < 4: displayButtonRect(screen, buy_upgrade_button, (100, 100, 100), font_20, 'Buy Council House', (0, 0, 0)) elif mainGame.getCurProp().T_Blocks == 0: displayButtonRect(screen, buy_upgrade_button, (100, 100, 100), font_20, 'Buy Tower Block', (0, 0, 0)) if mainGame.getCurProp().T_Blocks > 0: displayButtonRect(screen, sell_upgrade_button, (100, 100, 100), font_20, 'Sell Tower Block', (0, 0, 0)) elif mainGame.getCurProp().C_Houses > 0: displayButtonRect(screen, sell_upgrade_button, (100, 100, 100), font_20, 'Sell Council House', (0, 0, 0)) if mainGame.getCurProp( ).prop_type == Prop_Type.NORMAL or mainGame.getCurProp( ).prop_type == Prop_Type.SCHOOL or mainGame.getCurProp( ).prop_type == Prop_Type.STATION: if mainGame.getCurProp().prop_owner == mainGame.cur_player: #Display relevant button for mortgaging or unmortgaging a property if mainGame.getCurProp( ).mortgage_status: #Property is mortgaged displayButtonRect(screen, buy_prop_button, (100, 100, 100), font_28, 'Unmortgage Property', (0, 0, 0)) else: displayButtonRect(screen, buy_prop_button, (100, 100, 100), font_28, 'Mortgage Property', (0, 0, 0)) if mainGame.getCurProp( ).prop_owner == -1 and mainGame.controller.may_buy: #Give player the opportunity to buy property (since it is available and they have began their turn by rolling the dice) displayButtonRect(screen, buy_prop_button, (100, 100, 100), font_40, 'Buy Property', (0, 0, 0)) elif mainGame.getCurProp().prop_owner != -1: #Property is owned by a player so display information pertaining to the owning of said property by this aforementioned player displayOwner( screen, font_28, mainGame.getPlayer(mainGame.getCurProp().prop_owner)) else: if mainGame.getCurProp( ).prop_type != Prop_Type.LOST_IN_BOGSIDE: #Will work perfectly normally for all properties but the Lost In Bogside square tit_str = mainGame.getCurProp().prop_title elif mainGame.getCurPlayer( ).player_inJail: #If Player is actually 'in jail' tit_str = "Lost In Bogside" else: tit_str = "On The Paths" #In the same space but can move freely (i.e. 'not in jail') tit_text = font_40.render( tit_str, True, (0, 0, 0) ) #Render the property name as it does not have a title deed that can do so t_width, t_height = font_40.size(tit_str) screen.blit(tit_text, [(400 - t_width) / 2 + 600, 220]) if mainGame.getCurProp( ).prop_type == Prop_Type.NORMAL or mainGame.getCurProp( ).prop_type == Prop_Type.SCHOOL or mainGame.getCurProp( ).prop_type == Prop_Type.STATION or mainGame.getCurProp( ).prop_type == Prop_Type.PAYMENT: #If incurs a charge try: if mainGame.controller.turn_rent != 0: #If rent has actually been charged then the player is told they themselves have paid whatever amount displayPaidRent(screen, font_28, mainGame.controller.turn_rent) elif mainGame.getCurProp( ).prop_owner == mainGame.cur_player and mainGame.getCurProp( ).prop_type == Prop_Type.NORMAL: #If property is owned by the current player and NORMAL (since other properties depend on those owned and dice rolls if mainGame.board.wholeGroupOwned( mainGame.getCurProp().prop_owner, mainGame.getCurPlayer().player_pos ) and mainGame.getCurProp().C_Houses == 0: displayRent(screen, font_28, mainGame.getCurProp().getRent() * 2) else: displayRent(screen, font_28, mainGame.getCurProp().getRent()) except AttributeError: #Prevents errors as PAYMENT property has no owner but changes variable turn_rent pass if mainGame.getCurProp( ).prop_type == Prop_Type.POT_LUCK or mainGame.getCurProp( ).prop_type == Prop_Type.COUNCIL_CHEST: if mainGame.controller.cur_card != None: #If player was already on one of these places when their turn begins, cur_card and card_texts will be None object; this condition prevents an error when the following code thinks that it is displayCard(screen, mainGame.controller.cur_card) t_count = 0 for cur_text in mainGame.controller.card_texts: w, h = cur_text.get_size() screen.blit(cur_text, [(400 - w) / 2 + 600, 480 + t_count * 25]) t_count += 1 if turn_but_click: #End Turn button #If player could sell some things to avoid going bankrupt cont = True if mainGame.getCurPlayer().player_money < 0 and ( getObtainMon(mainGame.board, mainGame.cur_player) + mainGame.getCurPlayer().player_money) >= 0: msgBox = MessageBox( screen, 'You need to ensure your money is 0 or above before you can finish your turn. Please sell or mortgage some assets to continue.', 'Not Enough Money') cont = False elif ( getObtainMon(mainGame.board, mainGame.cur_player) + mainGame.getCurPlayer().player_money ) < 0: #If it is impossible for a player to not end up in debt, they go bankrupt mainGame.getCurPlayer().deactivate( ) #Remove player from the game cont = False for counter in range(mainGame.board.max_pos): if mainGame.board.getProp( counter).prop_type == Prop_Type.NORMAL: if mainGame.board.getProp( counter).prop_owner == mainGame.cur_player: mainGame.board.getProp(counter).p_owner = -1 mainGame.board.getProp( counter).mortgage_status = False mainGame.board.getProp(counter).C_Houses = 0 mainGame.board.getProp(counter).T_Blocks = 0 if mainGame.board.getProp( counter ).prop_type == Prop_Type.SCHOOL or mainGame.board.getProp( counter).prop_type == Prop_Type.STATION: if mainGame.board.getProp( counter).prop_owner == mainGame.cur_player: mainGame.board.getProp(counter).p_owner = -1 mainGame.board.getProp( counter).mortgage_status = False msgBox = MessageBox( screen, 'Unfortunately, this utopian capitalist world has ceased to be utopian for you: you have gone bankrupt and are no longer in the game.', 'Game Over') advanceOnBoxClose = True #Next player's turn now (if the previous player has no more to do if cont: mainGame.advancePlayer() mainGame.prop_thumbs = pygame.transform.smoothscale( CreateThumbs(mainGame.board, mainGame.cur_player), [385, 170] ) #Generate thumbnails for new player (here so it is only done when the player changes, not every frame change) if mainGame.countActivePlayers() < 2: mainGame.advancePlayer() msgBox = MessageBox( screen, mainGame.getCurPlayer().player_name + ' has won the game.', 'Game Over') exitOnBoxClose = True #Button for buying a property has been clicked if buy_but_click and ( mainGame.getCurProp().prop_type == Prop_Type.NORMAL or mainGame.getCurProp().prop_type == Prop_Type.SCHOOL or mainGame.getCurProp().prop_type == Prop_Type.STATION ): #Final check that the property can actually be owned #Player wished to buy property if mainGame.getCurProp( ).prop_owner == -1: #Property is unowned, hence can actually be bought if mainGame.getCurPlayer().player_money >= mainGame.getCurProp( ).cost: #Player has enough money mainGame.getCurPlayer().spendMoney(mainGame.getCurProp( ).cost) #Decrease the player's bank balance accordingly mainGame.getCurProp().buyProperty( mainGame.cur_player ) #Change the property's status to track the new ownership mainGame.prop_thumbs = pygame.transform.smoothscale( CreateThumbs(mainGame.board, mainGame.cur_player), [385, 170] ) #Update title deed thumbnails to reflect newly purchased properties #Button to apply the effects of a Pot Luck or Council Chest card if use_card_but_click and mainGame.controller.cur_card != None: #Check there is a card to work with mainGame.controller.card_used = True mainGame.applyCardEffects() #Apply card effects #All of the following may only be done if the current player owns the property #Button for mortgaging or unmortgaging a property if mort_but_click and ( mainGame.getCurProp().prop_type == Prop_Type.NORMAL or mainGame.getCurProp().prop_type == Prop_Type.SCHOOL or mainGame.getCurProp().prop_type == Prop_Type.STATION ): #Final check that the property is one that may be mortgaged if mainGame.getCurProp( ).prop_owner == mainGame.cur_player and mainGame.getCurProp( ).mortgage_status == False: #Property must be owned by the current player and not already mortgaged mainGame.getCurProp( ).mortgage_status = True #Property is now mortgaged mainGame.getCurPlayer().addMoney( int(mainGame.getCurProp().mortgage_val)) elif mainGame.getCurProp( ).prop_owner == mainGame.cur_player and mainGame.getCurProp( ).mortgage_status: #Property must be owned by the current player and is mortgaged if mainGame.getCurPlayer().player_money >= mainGame.getCurProp( ).mortgage_val * 1.2: #Player has sufficient money to unmortgage the property (twice the money gotten by mortgaging it) mainGame.getCurProp( ).mortgage_status = False #Property is no longer in a state of being mortgaged mainGame.getCurPlayer().spendMoney( int(mainGame.getCurProp().mortgage_val * 1.2) ) #Decrease player's money by the cost of unmortgaging the property #Button for buying a Council House or Tower Block if buy_upgrade_but_click and mainGame.getCurProp( ).prop_type == Prop_Type.NORMAL and mainGame.board.wholeGroupOwned( mainGame.cur_player, mainGame.getCurPlayer().player_pos ): #Player wishes to upgrade the property and said upgrade can actually be purchaed if mainGame.getCurProp( ).prop_owner == mainGame.cur_player: #May only be bought if the property is owned by the current player if mainGame.getCurProp( ).C_Houses < 4: #Fewer than 4 Council Houses, so these are the next upgrade to be bought if mainGame.getCurPlayer().player_money >= ( mainGame.getCurProp().CH_cost * mainGame.board.countGroupSize( mainGame.cur_player, mainGame.getCurPlayer().player_pos) ): #Player actually has enough money to buy the Council House upgrade mainGame.board.buyCHGroup( mainGame.cur_player, mainGame.getCurPlayer().player_pos ) #Buy the Council Houses for the whole group mainGame.getCurPlayer().spendMoney( mainGame.getCurProp().CH_cost * mainGame.board.countGroupSize( mainGame.cur_player, mainGame.getCurPlayer().player_pos) ) #Decrease the player's money by the cost of a Council House for however many properties are in the group elif mainGame.getCurProp( ).C_Houses == 4 and mainGame.getCurProp( ).T_Blocks == 0: #4 Council Houses and no Tower Blocks, so Tower Block can be bought if mainGame.getCurPlayer().player_money >= ( mainGame.getCurProp().TB_cost * mainGame.board.countGroupSize( mainGame.cur_player, mainGame.getCurPlayer().player_pos) ): #Player actually has enough money to buy the Tower Block upgrade mainGame.board.buyTBGroup( mainGame.cur_player, mainGame.getCurPlayer().player_pos ) #Buy the Council Houses for the whole group mainGame.getCurPlayer().spendMoney( mainGame.getCurProp().TB_cost * mainGame.board.countGroupSize( mainGame.cur_player, mainGame.getCurPlayer().player_pos) ) #Decrease the player's money by the cost of a Tower Block for however many properties are in the group #Button for selling a Council House or Tower Block if sell_upgrade_but_click and mainGame.getCurProp( ).prop_type == Prop_Type.NORMAL and mainGame.board.wholeGroupOwned( mainGame.cur_player, mainGame.getCurPlayer().player_pos ): #Player wishes to upgrade the property and said upgrade can actually be purchaed if mainGame.getCurProp( ).prop_owner == mainGame.cur_player: #May only be bought if the property is owned by the current player if mainGame.getCurProp( ).T_Blocks > 0: #Property has a Tower Block that can be sold mainGame.board.sellTBGroup( mainGame.cur_player, mainGame.getCurPlayer().player_pos ) #Sell the Tower Blocks for the whole group mainGame.getCurPlayer().addMoney( int(mainGame.getCurProp().TB_cost / 2 * mainGame.board.countGroupSize( mainGame.cur_player, mainGame.getCurPlayer().player_pos)) ) #Increase the player's money by half of what the upgrades were bought for elif mainGame.getCurProp( ).C_Houses > 0: #No Tower Blocks, buy some Council Houses which can instead be sold mainGame.board.sellCHGroup( mainGame.cur_player, mainGame.getCurPlayer().player_pos ) #Sell the Council Houses for the whole group mainGame.getCurPlayer().addMoney( int(mainGame.getCurProp().CH_cost / 2 * mainGame.board.countGroupSize( mainGame.cur_player, mainGame.getCurPlayer().player_pos)) ) #Increase the player's money by half of what the upgrades were bought for #Button to buy a map out of Bogside for £50 if leave_bogside_but_click and ( mainGame.getCurPlayer().player_money >= 50 or mainGame.getCurPlayer().player_hasBogMap ) and mainGame.getCurPlayer().player_inJail: mainGame.getCurPlayer().leaveJail() if mainGame.getCurPlayer().player_hasBogMap == False: mainGame.getCurPlayer().spendMoney(50) else: mainGame.getCurPlayer().useBogMap() if msgBox != None: msgBox.update() if msgBox.should_exit == False: msgBox.draw(screen) if main_buts[2].clicked(): #Details main_screen_running = False gotoScreen = 2 if main_buts[0].clicked(): #Leaderboards main_screen_running = False gotoScreen = 3 if main_buts[1].clicked(): #Pause main_screen_running = False gotoScreen = 4 for but in main_buts: but.render(screen) #Reset button booleans so that effects of clicking buttons do not happen more than once dice_but_click = False turn_but_click = False buy_but_click = False mort_but_click = False buy_upgrade_but_click = False sell_upgrade_but_click = False leave_bogside_but_click = False use_card_but_click = False clock.tick( fps ) #10 fps currently, but could easily be changed to update more or less often pygame.display.flip( ) #Refresh display from a pygame perspective, to reflect the screen.blit()s 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
import pygame from msgbox import MessageBox pygame.init() screen = pygame.display.set_mode((750, 500)) clock = pygame.time.Clock() message = 'The quick brown fox jumps over the lazy dog, but that does not tell us anything about what the cat did \n This starts a new line' title = 'This is a title' messageBox = MessageBox(screen, message, title) running = True while running: clock.tick(60) for event in pygame.event.get(): messageBox.handle_input_event(event) if messageBox.should_exit == False: #Prevents any other actions taking place on screen while the messagebox is visible. break if event.type == pygame.QUIT: running = False screen.fill((0, 0, 0)) messageBox.update() if messageBox.should_exit == False: messageBox.draw(screen) pygame.display.flip() pygame.quit()
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 Leaderboards(mainGame, screen, clock): font_48 = pygame.font.SysFont('Arial', 48) #Font for title and name font_40 = pygame.font.SysFont('Arial', 40) #Font for the "?" and Exit buttons font_28 = pygame.font.SysFont('Arial', 28) #Font for actual leaderboards and attributes font_32b = pygame.font.SysFont('Arial', 32, True) #Font for column headings lead_arr = setup2DArray(mainGame) #Arrow images to be displayed on the buttons that are used by the player for choosing which column to sort on and whether to sort ascending or descending arrow_both = pygame.image.load("img/Arrows/both.png") arrow_up = pygame.image.load("img/Arrows/up.png") arrow_down = pygame.image.load("img/Arrows/down.png") #Initialise button array sort_buts = [pygame.Rect(360,80,40,40), pygame.Rect(610,80,40,40), pygame.Rect(940,80,40,40)] leader_buts = [Button(880, 10, 120, 50, 'Exit', font_40), Button(819, 10, 50, 50, '?', font_40)] msgBox = MessageBox(screen, 'Total Money measures simply how much money each player has in the Bank. \n Total Assets counts the values of all owned properties, upgrades, etc. based on how much was paid for them initially. \n Obtainable Money is how much money each player could get if they were to sell off all of their properties and the like.', 'Leaderboards: Explained') msgBox.should_exit = True tit_text = font_48.render('Viewing Leaderboards:', True, (0,0,0)) #Render title at top left of screen head_1 = font_32b.render('Player', True, (0,0,0)) head_2 = font_32b.render('Total Money', True, (0,0,0)) head_3 = font_32b.render('Total Assets', True, (0,0,0)) head_4 = font_32b.render('Obtainable Money', True, (0,0,0)) mon_text = font_48.render(mainGame.getCurPlayer().player_name, True, (0,0,0)) #Render player money on screen f_width, f_height = font_48.size(mainGame.getCurPlayer().player_name) y_top = 120 #First y co-ordinate for a row of details y_space = 40 #Co-ordinate spacing between rows fps = 10 sort_column = 1 sort_asc = False sort_but_click = -1 lead_arr = quickSort(lead_arr, 0, lead_arr.shape[0]-1, sort_column, sort_asc) leaderboards_running = True while leaderboards_running: #Main loop for this part of the program for event in pygame.event.get(): for but in leader_buts: but.handle_input_event(event) msgBox.handle_input_event(event) if msgBox.should_exit == False: break if event.type == pygame.QUIT: leaderboards_running = False gotoScreen = -1 if event.type == pygame.KEYDOWN: #If any key pressed if event.key == pygame.K_ESCAPE: #Escape key exits the game leaderboards_running = False gotoScreen = -1 if event.type == pygame.MOUSEBUTTONDOWN: if event.button == 1: #Left mouse button mouse_pos = event.pos #Position of the cursor when nouse was clicked for counter in range(3): #Cycle through all the arrays of buttons to see if any have been clicked if sort_buts[counter].collidepoint(mouse_pos): sort_but_click = counter screen.fill((255,255,255)) screen.blit(tit_text, [10, 10]) screen.blit(mon_text, [(770-f_width), 10]) pygame.draw.rect(screen, (0,0,0), pygame.Rect(10,70,1000,700), 10) #Draw black rectangle surrounding the property data #Display each of the column headings (bold text) screen.blit(head_1, [30, 80]) screen.blit(head_2, [200, 80]) screen.blit(head_3, [450, 80]) screen.blit(head_4, [700, 80]) for counter in range(3): displayButtonRect(screen, sort_buts[counter], (100, 100, 100), font_28, '', (0, 0, 0)) if counter == sort_column-1: if sort_asc: screen.blit(arrow_down, [sort_buts[counter].x, sort_buts[counter].y]) else: screen.blit(arrow_up, [sort_buts[counter].x, sort_buts[counter].y]) else: screen.blit(arrow_both, [sort_buts[counter].x, sort_buts[counter].y]) y_pos = y_top #Y co-ordinate of the first row of data for counter in range(lead_arr.shape[0]): text_1 = font_28.render(mainGame.getPlayer(lead_arr[counter][0]).player_name, True, (0,0,0)) #Property name/title screen.blit(text_1, [30, y_pos]) text_2 = font_28.render(str(lead_arr[counter][1]), True, (0,0,0)) screen.blit(text_2, [200, y_pos]) text_3 = font_28.render(str(lead_arr[counter][2]), True, (0,0,0)) screen.blit(text_3, [450, y_pos]) text_4 = font_28.render(str(lead_arr[counter][3]), True, (0,0,0)) screen.blit(text_4, [700, y_pos]) y_pos += y_space #Increment y co-ordinate variable by the difference in co-ordinates between each row, as already defined if sort_but_click != -1: if sort_column == sort_but_click+1: sort_asc = not sort_asc else: sort_column = sort_but_click + 1 sort_asc = False lead_arr = quickSort(lead_arr, 0, lead_arr.shape[0]-1, sort_column, sort_asc) if leader_buts[0].clicked(): leaderboards_running = False gotoScreen = 1 if leader_buts[1].clicked(): msgBox.should_exit = False msgBox.update() if msgBox.should_exit == False: msgBox.draw(screen) for but in leader_buts: but.render(screen) sort_but_click = -1 clock.tick(fps) #10 fps currently, but could easily be changed to update more or less often pygame.display.flip() #Refresh display from a pygame perspective, to reflect the screen.blit()s 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