Return to repo list

heart-of-gold

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

commit cc11f762e878cda111b4d843f8b9a7693a9acd7c
parent 5860c1a25dbf8dfff3649f68a78f44d363738cd6
Author: Erik Letson <hmagellan@hmagellan.com>
Date:   Fri, 29 Jan 2021 15:39:58 -0600

added generic screen fade effects

Diffstat:
Mdata/json/scenes/scene1.json | 32++++++++++++++++++++++++++++++++
Msrc/constants.py | 3++-
Msrc/manager.py | 15++++++++++++++-
Msrc/scene.py | 96+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
4 files changed, 123 insertions(+), 23 deletions(-)

diff --git a/data/json/scenes/scene1.json b/data/json/scenes/scene1.json @@ -7,6 +7,22 @@ "bg_sprite" : [0, 0], "script" : [ { + "speaker" : "", + "name_font" : "A", + "name_pos" : [20, 480], + "line_font" : "A", + "voice" : null, + "portrait" : null, + "line" : "", + "characters" : [ ], + "effects" : [ + { + "call" : "ef_scene_fade", + "data" : [[0, 0, 0], 0, 0, -30, -30, 30] + } + ] + }, + { "speaker" : "Jisella", "name_font" : "A", "name_pos" : [20, 480], @@ -51,6 +67,22 @@ "characters" : [ ], "effects" : [ { + "call" : "ef_scene_fade", + "data" : [[0, 0, 0], "-SW", 0, 38, 0, 30] + } + ] + }, + { + "speaker" : "", + "name_font" : "A", + "name_pos" : [20, 480], + "line_font" : "A", + "voice" : null, + "portrait" : null, + "line" : "", + "characters" : [ ], + "effects" : [ + { "call" : "ef_game_switch_mode", "data" : ["Battle_Mode", "testmap1"] } diff --git a/src/constants.py b/src/constants.py @@ -91,7 +91,8 @@ OTHER_STATS = ["HP", "EXP", "LVL", "RNK"] STATE_MODES = enum.Enum('STATE_MODES', 'Main_Menu_Mode Base_Mode Battle_Mode Still_Scene_Mode') CTRL_MODES = enum.Enum('CTRL_MODES', 'No_Control Main_Menu_Normal Base_Normal Turn_Normal Turn_Select_Move Turn_Select_Attack Turn_Watch_Move Turn_Watch_Attack Turn_Display_Stats Turn_Watch_Guard Battle_Dialog Battle_Intro Still_Scene_Normal') FACE_DIR = enum.Enum('FACE_DIR', 'U D L R') -GAME_EFFECTS = enum.Enum('GAME_EFFECTS', 'ef_game_quit ef_game_switch_mode ef_game_switch_control') +GAME_EFFECTS = enum.Enum('GAME_EFFECTS', 'ef_game_dummy ef_game_quit ef_game_switch_mode ef_game_switch_control') +SCENE_EFFECTS = enum.Enum('SCENE_EFFECTS', 'ef_scene_dummy ef_scene_fade') TEAMS = enum.Enum('TEAMS', 'Player Ally Neutral Enemy Other') ATTACK_NOTATIONS = enum.Enum('ATTACK_NOTATIONS', 'backattack critical counter opposite weakness resist riposte ignoredef parry block sweep miss onetwo stun') diff --git a/src/manager.py b/src/manager.py @@ -90,7 +90,7 @@ class Manager(subsystem.GameSubsystem): Triggers game effects as defined in JSONs. This method can be extended in child objects that need to be able to trigger unique - effects. + effects by using the effect_extension method. """ # effect_list is ALWAYS a LIST of DICTS if self.activated and self.effectual: @@ -103,6 +103,19 @@ class Manager(subsystem.GameSubsystem): self.game.switch_mode(STATE_MODES[ef["data"][0]], ef["data"][1]) elif ef["call"] == GAME_EFFECTS.ef_game_switch_control.name: self.game.control_mode = CTRL_MODES[ef["data"]] + else: + self.effect_extension(ef) + + def effect_extension(self, effect): + """ + Target for extension of trigger_effects method. + This method should have a single branching + conditional statement inside it that is unique + to the manager that needs extra effects. It is + used to check only one effect at a time and should + not contain a loop like trigger_effects. + """ + pass def update(self, surface): """ diff --git a/src/scene.py b/src/scene.py @@ -38,6 +38,27 @@ class SceneManager(manager.Manager): Create a still scene from file. """ self.current_scene = StillScene(self, scenefile) + self.current_scene.cycle_script_segment() + + def effect_extension(self, effect): + """ + SceneManager-only effects for trigger_effects. + """ + if effect["call"] == SCENE_EFFECTS.ef_scene_fade.name: + posmap = { "SW" : SCREEN_WIDTH, "SH" : SCREEN_HEIGHT, "-SW" : - SCREEN_WIDTH, "-SH" : - SCREEN_HEIGHT } + ind = 0 + for d in effect["data"]: + if d != None and type(d) not in (list, bool, dict) and d in posmap.keys(): + effect["data"][ind] = posmap[d] + ind += 1 + fade_surface = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT)) + fade_surface_rect = fade_surface.get_rect() + fade_surface.fill(tuple(effect["data"][0])) + fade_surface_rect.topleft = (effect["data"][1], effect["data"][2]) + xmov = effect["data"][3] + ymov = effect["data"][4] + timer = effect["data"][5] + self.current_scene.setup_fade_effect(fade_surface, fade_surface_rect, xmov, ymov, timer) def expose(self): """ @@ -113,6 +134,12 @@ class StillScene(object): self.current_portrait_rect = None self.voice_delay = 0 self.script_index = -1 + self.fading = False + self.fade_surface = None + self.fade_surface_rect = None + self.fade_x_pos_change = 0 + self.fade_y_pos_change = 0 + self.fade_timer = 0 # Load the scene self.load_scene(scenefile) @@ -142,9 +169,6 @@ class StillScene(object): for f in scenedef["fonts"]: self.fonts[f] = pygame.font.Font(os.path.join(FONT_PATH, scenedef["fonts"][f][0]), scenedef["fonts"][f][1]) - # Cycle in for the first time - self.cycle_script_segment() - def cycle_script_segment(self): """ Cycle up to the next script segment. @@ -277,6 +301,29 @@ class StillScene(object): if self.continue_ready and self.script_index < len(self.script) - 1: self.cycle_script_segment() + def setup_fade_effect(self, fade_surface, fade_surface_rect, xmov, ymov, timer): + """ + Setup a fade effect to play. + """ + self.fading = True + self.fade_surface = fade_surface + self.fade_surface_rect = fade_surface_rect + self.fade_x_pos_change = xmov + self.fade_y_pos_change = ymov + self.fade_timer = timer + + def play_fade_effect(self): + """ + Play a previously setup fade effect. + """ + if self.fade_timer > 0: + self.fade_surface_rect.topleft = (self.fade_surface_rect.topleft[0] + self.fade_x_pos_change, self.fade_surface_rect.topleft[1] + self.fade_y_pos_change) + self.fade_timer -= 1 + else: + self.fading = False + self.continue_ready = True + self.continue_script() + def update(self, surface = None): """ Update the StillScene and draw visible elements. @@ -291,25 +338,32 @@ class StillScene(object): for e in c: e.update(surface) - self.text_box.update(surface) - self.name_box.update(surface) + # Handle fading + if self.fading: + self.play_fade_effect() + surface.blit(self.fade_surface, self.fade_surface_rect) + + # If not fading, do regular stuff + else: + self.text_box.update(surface) + self.name_box.update(surface) - # Write the name in the namebox - surface.blit(self.rendered_name, self.rendered_name_topleft) + # Write the name in the namebox + surface.blit(self.rendered_name, self.rendered_name_topleft) - if self.continue_ready: - self.continue_prompt.update(surface) + if self.continue_ready: + self.continue_prompt.update(surface) - if self.current_portrait != None: - xoff = self.current_portrait_rect.width + 4 - surface.blit(self.current_portrait, self.current_portrait_rect) + if self.current_portrait != None: + xoff = self.current_portrait_rect.width + 4 + surface.blit(self.current_portrait, self.current_portrait_rect) - self.write_text() - l = 0 - for t in self.rendered_text_surfaces: - if t != None: - surface.blit(t, (self.text_area_topleft[0] + xoff, self.text_area_topleft[1] + (self.current_font_height * l) + 2)) - l += 1 - - if self.current_voice != None and not self.continue_ready: - self.play_voice() + self.write_text() + l = 0 + for t in self.rendered_text_surfaces: + if t != None: + surface.blit(t, (self.text_area_topleft[0] + xoff, self.text_area_topleft[1] + (self.current_font_height * l) + 2)) + l += 1 + + if self.current_voice != None and not self.continue_ready: + self.play_voice()