game.py (8226B)
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 shift_frames(self): 108 """ 109 Shift to the next frame using the PyGame Clock object. 110 This must be the FIRST thing that happens in the mainloop. 111 """ 112 self.frame_clock.tick(self.framerate) 113 114 def update_game(self): 115 """ 116 Update the entire game (screen, subsystems, internal 117 values, etc.). 118 """ 119 120 # First, fill the entire screen with black 121 self.screen.fill((200, 200, 200)) 122 123 # Next, update all managers that are mode-agnostic 124 self.sheet_manager.update(None) 125 self.sound_manager.update(None) 126 127 # Next, update all the subsurfaces/game objects and draw them 128 self.interface.update_interface() 129 130 # State_Mode-specific actions (can be further subdivided by Control_Mode) 131 # Camera draw occurs in all these modes 132 if self.state_mode == STATE_MODES.Main_Menu_Mode: 133 self.menu_manager.update(self.camera.camera_surface) 134 self.camera.update_camera(self.screen) 135 elif self.state_mode == STATE_MODES.Base_Mode: 136 self.board_manager.update(self.camera.camera_surface) 137 self.base_manager.update(self.camera.camera_surface) 138 self.camera.update_camera(self.screen) 139 if self.control_mode == CTRL_MODES.Base_Dialog: 140 self.scene_manager.update(self.screen) 141 elif self.state_mode == STATE_MODES.Battle_Mode: 142 self.board_manager.update(self.camera.camera_surface) 143 self.piece_manager.update(self.camera.camera_surface) 144 # NOTE: This must happen here to avoid a very choppy rendering of the 145 # moving entity caused by the drawing order. 146 if self.control_mode == CTRL_MODES.Turn_Watch_Move: 147 self.camera.snap_to_position(self.turn_manager.current_active_piece.rect.center) 148 self.camera.update_camera(self.screen) 149 if self.control_mode == CTRL_MODES.Battle_Dialog: 150 self.scene_manager.update(self.screen) 151 else: 152 self.turn_manager.update(self.screen) # Draw to the screen since it manages UI elements 153 elif self.state_mode == STATE_MODES.Still_Scene_Mode: 154 self.scene_manager.update(self.camera.camera_surface) 155 self.camera.update_camera(self.screen) 156 157 # State_Mode agnostic, Control_Mode specific actions 158 if self.control_mode == CTRL_MODES.No_Control: 159 if self.no_control_timer > 0: 160 self.no_control_timer -= 1 161 elif self.no_control_timer == 0: 162 self.control_mode = self.return_control_mode 163 self.return_control_mode = None 164 165 # Last, update the screen 166 pygame.display.update() 167 168 def quit_game(self): 169 """ 170 Turn off so the game stops in a clean way. 171 """ 172 self.on = False 173 174 def mainloop(self): 175 """ 176 The loop where all game logic takes place. This 177 method must be called once from somewhere after 178 the Game object is initialized in order to start 179 the game itself. This method cleans up after 180 itself when the Game object is turned off. 181 """ 182 183 # While we are on, run the loop 184 while self.on: 185 self.shift_frames() 186 self.interface.handle_events(pygame.event.get()) 187 self.update_game() 188 189 # When we turn off, cleanup and end 190 pygame.quit() 191