game.py (8767B)
1 import pygame 2 from . import subsystem, bus, camera, interface, manager, images, sound, board, entity, piece, turn, menu, scene, base 3 from .constants import * 4 5 ########### 6 # game.py # 7 ########### 8 9 # TODO: There should be a method to call to change control mode as well as state mode 10 11 # This file contains: 12 # 1. The 'Game' class, which defines the overarching game object 13 14 ########################### 15 # Section 1 - Game object # 16 ########################### 17 18 class Game(object): 19 """ 20 Game is an object that represents the entire running game 21 instance. Everything is a sub-component of and subordinate 22 to Game, and there is only a single instance of Game. It 23 mostly acts as a container for the most basic PyGame obects, 24 such as the screen, and for the GameSubsystem objects. 25 """ 26 27 def __init__(self): 28 29 # Basic values 30 self.screen_dimensions = (SCREEN_WIDTH, SCREEN_HEIGHT) 31 self.framerate = FRAMERATE 32 self.on = True 33 self.no_control_timer = 0 34 self.return_control_mode = None 35 36 # Mode management values 37 self.state_mode = STATE_MODES.Main_Menu_Mode 38 self.control_mode = CTRL_MODES.Main_Menu_Normal 39 40 # PyGame objects 41 self.screen = pygame.display.set_mode(self.screen_dimensions) 42 self.frame_clock = pygame.time.Clock() 43 44 # Subsystems 45 self.manager_bus = bus.ManagerBus(self) 46 self.camera = camera.GameCamera(self) 47 self.object_oracle = subsystem.ObjectOracle(self) 48 self.save_system = subsystem.SaveSystem(self) 49 self.interface = interface.GameInterface(self, self.manager_bus, self.camera) 50 51 # Managers 52 self.sheet_manager = images.SheetManager(self, self.manager_bus, self.camera, "sheet_manager") 53 self.sound_manager = sound.SoundManager(self, self.manager_bus, self.camera, "sound_manager") 54 self.menu_manager = menu.MenuManager(self, self.manager_bus, self.camera, "menu_manager") 55 self.board_manager = board.BoardManager(self, self.manager_bus, self.camera, "board_manager") 56 self.piece_manager = piece.PieceManager(self, self.manager_bus, self.camera, "piece_manager") 57 self.base_manager = base.BaseManager(self, self.manager_bus, self.camera, "base_manager") 58 self.scene_manager = scene.SceneManager(self, self.manager_bus, self.camera, "scene_manager") 59 self.turn_manager = turn.TurnManager(self, self.manager_bus, self.camera, "turn_manager") 60 61 # Setup (This is WIP) 62 self.sheet_manager.load_animations_from_json("anims.json") 63 self.sheet_manager.load_sheets_from_json("sheets.json") 64 self.sound_manager.load_sounds_from_json("sounds.json") 65 66 # Switch to game control 67 self.switch_mode(STATE_MODES.Main_Menu_Mode) 68 69 def switch_mode(self, new_mode, data = None): 70 """ 71 Change the current state_mode, as well as load up 72 the elements of the new mode. This large method 73 should take account of every possible mode in the 74 game. Such a structure has no reason to exists e.g. 75 as a JSON file. The 'data' option contains the info 76 needed as part of a mode switch. This method handles 77 a change even if data is None. 78 """ 79 if new_mode == None: 80 return 81 else: 82 self.state_mode = new_mode 83 84 if new_mode == STATE_MODES.Main_Menu_Mode: 85 self.control_mode = CTRL_MODES.Main_Menu_Normal 86 self.menu_manager.load_menu_from_file("mainmenu.json") 87 self.camera.load_camera_surface((SCREEN_WIDTH, SCREEN_HEIGHT)) 88 elif new_mode == STATE_MODES.Base_Mode: 89 self.control_mode = CTRL_MODES.Base_Normal 90 self.board_manager.load_board(data) 91 self.base_manager.load_base(data) 92 self.base_manager.load_ui_elements() 93 self.camera.load_camera_surface(self.board_manager.current_board.pixel_dimensions) 94 elif new_mode == STATE_MODES.Battle_Mode: 95 self.control_mode = CTRL_MODES.Turn_Normal 96 self.board_manager.load_board(data) 97 self.piece_manager.load_pieces_from_file(data) 98 self.piece_manager.load_ui_elements() 99 self.camera.load_camera_surface(self.board_manager.current_board.pixel_dimensions) 100 # TODO: This maybe shouldn't happen here, probably not ideal in a more complex transition to battle 101 self.turn_manager.initialize_turns(self.piece_manager.pieces, data) 102 elif new_mode == STATE_MODES.Still_Scene_Mode: 103 self.control_mode = CTRL_MODES.Still_Scene_Normal 104 self.scene_manager.load_still_scene_from_file(data) 105 self.camera.load_camera_surface((SCREEN_WIDTH, SCREEN_HEIGHT)) 106 107 def lose_control(self, time = -1, followup_mode = None): 108 """ 109 Switch to no-control mode for a set period of time. If 110 time is a negative number, automatic followup will not 111 occur in the update loop, thus locking the game in 112 No_Control mode. 113 """ 114 if followup_mode != None: 115 self.return_control_mode = followup_mode 116 else: 117 self.return_control_mode = self.control_mode 118 self.control_mode = CTRL_MODES.No_Control 119 self.no_control_timer = time 120 121 def shift_frames(self): 122 """ 123 Shift to the next frame using the PyGame Clock object. 124 This must be the FIRST thing that happens in the mainloop. 125 """ 126 self.frame_clock.tick(self.framerate) 127 128 def update_game(self): 129 """ 130 Update the entire game (screen, subsystems, internal 131 values, etc.). 132 """ 133 134 # First, fill the entire screen with black 135 self.screen.fill((200, 200, 200)) 136 137 # Next, update all managers that are mode-agnostic 138 self.sheet_manager.update(None) 139 self.sound_manager.update(None) 140 141 # Next, update all the subsurfaces/game objects and draw them 142 self.interface.update_interface() 143 144 # State_Mode-specific actions (can be further subdivided by Control_Mode) 145 # Camera draw occurs in all these modes 146 if self.state_mode == STATE_MODES.Main_Menu_Mode: 147 self.menu_manager.update(self.camera.camera_surface) 148 self.camera.update_camera(self.screen) 149 elif self.state_mode == STATE_MODES.Base_Mode: 150 self.board_manager.update(self.camera.camera_surface) 151 self.base_manager.update(self.camera.camera_surface) 152 self.camera.update_camera(self.screen) 153 if self.control_mode == CTRL_MODES.Base_Dialog: 154 self.scene_manager.update(self.screen) 155 elif self.state_mode == STATE_MODES.Battle_Mode: 156 self.board_manager.update(self.camera.camera_surface) 157 self.piece_manager.update(self.camera.camera_surface) 158 # NOTE: This must happen here to avoid a very choppy rendering of the 159 # moving entity caused by the drawing order. 160 if self.control_mode == CTRL_MODES.Turn_Watch_Move: 161 self.camera.snap_to_position(self.turn_manager.current_active_piece.rect.center) 162 self.camera.update_camera(self.screen) 163 if self.control_mode == CTRL_MODES.Battle_Dialog: 164 self.scene_manager.update(self.screen) 165 else: 166 self.turn_manager.update(self.screen) # Draw to the screen since it manages UI elements 167 elif self.state_mode == STATE_MODES.Still_Scene_Mode: 168 self.scene_manager.update(self.camera.camera_surface) 169 self.camera.update_camera(self.screen) 170 171 # State_Mode agnostic, Control_Mode specific actions 172 if self.control_mode == CTRL_MODES.No_Control: 173 if self.no_control_timer > 0: 174 self.no_control_timer -= 1 175 elif self.no_control_timer == 0: 176 self.control_mode = self.return_control_mode 177 self.return_control_mode = None 178 179 # Last, update the screen 180 pygame.display.update() 181 182 def quit_game(self): 183 """ 184 Turn off so the game stops in a clean way. 185 """ 186 self.on = False 187 188 def mainloop(self): 189 """ 190 The loop where all game logic takes place. This 191 method must be called once from somewhere after 192 the Game object is initialized in order to start 193 the game itself. This method cleans up after 194 itself when the Game object is turned off. 195 """ 196 197 # While we are on, run the loop 198 while self.on: 199 self.shift_frames() 200 self.interface.handle_events(pygame.event.get()) 201 self.update_game() 202 203 # When we turn off, cleanup and end 204 pygame.quit() 205