Return to repo list

heart-of-gold

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

commit 6ce38ffedf38474f383d09b4982589ba9715e222
parent 7fb88b39411974f6e9427ebe88ef443b9ce7e428
Author: Erik Letson <hmagellan@hmagellan.com>
Date:   Sun, 20 Sep 2020 20:43:10 -0500

Workingh thru movement issues, checkpoint 1

Diffstat:
Msrc/board.py | 18+++++++++++++++---
Msrc/game.py | 11++++++++++-
Msrc/vgo.py | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
3 files changed, 90 insertions(+), 12 deletions(-)

diff --git a/src/board.py b/src/board.py @@ -50,6 +50,7 @@ class BoardManager(manager.Manager): if self.current_board.tmx_data.get_tile_properties_by_gid(gid)["Passable"] == 1: v = vgo.VisibleGameObject(self.game.sheet_manager.loaded_sheets["board_overlays_1"]) v.set_position((x * self.current_board.tmx_data.tilewidth, y * self.current_board.tmx_data.tileheight)) + v.custom_flags = "OverlayGrid" self.board_overlay.add(v) def switch_to_board(self, boardname): @@ -74,18 +75,28 @@ class BoardManager(manager.Manager): return (x, y, gid) return None - def get_tile_at_tile_pos(self, pos): + def get_tile_at_tile_pos(self, tile_pos): """ - Return (x, y, gid) if there is a tile at tile_pos '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 pos == (x, y): + if tile_pos == (x, y): return (x, y, gid) return None + def get_overlay_move_vgo_at_pos(self, pos): + """ + Return (x, y) if there is a legal overlay move vgo at 'pos', + and return None otherwise. + """ + for v in self.board_overlay: + if "OverlayMove" in v.custom_flags and v.rect.collidepoint(pos): + return v.custom_flags[1] + return None + def display_as_move_range(self, tile_pos_list): """ Display a move range from a given list of tile_pos @@ -104,6 +115,7 @@ class BoardManager(manager.Manager): v = vgo.VisibleGameObject(self.game.sheet_manager.loaded_sheets["board_overlays_1"]) v.set_position((x * self.current_board.tmx_data.tilewidth, y * self.current_board.tmx_data.tileheight)) v.set_sprite((1, 0)) + v.custom_flags = ("OverlayMove", (x, y)) self.board_overlay.add(v) def update_board(self, surface = None): diff --git a/src/game.py b/src/game.py @@ -135,6 +135,9 @@ class GameInterface(GameSubsystem): # Parent init super().__init__(game) + + # Saved values + self.control_mode = "Turn_Normal" # TODO: This should be an enum def handle_events(self, events): """ @@ -167,7 +170,13 @@ class GameInterface(GameSubsystem): React to a mousebutton being clicked. """ if event.button == 1: - self.game.entity_manager.select_entities_with_tile_cursor(self.game.board_manager.get_tile_at_position(pygame.mouse.get_pos())) + if self.control_mode == "Turn_Normal": + if self.game.entity_manager.select_entities_with_tile_cursor(self.game.board_manager.get_tile_at_position(pygame.mouse.get_pos())): + self.control_mode = "Turn_Select_Move" + 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" + self.game.board_manager.load_overlay() def handle_mouse_release(self, event): """ diff --git a/src/vgo.py b/src/vgo.py @@ -1,4 +1,4 @@ -import pygame, json, os +import pygame, json, os, math from . import manager, unit from .constants import ENTITY_JSON_PATH, TILE_WIDTH, TILE_HEIGHT @@ -36,6 +36,7 @@ class VisibleGameObject(pygame.sprite.DirtySprite): self.image = sheet.sprites[(0, 0)] # TODO: Should this be assigned?? self.rect = self.image.get_rect() self.rect.topleft = (0, 0) + self.custom_flags = None # Used to pass special info to VGOs # DirtySprite class defaults self.visible = 1 @@ -50,6 +51,10 @@ class VisibleGameObject(pygame.sprite.DirtySprite): if animated: self.set_animation(animation, animated) + # Motion values + self.motion = [] + self.motion_index = -1 + def set_sprite(self, sprite_coord): """ Set the VGO's sprite to another one on the board. The @@ -71,6 +76,30 @@ class VisibleGameObject(pygame.sprite.DirtySprite): self.image = self.sheet.sprites[new_animation[init_frame]["sprite"]] self.animated = play + def set_motion(self, target_pos, speed): + """ + 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 + + def set_position(self, pos): + """ + Assign the rect topleft to a raw position tuple, independent + of e.g. a tile. + """ + self.rect.topleft = pos + def animate(self): """ Play the current animation. This method is called as part of @@ -85,13 +114,17 @@ class VisibleGameObject(pygame.sprite.DirtySprite): self.animation_frame = 0 self.animation_timer = self.animation[self.animation_frame]["timer"] self.image = self.sheet.sprites[self.animation[self.animation_frame]["sprite"]] - - def set_position(self, pos): + + def motion_move(self): """ - Assign the rect topleft to a raw position tuple, independent - of e.g. a tile. + Perform current motion, if it is set. """ - self.rect.topleft = pos + 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 + else: + self.motion = [] + self.motion_index = -1 def act(self): """ @@ -109,6 +142,7 @@ class VisibleGameObject(pygame.sprite.DirtySprite): """ self.act() if surface != None: + self.motion_move() if self.animated: self.animate() surface.blit(self.image, self.rect) @@ -173,6 +207,9 @@ class TileCursor(Entity): # Parent initialization super().__init__(name, ent_id, sheet, animation, animated, passable, unit) + # VGO settings + self.custom_flags = "TileCursor" + # DirtySprite settings self.layer = 1 @@ -244,22 +281,27 @@ class EntityManager(manager.Manager): # TODO: Should not just check for TileCursor name, should be something more concrete found_ents = [] for e in self.loaded_entities: - if e.tile_pos == (tile_def[0], tile_def[1]) and e.name != "Tile_Cursor": + if e.tile_pos == (tile_def[0], tile_def[1]) and e.custom_flags != "TileCursor": found_ents.append(e) return found_ents def select_entities_with_tile_cursor(self, tile_def): """ Select the current entity under the tile cursor by way - of the tile_def. + of the tile_def. Returns True if an entity is selected, + and False otherwise. """ + # TODO: Eventually this should return info about the team of the selected + # entity so that GameInterface can make control mode decisions. e = self.get_entities_by_tile(tile_def) if e != []: self.selected_entity = e[0] # Select only the topmost ent on this tile self.game.board_manager.display_as_move_range(self.get_entity_legal_move_tile_pos(self.selected_entity)) + return True else: self.selected_entity = None self.game.board_manager.load_overlay() + return False def get_entity_legal_move_tile_pos(self, entity): """ @@ -278,6 +320,21 @@ class EntityManager(manager.Manager): legal_moves.append((x, y)) return legal_moves + def set_entity_move_to_tile_pos(self, entity, tile_pos): + """ + Sets the entity to move to the given tile_pos. A 'move' + is an assignment from the EntityManager. A 'motion' is + a setting similar to an animation (but for spatial travel) + for an entity. + """ + # 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.tile_pos = tile_pos + return True + else: + return False + def update_entities(self, surface = None): """ Update all loaded entities.