Return to repo list

heart-of-gold

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

commit 4d07565d741a1384ba1ea7320ba9abf7be4c67f1
parent e42b38f1253b684d9be7579a527d381e4f266e2e
Author: Erik Letson <hmagellan@hmagellan.com>
Date:   Wed, 16 Sep 2020 00:24:51 -0500

Added Unit functionality

Diffstat:
Mdata/json/ents/testmap1.json | 2+-
Adata/json/stats/jisella_1.json | 40++++++++++++++++++++++++++++++++++++++++
Msrc/constants.py | 1+
Msrc/game.py | 8+++++---
Msrc/images.py | 14++++++++++----
Asrc/unit.py | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/vgo.py | 24+++++++++++++++++-------
7 files changed, 138 insertions(+), 15 deletions(-)

diff --git a/data/json/ents/testmap1.json b/data/json/ents/testmap1.json @@ -1,6 +1,6 @@ { "testent1" : { - "name" : "Jisella_Unit", + "name" : "Jisella", "sheet" : "jisella_1", "visible" : true, "animation" : "stand_L", diff --git a/data/json/stats/jisella_1.json b/data/json/stats/jisella_1.json @@ -0,0 +1,40 @@ +{ + "name" : "Jisella", + "LVL" : 1, + "HP" : 100, + "HP_GR" : 100, + "ATK" : 135, + "ATK_GR" : 110, + "DEF" : 45, + "DEF_GR" : 100, + "SPD" : 100, + "SPD_GR" : 100, + "ACC" : 60, + "ACC_GR" : 100, + "INT" : 50, + "INT_GR" : 90, + "WIS" : 30, + "WIS_GR" : 90, + "MOVE" : 5, + "CRIT" : 10, + "SKIL" : 4, + "RANK" : 1, + "LEAD" : 4, + "INIT" : 5, + "MORL" : 70, + "AFFINITY" : "Fire", + "WEAPON" : "Sword", + "POWERS" : [ + "Courage" + ], + "KNOWN_SKILLS" : [ + "Charge", + "Drive" + ], + "EQ_SKILLS" : [ + "Charge", + "Drive", + false, + false + ] +} diff --git a/src/constants.py b/src/constants.py @@ -31,3 +31,4 @@ FONT_PATH = os.path.join(DATA_PATH, "font") BOARD_PATH = os.path.join(DATA_PATH, "map") JSON_PATH = os.path.join(DATA_PATH, "json") ENTITY_JSON_PATH = os.path.join(JSON_PATH, "ents") +STATUS_JSON_PATH = os.path.join(JSON_PATH, "stats") diff --git a/src/game.py b/src/game.py @@ -1,5 +1,5 @@ import pygame -from . import images, board, vgo +from . import images, board, vgo, unit from .constants import SCREEN_WIDTH, SCREEN_HEIGHT, FRAMERATE, TILE_WIDTH, TILE_HEIGHT ########### @@ -42,13 +42,15 @@ class Game(object): self.sheet_manager = images.SheetManager(self) self.board_manager = board.BoardManager(self) self.entity_manager = vgo.EntityManager(self) + self.unit_manager = unit.UnitManager(self) # Setup (This is WIP) # TODO: Fix this up, will see lots of revision - self.sheet_manager.load_sheets("sheets.json") - self.sheet_manager.load_animations("anims.json") + self.sheet_manager.load_sheets_from_json("sheets.json") + self.sheet_manager.load_animations_from_json("anims.json") self.board_manager.load_board_from_file("testmap1.tmx") self.board_manager.switch_to_board("testmap1.tmx") + self.unit_manager.load_stats_from_json("jisella_1.json") self.entity_manager.load_tile_cursor("cursor1") self.entity_manager.load_entities_from_json("testmap1.json") diff --git a/src/images.py b/src/images.py @@ -44,19 +44,19 @@ class SheetManager(manager.Manager): self.loaded_sheets = {} self.animations = {} - def load_sheets(self, sheetjson): + def load_sheets_from_json(self, sheet_json): """ Load sheets from the given definition JSON file. """ - self.sheets_def = json.load(open(os.path.join(JSON_PATH, sheetjson))) + self.sheets_def = json.load(open(os.path.join(JSON_PATH, sheet_json))) for j in self.sheets_def: self.loaded_sheets[j] = Sheet(self.sheets_def[j]["filename"], tuple(self.sheets_def[j]["dimensions"]), self.sheets_def[j]["total_sprites"]) - def load_animations(self, animjson): + def load_animations_from_json(self, anim_json): """ Load animations from the given definition JSON file. """ - self.animations = json.load(open(os.path.join(JSON_PATH, animjson))) + self.animations = json.load(open(os.path.join(JSON_PATH, anim_json))) # Make sure the sheet subimage coords are in tuple form for c in self.animations: @@ -67,10 +67,16 @@ class SheetManager(manager.Manager): self.animations[c][a][i][v] = tuple(self.animations[c][a][i][v]) def get_sheet(self, name): + """ + Return the sheet matching name if it exists. + """ if name in self.loaded_sheets.keys(): return self.loaded_sheets[name] def get_animation(self, name): + """ + Return the animation matching name if it exists. + """ if name in self.loaded_animations.keys(): return self.loaded_animations[name] diff --git a/src/unit.py b/src/unit.py @@ -0,0 +1,64 @@ +import pygame, json, os +from . import manager +from .constants import STATUS_JSON_PATH + +########### +# unit.py # +########### + +# This file contains +# 1. The UnitManager class, which loads Unit JSONs and keeps track of them (like SheetManager) +# 2. The Unit class, which represents the statistics of a charachter unit + +################################# +# Section 1. UnitManager Object # +################################# + +class UnitManager(manager.Manager): + """ + Loads and manages Unit status JSONs. This manager is + called whenever a Unit must be created and assigned to + an Entity, and it gives back a loaded dict representing + the stats of that Unit. + """ + + def __init__(self, game): + + # Parent initialization + super().__init__(game) + + # Saved values + self.loaded_stats = {} + + def load_stats_from_json(self, stats_json): + """ + Load the stats from a given stats_json file. + """ + j = json.load(open(os.path.join(STATUS_JSON_PATH, stats_json))) + self.loaded_stats[j["name"]] = j + + def get_stats(self, name): + """ + Return stats if it exists. + """ + if name in self.loaded_stats.keys(): + return self.loaded_stats[name] + +########################## +# Section 2. Unit Object # +########################## + +class Unit(object): + """ + Unit represents a turn-taking Entity's statistics that + are important for gameplay. An Entity can have a Unit, + and that Unit can be used to compare against the other + Unit's owned by other Entities. + """ + + def __init__(self, entity, stats_definition): + + # Saved values + self.entity = entity + self.static_stats = stats_definition + self.active_stats = stats_definition diff --git a/src/vgo.py b/src/vgo.py @@ -1,5 +1,5 @@ import pygame, json, os -from . import manager +from . import manager, unit from .constants import ENTITY_JSON_PATH, TILE_WIDTH, TILE_HEIGHT ########## @@ -109,10 +109,12 @@ class Entity(VisibleGameObject): by an EntityManager and record tile x, y and gid values. An Entity does not have to occupy a tile but it can. Entities also have a name (human-readable string set in their definition) - and a ent_id (number assigned by entity manager). + and a ent_id (number assigned by entity manager). Entities can + also optionally have a Unit assigned to them to represent + their statistics in gameplay. """ - def __init__(self, name, ent_id, sheet, visible = True, animation = None, animated = False, passable = False): + def __init__(self, name, ent_id, sheet, visible = True, animation = None, animated = False, passable = False, unit = None): # Parent initialization super().__init__(sheet, visible, animation, animated) @@ -121,6 +123,7 @@ class Entity(VisibleGameObject): self.name = name self.ent_id = ent_id self.passable = passable + self.unit = unit # Tile values self.tile_pos = (-1, -1) @@ -151,10 +154,10 @@ class TileCursor(Entity): tiles. """ - def __init__(self, name, ent_id, sheet, visible = True, animation = None, animated = False, passable = True): + def __init__(self, name, ent_id, sheet, visible = True, animation = None, animated = False, passable = True, unit = None): # Parent initialization - super().__init__(name, ent_id, sheet, visible, animation, animated, passable) + super().__init__(name, ent_id, sheet, visible, animation, animated, passable, unit) ############################################## # Section 4 - Managers for VGOs & Subclasses # @@ -191,10 +194,11 @@ class EntityManager(manager.Manager): j = json.load(open(os.path.join(ENTITY_JSON_PATH, entsjson))) for e in j: + s = self.game.unit_manager.get_stats(j[e]["name"]) ne = Entity(j[e]["name"], self.total_entities, self.game.sheet_manager.loaded_sheets[j[e]["sheet"]], j[e]["visible"], self.game.sheet_manager.animations[j[e]["sheet"]][j[e]["animation"]], - j[e]["animated"], j[e]["passable"]) + j[e]["animated"], j[e]["passable"], unit.Unit(self, s)) ne.assign_tile(self.game.board_manager.get_tile_at_tile_pos(tuple(j[e]["tile"]))) ne.snap_to_tile() self.add_entity(ne) @@ -211,6 +215,10 @@ class EntityManager(manager.Manager): Snap the TileCursor object's position to 'pos' and set the tile GID there as the current tile_cursor's selected tile. """ + # TODO: Cleanup this. It is mostly a bunch of additional + # stuff that doesn't have to be here. It just helps with + # debug. The only important things are the two calls to + # self.tile_cursor methods. ot = (self.tile_cursor.tile_pos, self.tile_cursor.tile_gid) self.tile_cursor.assign_tile(tile_def) self.tile_cursor.snap_to_tile() @@ -219,7 +227,9 @@ class EntityManager(manager.Manager): print(self.game.board_manager.get_tile_at_tile_pos(self.tile_cursor.tile_pos)) if e != []: for en in e: - print("Occupied by: " + en.name + "(" + str(en.ent_id) + ")") + if en.unit != None: + print("Occupied by: " + en.name + "(" + str(en.ent_id) + ")") + print("HP: " + str(en.unit.active_stats["HP"])) def get_entities_by_tile(self, tile_def): """