Return to repo list

heart-of-gold

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

commit ed06aa1ed331f3170d917ef88c244d6d5012a54e
parent 5fd6237c899a4503ec75b3685db3832905e24bc1
Author: Erik Letson <hmagellan@hmagellan.com>
Date:   Wed,  4 Nov 2020 17:22:41 -0600

More refactor progress, checkpoint 3

Diffstat:
Msrc/board.py | 23++++++-----------------
Msrc/entity.py | 53++++++++++++++++-------------------------------------
Msrc/game.py | 6++----
Msrc/menu.py | 10+---------
Msrc/piece.py | 10++++++----
Msrc/subsystem.py | 2++
6 files changed, 33 insertions(+), 71 deletions(-)

diff --git a/src/board.py b/src/board.py @@ -11,7 +11,6 @@ from .constants import BOARD_PATH # to frame-by-frame board interaction. This file should not require # so much refactoring as vgo.py to bring the new implementation of # managers into compliance here. -# 2. Moving an active entity should be a BoardManager thing. # This file contains: # 1. The BoardManager class, which manages boards and swaps between them @@ -21,8 +20,6 @@ from .constants import BOARD_PATH # Section 1 - BoardManager Object # ################################### -# TODO: Should BoardManager maintain a surface/rect to draw the Board onto, then -# pass that to Game? class BoardManager(manager.Manager): """ BoardManager handles loading and managing Board objects. It @@ -36,7 +33,6 @@ class BoardManager(manager.Manager): # Board values self.current_board = None - self.loaded_boards = {} self.board_overlay = pygame.sprite.LayeredDirty() self.current_board_dimensions = (0, 0) @@ -48,7 +44,9 @@ class BoardManager(manager.Manager): """ Load a board from a given tmx file. """ - self.loaded_boards[boardfile] = Board(self, boardfile) + self.current_board = Board(self, boardfile) + self.current_board_dimensions = (self.current_board.tmx_data.width * self.current_board.tmx_data.tilewidth, self.current_board.tmx_data.height * self.current_board.tmx_data.tileheight) + self.load_overlay() def load_overlay(self): """ @@ -60,20 +58,11 @@ class BoardManager(manager.Manager): if isinstance(layer, pytmx.TiledTileLayer): for x, y, gid in layer: if self.current_board.tmx_data.get_tile_properties_by_gid(gid)["Passable"] == 1: - e = entity.Entity(self.game.sheet_manager.loaded_sheets["board_overlays_1"]) + e = entity.Entity(self.bus.fetch_sheet("board_overlays_1")) e.set_position((x * self.current_board.tmx_data.tilewidth, y * self.current_board.tmx_data.tileheight)) e.custom_flags = "OverlayGrid" self.board_overlay.add(e) - def switch_to_board(self, boardname): - """ - Switch to a given loaded board. - """ - if boardname in self.loaded_boards.keys(): - self.current_board = self.loaded_boards[boardname] - self.current_board_dimensions = (self.current_board.tmx_data.width * self.current_board.tmx_data.tilewidth, self.current_board.tmx_data.height * self.current_board.tmx_data.tileheight) - self.load_overlay() - def get_tile_pos_at_position(self, pos): """ Return (x, y) tile_pos if there is a tile at 'pos', and @@ -133,9 +122,9 @@ class BoardManager(manager.Manager): self.load_overlay() # TEMP!!!! - self.create_move_range(self.game.piece_manager.selected_piece) + self.create_move_range(self.bus.fetch_selected_piece) for t in self.move_targets: - e = entity.Entity(self.game.sheet_manager.loaded_sheets["board_overlays_1"], (1, 0)) + e = entity.Entity(self.bus.fetch_sheet("board_overlays_1"), (1, 0)) e.set_position((t[0] * self.current_board.tmx_data.tilewidth, t[1] * self.current_board.tmx_data.tileheight)) e.custom_flags = ("OverlayMove", t) self.board_overlay.add(e) diff --git a/src/entity.py b/src/entity.py @@ -7,25 +7,6 @@ from .constants import * ############# # TODO: -# 1. Some serious refactoring needs to happen here. EntityManager needs to -# be brought in line with how managers in general are imagined to work -# now, especially if the generic manager is going to be significantly -# extended and the bus is going to be implemented. The differences -# between a VGO and an Entity are blurred right now. Hypothetically -# speaking, an Entity should be an extended VGO that has features that -# go beyond what a generally-extended pygame Sprite object should have. -# A VGO is a just a sprite that can be drawn and animated by any other -# object, but an Entity should be created and managed ONLY by the -# EntityManager object, because of its extensions. Positioning and -# animating can be VGO functions, but objects you interact with should -# be Entities. This means the EntityManager should be active and working -# in any mode that has on-screen object interaction (e.g. in Menu mode). -# This is NOT how EntityManager currently works and refactoring of the -# EntityManager, Entity, and VGO objects will be required to bring the -# imagined function of this system of objects to realization. One way to -# accomplish some of this would be to try to encapsulate more of what -# EntityManager does each frame into its own update method, and make -# the behavoir therein game_mode-conditional. # 2. An alternative to the above: Reimagine EntityManager as PieceManager, # Meaning it is only responsible for board Piece entities. The BoardCursor # could be handled by a seperate manager of its own, which could manage @@ -35,7 +16,7 @@ from .constants import * # be something PieceManager handles). All of this would be in line with # the natural path that the code has been taking, whereby there is not # one single management object for ALL entities, but rather entities and -# other VGOs are drawn and updated by the managers that logically are +# other Entity are drawn and updated by the managers that logically are # already associated with them. Drawing entities is a pan-Manager thing, # and one of the important distinctions between managers and subsystems. # The codebase should probably reflect this by doing away with EntityManager @@ -44,10 +25,10 @@ from .constants import * # object called ObjectOracle. This subsystem could be alerted each time # a new object is created, and could maintain a list of references to # those objects. It could manage ID by itself, and spread it across any -# VGO, not just Entities. VGOs would know their own ID, and they could be +# Entity, not just Entities. Entity would know their own ID, and they could be # accessed from the oracly by ID by any object with a basic call to # game.oracle. It would be excellent for debug as well. It is possible that -# even the non-VGO objects like the managers should have IDs and be referred +# even the non-Entity objects like the managers should have IDs and be referred # to by the oracle. # This file contains: @@ -55,7 +36,6 @@ from .constants import * # 2. Various kinds of specialized entity classes that don't fit in other source files # TODO: This should eventually use LayeredDirty sprites for performance reasons -# TODO: Eventually need to add a UI-element class type (sub of entity? Should entity replace VGO entirely???) ############################ # Section 1 - Entity class # @@ -63,7 +43,7 @@ from .constants import * class Entity(pygame.sprite.DirtySprite): """ - The parent of all visible objects. VisibleGameObject (VGO) is + The parent of all visible objects. The Entity object itself is essentially an extended, customised version of the PyGame Sprite object. Entity supports animations, motions (movement over time), and tile operations, but none of that is required. @@ -79,7 +59,7 @@ class Entity(pygame.sprite.DirtySprite): self.image = sheet.sprites[sprite] self.rect = self.image.get_rect() self.rect.topleft = (0, 0) - self.custom_flags = None # Used to pass special info to VGOs + self.custom_flags = None # Used to pass special info to Entities # DirtySprite class defaults self.visible = 1 @@ -102,19 +82,19 @@ class Entity(pygame.sprite.DirtySprite): self.tile_pos = (-1, -1) self.tile_gid = None - def set_sprite(self, sprite_coord): + def set_sprite(self, sprite): """ - Set the VGO's sprite to another one on the board. The - argument 'sprite_coord' is a tuple (x, y). This is used + Set the Entity's sprite to another one on the board. + The argument 'sprite' is a tuple (x, y). This is used to assign an image from the saved sheet to non-animated - VGO objects. + Entity objects. """ - # TODO: Error-checking - self.image = self.sheet.sprites[sprite_coord] + if sprite in self.sheet.sprites.keys(): + self.image = self.sheet.sprites[sprite_coord] def set_animation(self, new_animation, play = False, init_frame = 0): """ - Assign a new animation to this VGO and configure all + Assign a new animation to this Entity and configure all necessary values to get it playing. """ self.animation = new_animation @@ -125,12 +105,11 @@ class Entity(pygame.sprite.DirtySprite): def set_motion(self, target_pos, speed): """ - Assign a new motion to this VGO and start playing it. + Assign a new motion to this Entity and start playing it. Unlike animations, motions must be played if assigned. - Directions go by center rather than topleft. """ self.motion = { - "target" : (target_pos[0] + (TILE_WIDTH / 2), target_pos[1] + (TILE_HEIGHT / 2)), + "target" : target_pos, "speed" : speed, "direction" : ((target_pos[0] - self.rect.topleft[0]) / speed, (target_pos[1] - self.rect.topleft[1]) / speed), "timer" : speed @@ -207,8 +186,8 @@ class Entity(pygame.sprite.DirtySprite): def update(self, surface = None): """ - Draw the VGO to the surface. Also calls act() for update - logic for specific VGO children, and animate() to animate + Draw the Entity to the surface. Also calls act() for update + logic for specific Entity children, and animate() to animate the sprite image. """ self.act() diff --git a/src/game.py b/src/game.py @@ -43,7 +43,7 @@ class Game(object): self.interface = subsystem.GameInterface(self) self.manager_bus = subsystem.ManagerBus(self) self.camera = subsystem.GameCamera(self) - self.object_oracle = subsystem.ObjectOrace(self) + self.object_oracle = subsystem.ObjectOracle(self) self.save_system = subsystem.SaveSystem(self) # Managers @@ -80,16 +80,14 @@ class Game(object): if new_mode == STATE_MODES.Main_Menu_Mode: self.control_mode = CTRL_MODES.Main_Menu_Normal self.menu_manager.load_menu_from_file("mainmenu.json") - self.menu_manager.switch_to_menu("mainmenu.json") self.camera.load_camera_surface((SCREEN_WIDTH, SCREEN_HEIGHT)) elif new_mode == STATE_MODES.Battle_Mode: self.control_mode = CTRL_MODES.Turn_Normal # TODO: Obv this must be made more generic. Currently only # sources from the one map file. #self.board_manager.load_board_from_file("testmap1.tmx") - #self.board_manager.switch_to_board("testmap1.tmx") #self.entity_manager.load_entities_from_json("testmap1.json") - #self.entity_manager.load_tile_cursor("cursor1") + self.piece_manager.load_tile_cursor("cursor1") self.camera.load_camera_surface(self.board_manager.current_board_dimensions) elif new_mode == STATE_MODES.Still_Scene_Mode: self.control_mode = CTRL_MODES.Still_Scene_Normal diff --git a/src/menu.py b/src/menu.py @@ -31,21 +31,13 @@ class MenuManager(manager.Manager): # Important values self.current_menu = None - self.loaded_menus = {} def load_menu_from_file(self, menufile): """ Load a Menu object from a provided menu definition file. """ - self.loaded_menus[menufile] = Menu(self, menufile) - - def switch_to_menu(self, menuname): - """ - Switch to the given loaded Menu. - """ - if menuname in self.loaded_menus.keys(): - self.current_menu = self.loaded_menus[menuname] + self.current_menu = Menu(self, menufile) def trigger_button_at_pos(self, pos): """ diff --git a/src/piece.py b/src/piece.py @@ -68,8 +68,7 @@ class PieceManager(manager.Manager): """ Load a TileCursor object to highlight selected tiles. """ - self.tile_cursor = TileCursor("Tile_Cursor", self.total_entities, self.bus.fetch_sheet(sheet)) - self.tile_cursor.set_animation(self.bus.fetch_animation("cursor1", "pulse"), True) + self.tile_cursor = TileCursor(self.bus.fetch_sheet(sheet), (0, 0), self.bus.fetch_animation(sheet, "pulse"), True) def get_piece_by_name(self, name): """ @@ -217,7 +216,9 @@ class Piece(entity.Entity): Object that represents a playable piece on the board. Mostly only differs from entity in that it expects the standard animation format to allow for facing, moving, etc. Has some - sligthly modified move_motion and set_motion methods. + sligthly modified move_motion and set_motion methods. Also + has much more support for existing on a Board and amongst + tiles. """ def __init__(self, sheet, sprite = (0, 0), animation = None, animated = False, @@ -297,7 +298,8 @@ class Piece(entity.Entity): """ if self.current_tile_path != None and self.path_moving: if self.motion == {} and self.current_tile_path_index < len(self.current_tile_path): - next_tar = (self.current_tile_path[self.current_tile_path_index][0] * TILE_WIDTH, self.current_tile_path[self.current_tile_path_index][1] * TILE_HEIGHT) + next_tar = ((self.current_tile_path[self.current_tile_path_index][0] * TILE_WIDTH) + (TILE_WIDTH / 2), + (self.current_tile_path[self.current_tile_path_index][1] * TILE_HEIGHT) + (TILE_HEIGHT / 2)) self.set_motion(next_tar, PIECE_MOVE_SPEED) #anim = None #if next_tar[ diff --git a/src/subsystem.py b/src/subsystem.py @@ -163,6 +163,8 @@ class ManagerBus(GameSubsystem): return self.game.piece_manager.get_piece_by_name(name) def fetch_piece_by_tile(self, tile_pos): return self.game.piece_manager.get_piece_by_tile(tile_pos) + def fetch_selected_piece(self): + return self.game.piece_manager.selected_piece def fetch_tile_by_screen_pos(self, position): return self.game.board_manager.get_tile_by_position(position)