commit 04a12b28880194ae97de3019d3bb63b9479ab553
parent 145eb531b57dc6da62051dec4fed8b2bc6b5c76a
Author: Erik Letson <hmagellan@hmagellan.com>
Date: Wed, 11 Nov 2020 13:55:06 -0600
split off the largest subsystems to their own files
Diffstat:
A | src/camera.py | | | 73 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | src/game.py | | | 6 | +++--- |
A | src/interface.py | | | 139 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | src/subsystem.py | | | 200 | ++----------------------------------------------------------------------------- |
4 files changed, 219 insertions(+), 199 deletions(-)
diff --git a/src/camera.py b/src/camera.py
@@ -0,0 +1,73 @@
+import pygame
+from . import subsystem
+from .constants import *
+
+#############
+# camera.py #
+#############
+
+# This file contains:
+# 1. The GameCamera class, which manages the camera surface
+
+####################################
+# Section 1 - The GameCamera class #
+####################################
+
+class GameCamera(subsystem.GameSubsystem):
+ """
+ Object that controls the camera surface and
+ moves it in relation to input. The camera
+ surface is then drawn onto the game's real
+ screen at an offset determined by input.
+ """
+
+ def __init__(self, game):
+
+ # Parent init
+ super().__init__(game)
+
+ # Camera surface values
+ self.camera_surface = pygame.Surface((0, 0)).convert() # This surface is initialized whenever a new map or other game area is loaded
+ self.camera_surface_rect = self.camera_surface.get_rect()
+ self.camera_surface_offset = (0, 0) # The rect topleft is never changed; rather, this value is used by game to draw the camera surface at an offset
+ self.scroll_rects = {(1, 0) : None, (-1, 0) : None, (0, 1) : None, (0, -1) : None}
+
+ def load_camera_surface(self, dimensions, init_offset = (0, 0)):
+ """
+ Load up the camera surface as a new PyGame
+ surface object of the necessary size. Also
+ resets the camera offset.
+ """
+ self.camera_surface = pygame.Surface(dimensions).convert()
+ self.camera_surface_rect = self.camera_surface.get_rect()
+ self.camera_surface_offset = init_offset
+ self.scroll_rects = {
+ (1, 0) : pygame.Rect(0, 0, SCREEN_WIDTH / 4, SCREEN_HEIGHT),
+ (-1, 0) : pygame.Rect(SCREEN_WIDTH - (SCREEN_WIDTH / 4), 0, SCREEN_WIDTH / 4, SCREEN_HEIGHT),
+ (0, 1) : pygame.Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT / 4),
+ (0, -1) : pygame.Rect(0, SCREEN_HEIGHT - (SCREEN_HEIGHT / 4), SCREEN_WIDTH, SCREEN_HEIGHT / 4)
+ }
+
+ def move_offset(self, rel_offset, speed_multiple = 1):
+ """
+ Move the offset by the given relative offset.
+ Speed can also be increased or decreased by
+ passing a multiple here. Handles not moving
+ the camera view outside of game screen
+ completely.
+ """
+ changex = 0
+ changey = 0
+ if not ((self.camera_surface_offset[0] <= -(SCREEN_WIDTH / 2) and rel_offset[0] < 0) or (self.camera_surface_offset[0] >= (SCREEN_WIDTH / 2) and rel_offset[0] > 0)):
+ changex = rel_offset[0] * speed_multiple
+ if not ((self.camera_surface_offset[1] <= -SCREEN_HEIGHT and rel_offset[1] < 0) or (self.camera_surface_offset[1] >= (SCREEN_HEIGHT / 2) and rel_offset[1] > 0)):
+ changey = rel_offset[1] * speed_multiple
+ self.camera_surface_offset = (self.camera_surface_offset[0] + changex, self.camera_surface_offset[1] + changey)
+
+ def update_camera(self, surface = None):
+ """
+ Update and draw the camera contents.
+ """
+ if surface != None:
+ surface.blit(self.camera_surface, self.camera_surface_offset)
+
diff --git a/src/game.py b/src/game.py
@@ -1,5 +1,5 @@
import pygame
-from . import subsystem, bus, manager, images, sound, board, entity, piece, menu, scene
+from . import subsystem, bus, camera, interface, manager, images, sound, board, entity, piece, menu, scene
from .constants import *
###########
@@ -43,10 +43,10 @@ class Game(object):
# Subsystems
self.manager_bus = bus.ManagerBus(self)
- self.camera = subsystem.GameCamera(self)
+ self.camera = camera.GameCamera(self)
self.object_oracle = subsystem.ObjectOracle(self)
self.save_system = subsystem.SaveSystem(self)
- self.interface = subsystem.GameInterface(self, self.manager_bus, self.camera)
+ self.interface = interface.GameInterface(self, self.manager_bus, self.camera)
# Managers
self.sheet_manager = images.SheetManager(self, self.manager_bus, "sheet_manager")
diff --git a/src/interface.py b/src/interface.py
@@ -0,0 +1,139 @@
+import pygame
+from . import subsystem
+from .constants import *
+
+################
+# interface.py #
+################
+
+# This file contains:
+# 1. The GameInterface class, which handles all kinds of interaction from the player
+
+#######################################
+# Section 1 - The GameInterface class #
+#######################################
+
+class GameInterface(subsystem.GameSubsystem):
+ """
+ GameInterface handles all PyGame events, meaning
+ it is responsible for all input and the responses
+ to that input. GameInterface takes extra arguments
+ compared to other subsystems, representing its need
+ to directly access manager calls via bus and the
+ game camera.
+ """
+
+ def __init__(self, game, bus, camera):
+
+ # Parent init
+ super().__init__(game)
+
+ # Others
+ self.bus = bus
+ self.camera = camera
+
+ def handle_events(self, events):
+ """
+ Handle any kind of PyGame event and react appropriately.
+ """
+ for event in events:
+ if event.type == pygame.KEYDOWN:
+ self.handle_key_press(event)
+ elif event.type == pygame.KEYUP:
+ self.handle_key_release(event)
+ elif event.type == pygame.MOUSEBUTTONDOWN:
+ self.handle_mouse_click(event)
+ elif event.type == pygame.MOUSEBUTTONUP:
+ self.handle_mouse_release(event)
+ elif event.type == pygame.QUIT:
+ self.game.quit_game()
+
+ def handle_key_press(self, event):
+ """
+ React to a key being pressed.
+ """
+ # TODO: This is irregular compared to mouseclick. Desireable???
+ if self.game.control_mode == CTRL_MODES.Turn_Select_Move:
+ if event.key == pygame.K_q:
+ self.game.control_mode = CTRL_MODES.Turn_Normal
+ self.bus.perform_load_board_overlay()
+
+ def handle_key_release(self, event):
+ """
+ React to a key being released.
+ """
+ pass
+
+ def handle_mouse_click(self, event):
+ """
+ React to a mousebutton being clicked.
+ """
+ # If we clicked the left mouse button...
+ if event.button == 1:
+
+ # First, get important mouse positional info, namely unoffset mouse position and camera-offset mouse position
+ mouseraw = pygame.mouse.get_pos()
+ mousepos = (mouseraw[0] - self.camera.camera_surface_offset[0], mouseraw[1] - self.camera.camera_surface_offset[1])
+
+ # State checker
+ # Main menu mode behavior
+ if self.game.state_mode == STATE_MODES.Main_Menu_Mode:
+
+ # Normal main menu control
+ if self.game.control_mode == CTRL_MODES.Main_Menu_Normal:
+ self.bus.perform_trigger_menu_button_at_pos(mousepos)
+
+ # Battle mode behavior
+ elif self.game.state_mode == STATE_MODES.Battle_Mode:
+
+ # Normal in-battle turn control
+ if self.game.control_mode == CTRL_MODES.Turn_Normal:
+ self.bus.perform_select_piece_with_tile_cursor()
+ sp = self.bus.fetch("piece_manager", "selected_piece")
+ if sp != None:
+ self.bus.perform_display_move_range_of_piece(sp)
+ self.game.control_mode = CTRL_MODES.Turn_Select_Move
+
+ # Selecting a move for the active piece control
+ elif self.game.control_mode == CTRL_MODES.Turn_Select_Move:
+ if self.bus.check_for_overlay_move_entity_by_screen_pos(mousepos) != None:
+ targ = self.bus.check_for_tile_pos_by_screen_pos(mousepos)
+ to_path = self.bus.check_for_piece_path_by_previous_moves(self.bus.fetch("piece_manager", "selected_piece").tile_pos, targ)
+ if to_path != None:
+ self.bus.perform_set_piece_move_along_tile_path(self.bus.fetch("piece_manager", "selected_piece"), to_path)
+ # TODO: Not like this
+ self.game.lose_control(len(to_path) * PIECE_MOVE_DELAY, CTRL_MODES.Turn_Normal)
+ self.bus.perform_load_board_overlay()
+
+ # Still-scene mode behavior
+ elif self.game.state_mode == STATE_MODES.Still_Scene_Mode:
+
+ # Normal still-scene control
+ if self.game.control_mode == CTRL_MODES.Still_Scene_Normal:
+ self.bus.perform_continue_current_scene_script()
+
+ def handle_mouse_release(self, event):
+ """
+ React to a mousebutton being released.
+ """
+ pass
+
+ def update_interface(self):
+ """
+ Update interface elements (such as the cursor) once
+ per frame. This is not the same as a drawing update for
+ e.g. an Entity, and is logic-only.
+ """
+ # Update cursor position
+ if self.game.state_mode == STATE_MODES.Battle_Mode:
+ mouseraw = pygame.mouse.get_pos()
+ mousepos = (mouseraw[0] - self.camera.camera_surface_offset[0], mouseraw[1] - self.camera.camera_surface_offset[1])
+ tilepos = self.bus.check_for_tile_by_screen_pos(mousepos)
+ if tilepos != None:
+ self.bus.perform_position_tile_cursor((tilepos[0], tilepos[1]))
+
+ if self.game.control_mode == CTRL_MODES.Turn_Normal:
+ for r in self.camera.scroll_rects:
+ if self.camera.scroll_rects[r].collidepoint(mouseraw):
+ self.camera.move_offset(r, SCROLL_SPEED)
+
diff --git a/src/subsystem.py b/src/subsystem.py
@@ -7,10 +7,8 @@ from .constants import *
# This file contains:
# 1. The generic GameSubsystem class, which abstract subsystems (like GameInterface) are children of, as well as all Managers
-# 2. The GameInterface class, which handles game events such as keyboard and mouse input
-# 3. The GameCamera class, which controls camera-oriented logic and drawing
-# 4. The ObjectOracle class, which keeps track of all Entity objects and can refer to them, but does not manage or draw them
-# 5. The SaveSystem class, which handles saving and loading games
+# 2. The ObjectOracle class, which keeps track of all Entity objects and can refer to them, but does not manage or draw them
+# 3. The SaveSystem class, which handles saving and loading games
#######################################
# Section 1 - The GameSubsystem class #
@@ -39,198 +37,8 @@ class GameSubsystem(object):
self.game = game
-#######################################
-# Section 2 - The GameInterface class #
-#######################################
-
-class GameInterface(GameSubsystem):
- """
- GameInterface handles all PyGame events, meaning
- it is responsible for all input and the responses
- to that input. GameInterface takes extra arguments
- compared to other subsystems, representing its need
- to directly access manager calls via bus and the
- game camera.
- """
-
- def __init__(self, game, bus, camera):
-
- # Parent init
- super().__init__(game)
-
- # Others
- self.bus = bus
- self.camera = camera
-
- def handle_events(self, events):
- """
- Handle any kind of PyGame event and react appropriately.
- """
- for event in events:
- if event.type == pygame.KEYDOWN:
- self.handle_key_press(event)
- elif event.type == pygame.KEYUP:
- self.handle_key_release(event)
- elif event.type == pygame.MOUSEBUTTONDOWN:
- self.handle_mouse_click(event)
- elif event.type == pygame.MOUSEBUTTONUP:
- self.handle_mouse_release(event)
- elif event.type == pygame.QUIT:
- self.game.quit_game()
-
- def handle_key_press(self, event):
- """
- React to a key being pressed.
- """
- # TODO: This is irregular compared to mouseclick. Desireable???
- if self.game.control_mode == CTRL_MODES.Turn_Select_Move:
- if event.key == pygame.K_q:
- self.game.control_mode = CTRL_MODES.Turn_Normal
- self.bus.perform_load_board_overlay()
-
- def handle_key_release(self, event):
- """
- React to a key being released.
- """
- pass
-
- def handle_mouse_click(self, event):
- """
- React to a mousebutton being clicked.
- """
- # If we clicked the left mouse button...
- if event.button == 1:
-
- # First, get important mouse positional info, namely unoffset mouse position and camera-offset mouse position
- mouseraw = pygame.mouse.get_pos()
- mousepos = (mouseraw[0] - self.camera.camera_surface_offset[0], mouseraw[1] - self.camera.camera_surface_offset[1])
-
- # State checker
- # Main menu mode behavior
- if self.game.state_mode == STATE_MODES.Main_Menu_Mode:
-
- # Normal main menu control
- if self.game.control_mode == CTRL_MODES.Main_Menu_Normal:
- self.bus.perform_trigger_menu_button_at_pos(mousepos)
-
- # Battle mode behavior
- elif self.game.state_mode == STATE_MODES.Battle_Mode:
-
- # Normal in-battle turn control
- if self.game.control_mode == CTRL_MODES.Turn_Normal:
- self.bus.perform_select_piece_with_tile_cursor()
- sp = self.bus.fetch("piece_manager", "selected_piece")
- if sp != None:
- self.bus.perform_display_move_range_of_piece(sp)
- self.game.control_mode = CTRL_MODES.Turn_Select_Move
-
- # Selecting a move for the active piece control
- elif self.game.control_mode == CTRL_MODES.Turn_Select_Move:
- if self.bus.check_for_overlay_move_entity_by_screen_pos(mousepos) != None:
- targ = self.bus.check_for_tile_pos_by_screen_pos(mousepos)
- to_path = self.bus.check_for_piece_path_by_previous_moves(self.bus.fetch("piece_manager", "selected_piece").tile_pos, targ)
- if to_path != None:
- self.bus.perform_set_piece_move_along_tile_path(self.bus.fetch("piece_manager", "selected_piece"), to_path)
- # TODO: Not like this
- self.game.lose_control(len(to_path) * PIECE_MOVE_DELAY, CTRL_MODES.Turn_Normal)
- self.bus.perform_load_board_overlay()
-
- # Still-scene mode behavior
- elif self.game.state_mode == STATE_MODES.Still_Scene_Mode:
-
- # Normal still-scene control
- if self.game.control_mode == CTRL_MODES.Still_Scene_Normal:
- self.bus.perform_continue_current_scene_script()
-
- def handle_mouse_release(self, event):
- """
- React to a mousebutton being released.
- """
- pass
-
- def update_interface(self):
- """
- Update interface elements (such as the cursor) once
- per frame. This is not the same as a drawing update for
- e.g. an Entity, and is logic-only.
- """
- # Update cursor position
- if self.game.state_mode == STATE_MODES.Battle_Mode:
- mouseraw = pygame.mouse.get_pos()
- mousepos = (mouseraw[0] - self.camera.camera_surface_offset[0], mouseraw[1] - self.camera.camera_surface_offset[1])
- tilepos = self.bus.check_for_tile_by_screen_pos(mousepos)
- if tilepos != None:
- self.bus.perform_position_tile_cursor((tilepos[0], tilepos[1]))
-
- if self.game.control_mode == CTRL_MODES.Turn_Normal:
- for r in self.camera.scroll_rects:
- if self.camera.scroll_rects[r].collidepoint(mouseraw):
- self.camera.move_offset(r, SCROLL_SPEED)
-
-####################################
-# Section 3 - The GameCamera class #
-####################################
-
-class GameCamera(GameSubsystem):
- """
- Object that controls the camera surface and
- moves it in relation to input. The camera
- surface is then drawn onto the game's real
- screen at an offset determined by input.
- """
-
- def __init__(self, game):
-
- # Parent init
- super().__init__(game)
-
- # Camera surface values
- self.camera_surface = pygame.Surface((0, 0)).convert() # This surface is initialized whenever a new map or other game area is loaded
- self.camera_surface_rect = self.camera_surface.get_rect()
- self.camera_surface_offset = (0, 0) # The rect topleft is never changed; rather, this value is used by game to draw the camera surface at an offset
- self.scroll_rects = {(1, 0) : None, (-1, 0) : None, (0, 1) : None, (0, -1) : None}
-
- def load_camera_surface(self, dimensions, init_offset = (0, 0)):
- """
- Load up the camera surface as a new PyGame
- surface object of the necessary size. Also
- resets the camera offset.
- """
- self.camera_surface = pygame.Surface(dimensions).convert()
- self.camera_surface_rect = self.camera_surface.get_rect()
- self.camera_surface_offset = init_offset
- self.scroll_rects = {
- (1, 0) : pygame.Rect(0, 0, SCREEN_WIDTH / 4, SCREEN_HEIGHT),
- (-1, 0) : pygame.Rect(SCREEN_WIDTH - (SCREEN_WIDTH / 4), 0, SCREEN_WIDTH / 4, SCREEN_HEIGHT),
- (0, 1) : pygame.Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT / 4),
- (0, -1) : pygame.Rect(0, SCREEN_HEIGHT - (SCREEN_HEIGHT / 4), SCREEN_WIDTH, SCREEN_HEIGHT / 4)
- }
-
- def move_offset(self, rel_offset, speed_multiple = 1):
- """
- Move the offset by the given relative offset.
- Speed can also be increased or decreased by
- passing a multiple here. Handles not moving
- the camera view outside of game screen
- completely.
- """
- changex = 0
- changey = 0
- if not ((self.camera_surface_offset[0] <= -(SCREEN_WIDTH / 2) and rel_offset[0] < 0) or (self.camera_surface_offset[0] >= (SCREEN_WIDTH / 2) and rel_offset[0] > 0)):
- changex = rel_offset[0] * speed_multiple
- if not ((self.camera_surface_offset[1] <= -SCREEN_HEIGHT and rel_offset[1] < 0) or (self.camera_surface_offset[1] >= (SCREEN_HEIGHT / 2) and rel_offset[1] > 0)):
- changey = rel_offset[1] * speed_multiple
- self.camera_surface_offset = (self.camera_surface_offset[0] + changex, self.camera_surface_offset[1] + changey)
-
- def update_camera(self, surface = None):
- """
- Update and draw the camera contents.
- """
- if surface != None:
- surface.blit(self.camera_surface, self.camera_surface_offset)
-
######################################
-# Section 4 - The ObjectOracle class #
+# Section 2 - The ObjectOracle class #
######################################
class ObjectOracle(GameSubsystem):
@@ -250,7 +58,7 @@ class ObjectOracle(GameSubsystem):
super().__init__(game)
####################################
-# Section 5 - The SaveSystem class #
+# Section 3 - The SaveSystem class #
####################################
class SaveSystem(GameSubsystem):