commit 90d29a2dfa37b4095e10be7259bdea67d0c15645
parent 6ce38ffedf38474f383d09b4982589ba9715e222
Author: Erik Letson <hmagellan@hmagellan.com>
Date: Sun, 20 Sep 2020 23:38:37 -0500
Animated movement system, big additions
Diffstat:
6 files changed, 149 insertions(+), 25 deletions(-)
diff --git a/data/json/anims.json b/data/json/anims.json
@@ -9,6 +9,60 @@
{ "sprite" : [1, 1], "timer" : 4 },
{ "sprite" : [2, 1], "timer" : 4 },
{ "sprite" : [3, 1], "timer" : 4 }
+ ],
+ "stand_R" : [
+ { "sprite" : [4, 0], "timer" : 4 },
+ { "sprite" : [5, 0], "timer" : 4 },
+ { "sprite" : [6, 0], "timer" : 4 },
+ { "sprite" : [7, 0], "timer" : 4 },
+ { "sprite" : [4, 1], "timer" : 4 },
+ { "sprite" : [5, 1], "timer" : 4 },
+ { "sprite" : [6, 1], "timer" : 4 },
+ { "sprite" : [7, 1], "timer" : 4 }
+ ],
+ "stand_U" : [
+ { "sprite" : [8, 0], "timer" : 4 },
+ { "sprite" : [9, 0], "timer" : 4 },
+ { "sprite" : [10, 0], "timer" : 4 },
+ { "sprite" : [11, 0], "timer" : 4 },
+ { "sprite" : [8, 1], "timer" : 4 },
+ { "sprite" : [9, 1], "timer" : 4 },
+ { "sprite" : [10, 1], "timer" : 4 },
+ { "sprite" : [11, 1], "timer" : 4 }
+ ],
+ "stand_D" : [
+ { "sprite" : [0, 0], "timer" : 4 },
+ { "sprite" : [1, 0], "timer" : 4 },
+ { "sprite" : [2, 0], "timer" : 4 },
+ { "sprite" : [3, 0], "timer" : 4 },
+ { "sprite" : [0, 1], "timer" : 4 },
+ { "sprite" : [1, 1], "timer" : 4 },
+ { "sprite" : [2, 1], "timer" : 4 },
+ { "sprite" : [3, 1], "timer" : 4 }
+ ],
+ "walk_L" : [
+ { "sprite" : [0, 2], "timer" : 6 },
+ { "sprite" : [1, 2], "timer" : 6 },
+ { "sprite" : [2, 2], "timer" : 6 },
+ { "sprite" : [3, 2], "timer" : 6 }
+ ],
+ "walk_R" : [
+ { "sprite" : [4, 2], "timer" : 6 },
+ { "sprite" : [5, 2], "timer" : 6 },
+ { "sprite" : [6, 2], "timer" : 6 },
+ { "sprite" : [7, 2], "timer" : 6 }
+ ],
+ "walk_U" : [
+ { "sprite" : [8, 2], "timer" : 6 },
+ { "sprite" : [9, 2], "timer" : 6 },
+ { "sprite" : [10, 2], "timer" : 6 },
+ { "sprite" : [11, 2], "timer" : 6 }
+ ],
+ "walk_D" : [
+ { "sprite" : [0, 2], "timer" : 6 },
+ { "sprite" : [1, 2], "timer" : 6 },
+ { "sprite" : [2, 2], "timer" : 6 },
+ { "sprite" : [3, 2], "timer" : 6 }
]
},
"cursor1" : {
diff --git a/data/json/ents/testmap1.json b/data/json/ents/testmap1.json
@@ -1,6 +1,7 @@
{
"testent1" : {
"name" : "Jisella",
+ "type" : "Piece",
"sheet" : "jisella_1",
"visible" : true,
"animation" : "stand_L",
diff --git a/main.py b/main.py
@@ -11,6 +11,7 @@ from src import game
# the game would be in a loaded state. This seems the ideal solution, and it can be put off a bit.
# 3. Implement the "draw()" functionality of DirtySprite for all VGOs, which will be done in anything that manages a LayeredDirty group, e.g. in the
# EntityManager object.
+# 4. Entities should probably be passed their manager. VGOs probably do not need this.
pygame.init()
diff --git a/src/game.py b/src/game.py
@@ -176,6 +176,7 @@ class GameInterface(GameSubsystem):
elif self.control_mode == "Turn_Select_Move":
if self.game.entity_manager.set_entity_move_to_tile_pos(self.game.entity_manager.selected_entity, self.game.board_manager.get_overlay_move_vgo_at_pos(pygame.mouse.get_pos())):
self.control_mode = "Turn_Normal"
+ # TODO: Should this really be done here???
self.game.board_manager.load_overlay()
def handle_mouse_release(self, event):
diff --git a/src/images.py b/src/images.py
@@ -50,7 +50,7 @@ class SheetManager(manager.Manager):
"""
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"])
+ self.loaded_sheets[j] = Sheet(self, self.sheets_def[j]["filename"], j, tuple(self.sheets_def[j]["dimensions"]), self.sheets_def[j]["total_sprites"])
def load_animations_from_json(self, anim_json):
"""
@@ -91,10 +91,12 @@ class Sheet(object):
(that is, all sprites are the same dimensions).
"""
- def __init__(self, filename, sprite_size, total_sprites):
+ def __init__(self, manager, filename, name, sprite_size, total_sprites):
# Important values
+ self.manager = manager
self.filename = filename
+ self.name = name
self.sprite_dimensions = sprite_size
self.total_sprites = total_sprites
self.sprites = {}
diff --git a/src/vgo.py b/src/vgo.py
@@ -52,8 +52,8 @@ class VisibleGameObject(pygame.sprite.DirtySprite):
self.set_animation(animation, animated)
# Motion values
- self.motion = []
- self.motion_index = -1
+ self.motion = {}
+ self.motion_timer = 0
def set_sprite(self, sprite_coord):
"""
@@ -81,17 +81,12 @@ class VisibleGameObject(pygame.sprite.DirtySprite):
Assign a new motion to this VGO and start playing it.
Unlike animations, motions must be played if assigned.
"""
- # TODO: THIS OBVIOUSLY DOES NOT WORK!!!!
- # FIXME!!!!
- mx = target_pos[0] - self.rect.topleft[0]
- my = target_pos[1] - self.rect.topleft[1]
- direc = math.sqrt((mx**2) + (my**2))
- uv = (mx / direc) + (my / direc)
- self.motion = [self.rect.topleft]
- for p in range(2, 10):# TODO: 10 steps is totally arbitrary
- self.motion.append((self.rect.topleft[0] + (uv * p * speed), self.rect.topleft[1] + (uv * p * speed)))
- self.motion.append(target_pos)
- self.motion_index = 0
+ self.motion = {
+ "target" : target_pos,
+ "speed" : speed,
+ "direction" : ((target_pos[0] - self.rect.topleft[0]) / speed, (target_pos[1] - self.rect.topleft[1]) / speed),
+ "timer" : speed
+ }
def set_position(self, pos):
"""
@@ -119,12 +114,18 @@ class VisibleGameObject(pygame.sprite.DirtySprite):
"""
Perform current motion, if it is set.
"""
- if self.motion != [] and self.motion_index != -1 and self.motion_index < len(self.motion) - 1:
- self.rect.topleft = self.motion[self.motion_index]
- self.motion_index += 1
+ if self.motion != {} and not self.rect.collidepoint(self.motion["target"]):
+ if self.motion_timer == 0:
+ mx = self.rect.topleft[0] + self.motion["direction"][0]
+ my = self.rect.topleft[1] + self.motion["direction"][1]
+ self.rect.topleft = (mx, my)
+ self.motion_timer = self.motion["speed"]
+ else:
+ self.motion_timer -= 1
else:
- self.motion = []
- self.motion_index = -1
+ if self.motion != {}:
+ self.rect.topleft = self.motion["target"] # Make sure we end up in exactly the right spot
+ self.motion = {}
def act(self):
"""
@@ -213,6 +214,63 @@ class TileCursor(Entity):
# DirtySprite settings
self.layer = 1
+class Piece(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.
+ """
+
+ def __init__(self, name, ent_id, sheet, animation = None, animated = False, passable = False, unit = None):
+
+ # Parent initialization
+ super().__init__(name, ent_id, sheet, animation, animated, passable, unit)
+
+ # Face settings
+ self.facing = "D" # TODO: This should ABSOLUTELY be an enum
+
+ # Others
+ self.back_to_stand = False #TODO: This may not be the best way
+
+ def set_motion(self, target_pos, speed):
+ """
+ Overwrite of the basic VGO version to support facing and
+ animating automatically.
+ """
+ super().set_motion(target_pos, speed)
+
+ # Decide facing
+ mx = target_pos[0] - self.rect.topleft[0]
+ my = target_pos[1] - self.rect.topleft[1]
+ a = math.atan2(mx, my) * 180 / math.pi
+ if a >= -67.5 and a < 67.5:
+ self.facing = "D"
+ elif a >= 67.5 and a < 112.5:
+ self.facing = "R"
+ elif a > 112.5 or a < -112.5:
+ self.facing = "U"
+ else:
+ self.facing = "L"
+
+ # Set a movement animation
+ # TODO: It may be neccessary in the future to indicate whether or not this
+ # animation should be assigned according to whether or not a board move is
+ # actually taking place. Also, this is a very roundabout way to reference
+ # the sheet's animations. Maybe sheets should be aware of their anims?
+ self.set_animation(self.sheet.manager.animations[self.sheet.name]["walk_" + self.facing], True)
+ self.back_to_stand = True
+
+ def act(self):
+ """
+ Overwriting basic act mode.
+ """
+ # TODO: Something else should be done so that this doesn't overwrite other
+ # legit non-walking, non-standing anims. THIS MAY NOT BE THE BEST.
+ if self.motion == {} and self.back_to_stand:
+ self.set_animation(self.sheet.manager.animations[self.sheet.name]["stand_" + self.facing], True)
+ self.back_to_stand = False
+
##############################################
# Section 4 - Managers for VGOs & Subclasses #
##############################################
@@ -249,10 +307,17 @@ class EntityManager(manager.Manager):
j = json.load(open(os.path.join(ENTITY_JSON_PATH, entsjson)))
for e in j:
- ne = Entity(j[e]["name"], self.total_entities,
- self.game.sheet_manager.loaded_sheets[j[e]["sheet"]],
- self.game.sheet_manager.animations[j[e]["sheet"]][j[e]["animation"]],
- j[e]["animated"], j[e]["passable"], unit.Unit(self, self.game.unit_manager.get_stats(j[e]["name"])))
+ # TODO: type should be enum
+ if j[e]["type"] == "Entity":
+ ne = Entity(j[e]["name"], self.total_entities,
+ self.game.sheet_manager.loaded_sheets[j[e]["sheet"]],
+ self.game.sheet_manager.animations[j[e]["sheet"]][j[e]["animation"]],
+ j[e]["animated"], j[e]["passable"], unit.Unit(self, self.game.unit_manager.get_stats(j[e]["name"])))
+ elif j[e]["type"] == "Piece":
+ ne = Piece(j[e]["name"], self.total_entities,
+ self.game.sheet_manager.loaded_sheets[j[e]["sheet"]],
+ self.game.sheet_manager.animations[j[e]["sheet"]][j[e]["animation"]],
+ j[e]["animated"], j[e]["passable"], unit.Unit(self, self.game.unit_manager.get_stats(j[e]["name"])))
ne.assign_tile(self.game.board_manager.get_tile_at_tile_pos(tuple(j[e]["tile"])))
ne.snap_to_tile()
self.add_entity(ne)
@@ -329,7 +394,7 @@ class EntityManager(manager.Manager):
"""
# TODO: Set speed of motion somehow, maybe calculated from MOVE of entity
if entity != None and tile_pos != None:
- entity.set_motion((tile_pos[0] * self.game.board_manager.current_board.tmx_data.tilewidth, tile_pos[1] * self.game.board_manager.current_board.tmx_data.tileheight), 10)
+ entity.set_motion((tile_pos[0] * self.game.board_manager.current_board.tmx_data.tilewidth, tile_pos[1] * self.game.board_manager.current_board.tmx_data.tileheight), 6)
entity.tile_pos = tile_pos
return True
else: