commit 058bfaba5be555d04f8c47dea9791b01652908d2
parent 97aa01927c376551006de3134a875ea450857e6f
Author: Erik Letson <hmagellan@hmagellan.com>
Date: Sat, 5 Jun 2021 22:51:57 -0500
added boards
Diffstat:
4 files changed, 183 insertions(+), 2 deletions(-)
diff --git a/src/board.py b/src/board.py
@@ -0,0 +1,179 @@
+import pygame, pytmx, os
+from . import manager, entity
+from .envvars import *
+
+############
+# board.py #
+############
+
+# This file contains:
+# 1. The BoardManager class, which manages boards and swaps between them
+# 2. The Board class, which represents a grid of Tile objects and is the play area
+
+###################################
+# Section 1 - BoardManager Object #
+###################################
+
+class BoardManager(manager.Manager):
+ """
+ BoardManager handles loading and managing Board objects. It
+ is directly subordinate to Game.
+ """
+
+ def __init__(self, game, name, bus, system_bus):
+
+ super().__init__(game, name, bus, system_bus)
+
+ # Board values
+ self.current_board = None
+ self.board_overlay = pygame.sprite.LayeredDirty()
+
+ def load_board(self, boardname):
+ """
+ Load a given board.
+ """
+ # TODO: Bring this inline with loading in managers rather than in managed objects
+ self.current_board = Board(self, boardname)
+ self.load_overlay()
+ self.update(None)
+
+ def load_overlay(self):
+ """
+ Derive an overlay from available loaded board. Calling
+ this has the effect of refreshing the overlay.
+ """
+ self.board_overlay = pygame.sprite.LayeredDirty()
+ for layer in self.current_board.tmx_data.visible_layers:
+ 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.bus.fetch("sheet_manager", "sheets")["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 get_tile_pos_at_position(self, pos):
+ """
+ Return (x, y) tile_pos if there is a tile at 'pos', and
+ return None otherwise.
+ """
+ w = self.current_board.tmx_data.tilewidth
+ h = self.current_board.tmx_data.tileheight
+ for layer in self.current_board.tmx_data.visible_layers:
+ if isinstance(layer, pytmx.TiledTileLayer):
+ for x, y, gid in layer:
+ if pos[0] >= x * w and pos[0] < (x + 1) * w and pos[1] >= y * w and pos[1] < (y + 1) * w:
+ return (x, y)
+ return None
+
+ def get_tile_at_position(self, pos):
+ """
+ Return (x, y, gid) if there is tile at 'pos', and return
+ None otherwise.
+ """
+ w = self.current_board.tmx_data.tilewidth
+ h = self.current_board.tmx_data.tileheight
+ for layer in self.current_board.tmx_data.visible_layers:
+ if isinstance(layer, pytmx.TiledTileLayer):
+ for x, y, gid in layer:
+ if pos[0] >= x * w and pos[0] < (x + 1) * w and pos[1] >= y * w and pos[1] < (y + 1) * w:
+ return (x, y, gid)
+ return None
+
+ def get_tile_at_tile_pos(self, tile_pos):
+ """
+ Return (x, y, gid) if there is a tile at tile_pos 'tile_pos',
+ and return None otherwise.
+ """
+ for layer in self.current_board.tmx_data.visible_layers:
+ if isinstance(layer, pytmx.TiledTileLayer):
+ for x, y, gid in layer:
+ if tile_pos == (x, y):
+ return (x, y, gid)
+ return None
+
+ def get_adjacent_tiles_by_tile_pos(self, tile_pos):
+ """
+ Return cardinal adjacent tiles of the given tile_pos.
+ Return value is a dict, the values of which are either
+ (x, y) tuples or None if the adjacent is outside of the
+ bounds of the board.
+ """
+ adj = {(-1, 0) : None, (1, 0) : None, (0, -1) : None, (0, 1): None}
+ mx = 0
+ my = 0
+ for x in range(0, self.current_board.tmx_data.width):
+ for y in range(0, self.current_board.tmx_data.height):
+ mx = tile_pos[0] - x
+ my = tile_pos[1] - y
+ if (mx, my) in adj.keys():
+ adj[(mx, my)] = (x, y)
+ return adj
+
+ def get_adjacency_list(self, tiles):
+ """
+ Return an adjaceny list of all the tiles included
+ in 'tiles'. Tiles should be a list or tuple. The
+ return value is a dict.
+ """
+ adj_list = {}
+ for t in tiles:
+ adj_list[t] = self.get_adjacent_tiles_by_tile_pos(t)
+ return adj_list
+
+ def expose(self):
+ """
+ Expose info about the board to the ManagerBus.
+ """
+ data = {
+ "current_board" : self.current_board,
+ "board_dimensions" : self.current_board.board_dimensions,
+ "board_pixel_dimensions" : self.current_board.pixel_dimensions,
+ "board_tile_layer" : { (x, y) : gid for layer in self.current_board.tmx_data.visible_layers for x, y, gid in layer if isinstance(layer, pytmx.TiledTileLayer) },
+ "board_overlay" : self.board_overlay
+ }
+ self.bus.record(self.name, data)
+
+ def update_managed(self, surface = None):
+ """
+ Update the current board.
+ """
+ if surface != None:
+ self.current_board.draw_board(surface)
+ self.board_overlay.update(surface)
+
+############################
+# Section 2 - Board Object #
+############################
+
+class Board(object):
+ """
+ Board is an object that consists of a Pytmx Tiled map and
+ some functions for drawing it. Board is managed by a
+ BoardManager object.
+ """
+
+ def __init__(self, manager, boardname):
+
+ # Saved values
+ self.manager = manager
+ self.boardname = boardname
+ self.filename = boardname + ".tmx"
+
+ # Pytmx values
+ self.tmx_data = pytmx.load_pygame(os.path.join(BOARD_PATH, self.boardname, self.filename))
+ self.board_dimensions = (self.tmx_data.width, self.tmx_data.height)
+ self.pixel_dimensions = (self.tmx_data.width * TILE_WIDTH, self.tmx_data.height * TILE_HEIGHT)
+
+ def draw_board(self, surface = None):
+ """
+ Draw the tiles of the board onto the provided PyGame
+ surface object.
+ """
+ for layer in self.tmx_data.visible_layers:
+ if isinstance(layer, pytmx.TiledTileLayer):
+ for x, y, gid in layer:
+ t = self.tmx_data.get_tile_image_by_gid(gid)
+ if t:
+ surface.blit(t, (x * TILE_HEIGHT, y * TILE_WIDTH))
+
diff --git a/src/entity.py b/src/entity.py
@@ -121,7 +121,7 @@ class Entity(pygame.sprite.DirtySprite):
def set_flip(self, hz = None, vt = None):
"""
- Set the flip tuple valse to True or False. hz is for horizontal
+ Set the flip tuple values to True or False. hz is for horizontal
flipping and vt is vertical. If either is None, that value will
not be changed.
"""
diff --git a/src/envvars.py b/src/envvars.py
@@ -30,6 +30,7 @@ IMAGE_PATH = os.path.join(DATA_PATH, "img")
SOUND_PATH = os.path.join(DATA_PATH, "snd")
FONT_PATH = os.path.join(DATA_PATH, "font")
TILE_PATH = os.path.join(DATA_PATH, "tsx")
+BOARD_PATH = os.path.join(DATA_PATH, "boards")
JSON_PATH = os.path.join(DATA_PATH, "json")
SAVE_PATH = os.path.join(str(pathlib.Path.home), ".local", "share", "heart-of-gold", "savegames")
diff --git a/src/game.py b/src/game.py
@@ -1,5 +1,5 @@
import pygame
-from . import interface, bus, camera, sound, images
+from . import interface, bus, camera, sound, images, board
from .envvars import *
###########
@@ -39,6 +39,7 @@ class Game(object):
self.interface = interface.GameInterface(self, "interface", self.subsystem_bus, self.manager_bus)
# Managers
+ self.board_manager = board.BoardManager(self, "board_manager", self.manager_bus, self.subsystem_bus)
# Setup (This is WIP)
#self.sheet_system.load_animations_from_json("anims.json")