Return to repo list

heart-of-gold

Tactical RPG written in python, using pygame.
Return to HMagellan.com

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