draft tutorial revisions
This commit is contained in:
parent
838da4571d
commit
48359b5a48
70 changed files with 6216 additions and 28 deletions
118
docs/cookbook/effects/effects_color_pulse_basic.py
Normal file
118
docs/cookbook/effects/effects_color_pulse_basic.py
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
"""McRogueFace - Color Pulse Effect (basic)
|
||||
|
||||
Documentation: https://mcrogueface.github.io/cookbook/effects_color_pulse
|
||||
Repository: https://github.com/jmccardle/McRogueFace/blob/master/docs/cookbook/effects/effects_color_pulse_basic.py
|
||||
|
||||
This code is extracted from the McRogueFace documentation and can be
|
||||
run directly with: ./mcrogueface path/to/this/file.py
|
||||
"""
|
||||
|
||||
import mcrfpy
|
||||
|
||||
class PulsingCell:
|
||||
"""A cell that continuously pulses until stopped."""
|
||||
|
||||
def __init__(self, grid, x, y, color, period=1.0, max_alpha=180):
|
||||
"""
|
||||
Args:
|
||||
grid: Grid with color layer
|
||||
x, y: Cell position
|
||||
color: RGB tuple
|
||||
period: Time for one complete pulse cycle
|
||||
max_alpha: Maximum alpha value (0-255)
|
||||
"""
|
||||
self.grid = grid
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.color = color
|
||||
self.period = period
|
||||
self.max_alpha = max_alpha
|
||||
self.is_pulsing = False
|
||||
self.pulse_id = 0
|
||||
self.cell = None
|
||||
|
||||
self._setup_layer()
|
||||
|
||||
def _setup_layer(self):
|
||||
"""Ensure color layer exists and get cell reference."""
|
||||
color_layer = None
|
||||
for layer in self.grid.layers:
|
||||
if isinstance(layer, mcrfpy.ColorLayer):
|
||||
color_layer = layer
|
||||
break
|
||||
|
||||
if not color_layer:
|
||||
self.grid.add_layer("color")
|
||||
color_layer = self.grid.layers[-1]
|
||||
|
||||
self.cell = color_layer.at(self.x, self.y)
|
||||
if self.cell:
|
||||
self.cell.color = mcrfpy.Color(self.color[0], self.color[1],
|
||||
self.color[2], 0)
|
||||
|
||||
def start(self):
|
||||
"""Start continuous pulsing."""
|
||||
if self.is_pulsing or not self.cell:
|
||||
return
|
||||
|
||||
self.is_pulsing = True
|
||||
self.pulse_id += 1
|
||||
self._pulse_up()
|
||||
|
||||
def _pulse_up(self):
|
||||
"""Animate alpha increasing."""
|
||||
if not self.is_pulsing:
|
||||
return
|
||||
|
||||
current_id = self.pulse_id
|
||||
half_period = self.period / 2
|
||||
|
||||
anim = mcrfpy.Animation("a", float(self.max_alpha), half_period, "easeInOut")
|
||||
anim.start(self.cell.color)
|
||||
|
||||
def next_phase(timer_name):
|
||||
if self.is_pulsing and self.pulse_id == current_id:
|
||||
self._pulse_down()
|
||||
|
||||
mcrfpy.Timer(f"pulse_up_{id(self)}_{current_id}",
|
||||
next_phase, int(half_period * 1000), once=True)
|
||||
|
||||
def _pulse_down(self):
|
||||
"""Animate alpha decreasing."""
|
||||
if not self.is_pulsing:
|
||||
return
|
||||
|
||||
current_id = self.pulse_id
|
||||
half_period = self.period / 2
|
||||
|
||||
anim = mcrfpy.Animation("a", 0.0, half_period, "easeInOut")
|
||||
anim.start(self.cell.color)
|
||||
|
||||
def next_phase(timer_name):
|
||||
if self.is_pulsing and self.pulse_id == current_id:
|
||||
self._pulse_up()
|
||||
|
||||
mcrfpy.Timer(f"pulse_down_{id(self)}_{current_id}",
|
||||
next_phase, int(half_period * 1000), once=True)
|
||||
|
||||
def stop(self):
|
||||
"""Stop pulsing and fade out."""
|
||||
self.is_pulsing = False
|
||||
if self.cell:
|
||||
anim = mcrfpy.Animation("a", 0.0, 0.2, "easeOut")
|
||||
anim.start(self.cell.color)
|
||||
|
||||
def set_color(self, color):
|
||||
"""Change pulse color."""
|
||||
self.color = color
|
||||
if self.cell:
|
||||
current_alpha = self.cell.color.a
|
||||
self.cell.color = mcrfpy.Color(color[0], color[1], color[2], current_alpha)
|
||||
|
||||
|
||||
# Usage
|
||||
objective_pulse = PulsingCell(grid, 10, 10, (0, 255, 100), period=1.5)
|
||||
objective_pulse.start()
|
||||
|
||||
# Later, when objective is reached:
|
||||
objective_pulse.stop()
|
||||
61
docs/cookbook/effects/effects_color_pulse_multi.py
Normal file
61
docs/cookbook/effects/effects_color_pulse_multi.py
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
"""McRogueFace - Color Pulse Effect (multi)
|
||||
|
||||
Documentation: https://mcrogueface.github.io/cookbook/effects_color_pulse
|
||||
Repository: https://github.com/jmccardle/McRogueFace/blob/master/docs/cookbook/effects/effects_color_pulse_multi.py
|
||||
|
||||
This code is extracted from the McRogueFace documentation and can be
|
||||
run directly with: ./mcrogueface path/to/this/file.py
|
||||
"""
|
||||
|
||||
import mcrfpy
|
||||
|
||||
def ripple_effect(grid, center_x, center_y, color, max_radius=5, duration=1.0):
|
||||
"""
|
||||
Create an expanding ripple effect.
|
||||
|
||||
Args:
|
||||
grid: Grid with color layer
|
||||
center_x, center_y: Ripple origin
|
||||
color: RGB tuple
|
||||
max_radius: Maximum ripple size
|
||||
duration: Total animation time
|
||||
"""
|
||||
# Get color layer
|
||||
color_layer = None
|
||||
for layer in grid.layers:
|
||||
if isinstance(layer, mcrfpy.ColorLayer):
|
||||
color_layer = layer
|
||||
break
|
||||
|
||||
if not color_layer:
|
||||
grid.add_layer("color")
|
||||
color_layer = grid.layers[-1]
|
||||
|
||||
step_duration = duration / max_radius
|
||||
|
||||
for radius in range(max_radius + 1):
|
||||
# Get cells at this radius (ring, not filled)
|
||||
ring_cells = []
|
||||
for dy in range(-radius, radius + 1):
|
||||
for dx in range(-radius, radius + 1):
|
||||
dist_sq = dx * dx + dy * dy
|
||||
# Include cells approximately on the ring edge
|
||||
if radius * radius - radius <= dist_sq <= radius * radius + radius:
|
||||
cell = color_layer.at(center_x + dx, center_y + dy)
|
||||
if cell:
|
||||
ring_cells.append(cell)
|
||||
|
||||
# Schedule this ring to animate
|
||||
def animate_ring(timer_name, cells=ring_cells, c=color):
|
||||
for cell in cells:
|
||||
cell.color = mcrfpy.Color(c[0], c[1], c[2], 200)
|
||||
# Fade out
|
||||
anim = mcrfpy.Animation("a", 0.0, step_duration * 2, "easeOut")
|
||||
anim.start(cell.color)
|
||||
|
||||
delay = int(radius * step_duration * 1000)
|
||||
mcrfpy.Timer(f"ripple_{radius}", animate_ring, delay, once=True)
|
||||
|
||||
|
||||
# Usage
|
||||
ripple_effect(grid, 10, 10, (100, 200, 255), max_radius=6, duration=0.8)
|
||||
41
docs/cookbook/effects/effects_damage_flash_basic.py
Normal file
41
docs/cookbook/effects/effects_damage_flash_basic.py
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
"""McRogueFace - Damage Flash Effect (basic)
|
||||
|
||||
Documentation: https://mcrogueface.github.io/cookbook/effects_damage_flash
|
||||
Repository: https://github.com/jmccardle/McRogueFace/blob/master/docs/cookbook/effects/effects_damage_flash_basic.py
|
||||
|
||||
This code is extracted from the McRogueFace documentation and can be
|
||||
run directly with: ./mcrogueface path/to/this/file.py
|
||||
"""
|
||||
|
||||
import mcrfpy
|
||||
|
||||
# Add a color layer to your grid (do this once during setup)
|
||||
grid.add_layer("color")
|
||||
color_layer = grid.layers[-1] # Get the color layer
|
||||
|
||||
def flash_cell(grid, x, y, color, duration=0.3):
|
||||
"""Flash a grid cell with a color overlay."""
|
||||
# Get the color layer (assumes it's the last layer added)
|
||||
color_layer = None
|
||||
for layer in grid.layers:
|
||||
if isinstance(layer, mcrfpy.ColorLayer):
|
||||
color_layer = layer
|
||||
break
|
||||
|
||||
if not color_layer:
|
||||
return
|
||||
|
||||
# Set cell to flash color
|
||||
cell = color_layer.at(x, y)
|
||||
cell.color = mcrfpy.Color(color[0], color[1], color[2], 200)
|
||||
|
||||
# Animate alpha back to 0
|
||||
anim = mcrfpy.Animation("a", 0.0, duration, "easeOut")
|
||||
anim.start(cell.color)
|
||||
|
||||
def damage_at_position(grid, x, y, duration=0.3):
|
||||
"""Flash red at a grid position when damage occurs."""
|
||||
flash_cell(grid, x, y, (255, 0, 0), duration)
|
||||
|
||||
# Usage when entity takes damage
|
||||
damage_at_position(grid, int(enemy.x), int(enemy.y))
|
||||
85
docs/cookbook/effects/effects_damage_flash_complete.py
Normal file
85
docs/cookbook/effects/effects_damage_flash_complete.py
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
"""McRogueFace - Damage Flash Effect (complete)
|
||||
|
||||
Documentation: https://mcrogueface.github.io/cookbook/effects_damage_flash
|
||||
Repository: https://github.com/jmccardle/McRogueFace/blob/master/docs/cookbook/effects/effects_damage_flash_complete.py
|
||||
|
||||
This code is extracted from the McRogueFace documentation and can be
|
||||
run directly with: ./mcrogueface path/to/this/file.py
|
||||
"""
|
||||
|
||||
import mcrfpy
|
||||
|
||||
class DamageEffects:
|
||||
"""Manages visual damage feedback effects."""
|
||||
|
||||
# Color presets
|
||||
DAMAGE_RED = (255, 50, 50)
|
||||
HEAL_GREEN = (50, 255, 50)
|
||||
POISON_PURPLE = (150, 50, 200)
|
||||
FIRE_ORANGE = (255, 150, 50)
|
||||
ICE_BLUE = (100, 200, 255)
|
||||
|
||||
def __init__(self, grid):
|
||||
self.grid = grid
|
||||
self.color_layer = None
|
||||
self._setup_color_layer()
|
||||
|
||||
def _setup_color_layer(self):
|
||||
"""Ensure grid has a color layer for effects."""
|
||||
self.grid.add_layer("color")
|
||||
self.color_layer = self.grid.layers[-1]
|
||||
|
||||
def flash_entity(self, entity, color, duration=0.3):
|
||||
"""Flash an entity with a color tint."""
|
||||
# Flash at entity's grid position
|
||||
x, y = int(entity.x), int(entity.y)
|
||||
self.flash_cell(x, y, color, duration)
|
||||
|
||||
def flash_cell(self, x, y, color, duration=0.3):
|
||||
"""Flash a specific grid cell."""
|
||||
if not self.color_layer:
|
||||
return
|
||||
|
||||
cell = self.color_layer.at(x, y)
|
||||
if cell:
|
||||
cell.color = mcrfpy.Color(color[0], color[1], color[2], 180)
|
||||
|
||||
# Fade out
|
||||
anim = mcrfpy.Animation("a", 0.0, duration, "easeOut")
|
||||
anim.start(cell.color)
|
||||
|
||||
def damage(self, entity, amount, duration=0.3):
|
||||
"""Standard damage flash."""
|
||||
self.flash_entity(entity, self.DAMAGE_RED, duration)
|
||||
|
||||
def heal(self, entity, amount, duration=0.4):
|
||||
"""Healing effect - green flash."""
|
||||
self.flash_entity(entity, self.HEAL_GREEN, duration)
|
||||
|
||||
def poison(self, entity, duration=0.5):
|
||||
"""Poison damage - purple flash."""
|
||||
self.flash_entity(entity, self.POISON_PURPLE, duration)
|
||||
|
||||
def fire(self, entity, duration=0.3):
|
||||
"""Fire damage - orange flash."""
|
||||
self.flash_entity(entity, self.FIRE_ORANGE, duration)
|
||||
|
||||
def ice(self, entity, duration=0.4):
|
||||
"""Ice damage - blue flash."""
|
||||
self.flash_entity(entity, self.ICE_BLUE, duration)
|
||||
|
||||
def area_damage(self, center_x, center_y, radius, color, duration=0.4):
|
||||
"""Flash all cells in a radius."""
|
||||
for dy in range(-radius, radius + 1):
|
||||
for dx in range(-radius, radius + 1):
|
||||
if dx * dx + dy * dy <= radius * radius:
|
||||
self.flash_cell(center_x + dx, center_y + dy, color, duration)
|
||||
|
||||
# Setup
|
||||
effects = DamageEffects(grid)
|
||||
|
||||
# Usage examples
|
||||
effects.damage(player, 10) # Red flash
|
||||
effects.heal(player, 5) # Green flash
|
||||
effects.poison(enemy) # Purple flash
|
||||
effects.area_damage(5, 5, 3, effects.FIRE_ORANGE) # Area effect
|
||||
25
docs/cookbook/effects/effects_damage_flash_multi.py
Normal file
25
docs/cookbook/effects/effects_damage_flash_multi.py
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
"""McRogueFace - Damage Flash Effect (multi)
|
||||
|
||||
Documentation: https://mcrogueface.github.io/cookbook/effects_damage_flash
|
||||
Repository: https://github.com/jmccardle/McRogueFace/blob/master/docs/cookbook/effects/effects_damage_flash_multi.py
|
||||
|
||||
This code is extracted from the McRogueFace documentation and can be
|
||||
run directly with: ./mcrogueface path/to/this/file.py
|
||||
"""
|
||||
|
||||
import mcrfpy
|
||||
|
||||
def multi_flash(grid, x, y, color, flashes=3, flash_duration=0.1):
|
||||
"""Flash a cell multiple times for emphasis."""
|
||||
delay = 0
|
||||
|
||||
for i in range(flashes):
|
||||
# Schedule each flash with increasing delay
|
||||
def do_flash(timer_name, fx=x, fy=y, fc=color, fd=flash_duration):
|
||||
flash_cell(grid, fx, fy, fc, fd)
|
||||
|
||||
mcrfpy.Timer(f"flash_{x}_{y}_{i}", do_flash, int(delay * 1000), once=True)
|
||||
delay += flash_duration * 1.5 # Gap between flashes
|
||||
|
||||
# Usage for critical hit
|
||||
multi_flash(grid, int(enemy.x), int(enemy.y), (255, 255, 0), flashes=3)
|
||||
42
docs/cookbook/effects/effects_floating_text.py
Normal file
42
docs/cookbook/effects/effects_floating_text.py
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
"""McRogueFace - Floating Damage Numbers (effects_floating_text)
|
||||
|
||||
Documentation: https://mcrogueface.github.io/cookbook/effects_floating_text
|
||||
Repository: https://github.com/jmccardle/McRogueFace/blob/master/docs/cookbook/effects/effects_floating_text.py
|
||||
|
||||
This code is extracted from the McRogueFace documentation and can be
|
||||
run directly with: ./mcrogueface path/to/this/file.py
|
||||
"""
|
||||
|
||||
class StackedFloatingText:
|
||||
"""Prevents overlapping text by stacking vertically."""
|
||||
|
||||
def __init__(self, scene_name, grid=None):
|
||||
self.manager = FloatingTextManager(scene_name, grid)
|
||||
self.position_stack = {} # Track recent spawns per position
|
||||
|
||||
def spawn_stacked(self, x, y, text, color, **kwargs):
|
||||
"""Spawn with automatic vertical stacking."""
|
||||
key = (int(x), int(y))
|
||||
|
||||
# Calculate offset based on recent spawns at this position
|
||||
offset = self.position_stack.get(key, 0)
|
||||
actual_y = y - (offset * 20) # 20 pixels between stacked texts
|
||||
|
||||
self.manager.spawn(x, actual_y, text, color, **kwargs)
|
||||
|
||||
# Increment stack counter
|
||||
self.position_stack[key] = offset + 1
|
||||
|
||||
# Reset stack after delay
|
||||
def reset_stack(timer_name, k=key):
|
||||
if k in self.position_stack:
|
||||
self.position_stack[k] = max(0, self.position_stack[k] - 1)
|
||||
|
||||
mcrfpy.Timer(f"stack_reset_{x}_{y}_{offset}", reset_stack, 300, once=True)
|
||||
|
||||
# Usage
|
||||
stacked = StackedFloatingText("game", grid)
|
||||
# Rapid hits will stack vertically instead of overlapping
|
||||
stacked.spawn_stacked(5, 5, "-10", (255, 0, 0), is_grid_pos=True)
|
||||
stacked.spawn_stacked(5, 5, "-8", (255, 0, 0), is_grid_pos=True)
|
||||
stacked.spawn_stacked(5, 5, "-12", (255, 0, 0), is_grid_pos=True)
|
||||
65
docs/cookbook/effects/effects_path_animation.py
Normal file
65
docs/cookbook/effects/effects_path_animation.py
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
"""McRogueFace - Path Animation (Multi-Step Movement) (effects_path_animation)
|
||||
|
||||
Documentation: https://mcrogueface.github.io/cookbook/effects_path_animation
|
||||
Repository: https://github.com/jmccardle/McRogueFace/blob/master/docs/cookbook/effects/effects_path_animation.py
|
||||
|
||||
This code is extracted from the McRogueFace documentation and can be
|
||||
run directly with: ./mcrogueface path/to/this/file.py
|
||||
"""
|
||||
|
||||
import mcrfpy
|
||||
|
||||
class CameraFollowingPath:
|
||||
"""Path animator that also moves the camera."""
|
||||
|
||||
def __init__(self, entity, grid, path, step_duration=0.2):
|
||||
self.entity = entity
|
||||
self.grid = grid
|
||||
self.path = path
|
||||
self.step_duration = step_duration
|
||||
self.index = 0
|
||||
self.on_complete = None
|
||||
|
||||
def start(self):
|
||||
self.index = 0
|
||||
self._next()
|
||||
|
||||
def _next(self):
|
||||
if self.index >= len(self.path):
|
||||
if self.on_complete:
|
||||
self.on_complete(self)
|
||||
return
|
||||
|
||||
x, y = self.path[self.index]
|
||||
|
||||
def done(anim, target):
|
||||
self.index += 1
|
||||
self._next()
|
||||
|
||||
# Animate entity
|
||||
if self.entity.x != x:
|
||||
anim = mcrfpy.Animation("x", float(x), self.step_duration,
|
||||
"easeInOut", callback=done)
|
||||
anim.start(self.entity)
|
||||
elif self.entity.y != y:
|
||||
anim = mcrfpy.Animation("y", float(y), self.step_duration,
|
||||
"easeInOut", callback=done)
|
||||
anim.start(self.entity)
|
||||
else:
|
||||
done(None, None)
|
||||
return
|
||||
|
||||
# Animate camera to follow
|
||||
cam_x = mcrfpy.Animation("center_x", (x + 0.5) * 16,
|
||||
self.step_duration, "easeInOut")
|
||||
cam_y = mcrfpy.Animation("center_y", (y + 0.5) * 16,
|
||||
self.step_duration, "easeInOut")
|
||||
cam_x.start(self.grid)
|
||||
cam_y.start(self.grid)
|
||||
|
||||
|
||||
# Usage
|
||||
path = [(5, 5), (5, 10), (10, 10)]
|
||||
mover = CameraFollowingPath(player, grid, path)
|
||||
mover.on_complete = lambda m: print("Journey complete!")
|
||||
mover.start()
|
||||
166
docs/cookbook/effects/effects_scene_transitions.py
Normal file
166
docs/cookbook/effects/effects_scene_transitions.py
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
"""McRogueFace - Scene Transition Effects (effects_scene_transitions)
|
||||
|
||||
Documentation: https://mcrogueface.github.io/cookbook/effects_scene_transitions
|
||||
Repository: https://github.com/jmccardle/McRogueFace/blob/master/docs/cookbook/effects/effects_scene_transitions.py
|
||||
|
||||
This code is extracted from the McRogueFace documentation and can be
|
||||
run directly with: ./mcrogueface path/to/this/file.py
|
||||
"""
|
||||
|
||||
import mcrfpy
|
||||
|
||||
class TransitionManager:
|
||||
"""Manages scene transitions with multiple effect types."""
|
||||
|
||||
def __init__(self, screen_width=1024, screen_height=768):
|
||||
self.width = screen_width
|
||||
self.height = screen_height
|
||||
self.is_transitioning = False
|
||||
|
||||
def go_to(self, scene_name, effect="fade", duration=0.5, **kwargs):
|
||||
"""
|
||||
Transition to a scene with the specified effect.
|
||||
|
||||
Args:
|
||||
scene_name: Target scene
|
||||
effect: "fade", "flash", "wipe", "instant"
|
||||
duration: Transition duration
|
||||
**kwargs: Effect-specific options (color, direction)
|
||||
"""
|
||||
if self.is_transitioning:
|
||||
return
|
||||
|
||||
self.is_transitioning = True
|
||||
|
||||
if effect == "instant":
|
||||
mcrfpy.setScene(scene_name)
|
||||
self.is_transitioning = False
|
||||
|
||||
elif effect == "fade":
|
||||
color = kwargs.get("color", (0, 0, 0))
|
||||
self._fade(scene_name, duration, color)
|
||||
|
||||
elif effect == "flash":
|
||||
color = kwargs.get("color", (255, 255, 255))
|
||||
self._flash(scene_name, duration, color)
|
||||
|
||||
elif effect == "wipe":
|
||||
direction = kwargs.get("direction", "right")
|
||||
color = kwargs.get("color", (0, 0, 0))
|
||||
self._wipe(scene_name, duration, direction, color)
|
||||
|
||||
def _fade(self, scene, duration, color):
|
||||
half = duration / 2
|
||||
ui = mcrfpy.sceneUI(mcrfpy.currentScene())
|
||||
|
||||
overlay = mcrfpy.Frame(0, 0, self.width, self.height)
|
||||
overlay.fill_color = mcrfpy.Color(color[0], color[1], color[2], 0)
|
||||
overlay.z_index = 9999
|
||||
ui.append(overlay)
|
||||
|
||||
anim = mcrfpy.Animation("opacity", 1.0, half, "easeIn")
|
||||
anim.start(overlay)
|
||||
|
||||
def phase2(timer_name):
|
||||
mcrfpy.setScene(scene)
|
||||
new_ui = mcrfpy.sceneUI(scene)
|
||||
|
||||
new_overlay = mcrfpy.Frame(0, 0, self.width, self.height)
|
||||
new_overlay.fill_color = mcrfpy.Color(color[0], color[1], color[2], 255)
|
||||
new_overlay.z_index = 9999
|
||||
new_ui.append(new_overlay)
|
||||
|
||||
anim2 = mcrfpy.Animation("opacity", 0.0, half, "easeOut")
|
||||
anim2.start(new_overlay)
|
||||
|
||||
def cleanup(timer_name):
|
||||
for i, elem in enumerate(new_ui):
|
||||
if elem is new_overlay:
|
||||
new_ui.remove(i)
|
||||
break
|
||||
self.is_transitioning = False
|
||||
|
||||
mcrfpy.Timer("fade_done", cleanup, int(half * 1000) + 50, once=True)
|
||||
|
||||
mcrfpy.Timer("fade_switch", phase2, int(half * 1000), once=True)
|
||||
|
||||
def _flash(self, scene, duration, color):
|
||||
quarter = duration / 4
|
||||
ui = mcrfpy.sceneUI(mcrfpy.currentScene())
|
||||
|
||||
overlay = mcrfpy.Frame(0, 0, self.width, self.height)
|
||||
overlay.fill_color = mcrfpy.Color(color[0], color[1], color[2], 0)
|
||||
overlay.z_index = 9999
|
||||
ui.append(overlay)
|
||||
|
||||
anim = mcrfpy.Animation("opacity", 1.0, quarter, "easeOut")
|
||||
anim.start(overlay)
|
||||
|
||||
def phase2(timer_name):
|
||||
mcrfpy.setScene(scene)
|
||||
new_ui = mcrfpy.sceneUI(scene)
|
||||
|
||||
new_overlay = mcrfpy.Frame(0, 0, self.width, self.height)
|
||||
new_overlay.fill_color = mcrfpy.Color(color[0], color[1], color[2], 255)
|
||||
new_overlay.z_index = 9999
|
||||
new_ui.append(new_overlay)
|
||||
|
||||
anim2 = mcrfpy.Animation("opacity", 0.0, duration / 2, "easeIn")
|
||||
anim2.start(new_overlay)
|
||||
|
||||
def cleanup(timer_name):
|
||||
for i, elem in enumerate(new_ui):
|
||||
if elem is new_overlay:
|
||||
new_ui.remove(i)
|
||||
break
|
||||
self.is_transitioning = False
|
||||
|
||||
mcrfpy.Timer("flash_done", cleanup, int(duration * 500) + 50, once=True)
|
||||
|
||||
mcrfpy.Timer("flash_switch", phase2, int(quarter * 2000), once=True)
|
||||
|
||||
def _wipe(self, scene, duration, direction, color):
|
||||
# Simplified wipe - right direction only for brevity
|
||||
half = duration / 2
|
||||
ui = mcrfpy.sceneUI(mcrfpy.currentScene())
|
||||
|
||||
overlay = mcrfpy.Frame(0, 0, 0, self.height)
|
||||
overlay.fill_color = mcrfpy.Color(color[0], color[1], color[2], 255)
|
||||
overlay.z_index = 9999
|
||||
ui.append(overlay)
|
||||
|
||||
anim = mcrfpy.Animation("w", float(self.width), half, "easeInOut")
|
||||
anim.start(overlay)
|
||||
|
||||
def phase2(timer_name):
|
||||
mcrfpy.setScene(scene)
|
||||
new_ui = mcrfpy.sceneUI(scene)
|
||||
|
||||
new_overlay = mcrfpy.Frame(0, 0, self.width, self.height)
|
||||
new_overlay.fill_color = mcrfpy.Color(color[0], color[1], color[2], 255)
|
||||
new_overlay.z_index = 9999
|
||||
new_ui.append(new_overlay)
|
||||
|
||||
anim2 = mcrfpy.Animation("x", float(self.width), half, "easeInOut")
|
||||
anim2.start(new_overlay)
|
||||
|
||||
def cleanup(timer_name):
|
||||
for i, elem in enumerate(new_ui):
|
||||
if elem is new_overlay:
|
||||
new_ui.remove(i)
|
||||
break
|
||||
self.is_transitioning = False
|
||||
|
||||
mcrfpy.Timer("wipe_done", cleanup, int(half * 1000) + 50, once=True)
|
||||
|
||||
mcrfpy.Timer("wipe_switch", phase2, int(half * 1000), once=True)
|
||||
|
||||
|
||||
# Usage
|
||||
transitions = TransitionManager()
|
||||
|
||||
# Various transition styles
|
||||
transitions.go_to("game", effect="fade", duration=0.5)
|
||||
transitions.go_to("menu", effect="flash", color=(255, 255, 255), duration=0.4)
|
||||
transitions.go_to("next_level", effect="wipe", direction="right", duration=0.6)
|
||||
transitions.go_to("options", effect="instant")
|
||||
38
docs/cookbook/effects/effects_screen_shake_basic.py
Normal file
38
docs/cookbook/effects/effects_screen_shake_basic.py
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
"""McRogueFace - Screen Shake Effect (basic)
|
||||
|
||||
Documentation: https://mcrogueface.github.io/cookbook/effects_screen_shake
|
||||
Repository: https://github.com/jmccardle/McRogueFace/blob/master/docs/cookbook/effects/effects_screen_shake_basic.py
|
||||
|
||||
This code is extracted from the McRogueFace documentation and can be
|
||||
run directly with: ./mcrogueface path/to/this/file.py
|
||||
"""
|
||||
|
||||
import mcrfpy
|
||||
|
||||
def screen_shake(frame, intensity=5, duration=0.2):
|
||||
"""
|
||||
Shake a frame/container by animating its position.
|
||||
|
||||
Args:
|
||||
frame: The UI Frame to shake (often a container for all game elements)
|
||||
intensity: Maximum pixel offset
|
||||
duration: Total shake duration in seconds
|
||||
"""
|
||||
original_x = frame.x
|
||||
original_y = frame.y
|
||||
|
||||
# Quick shake to offset position
|
||||
shake_x = mcrfpy.Animation("x", float(original_x + intensity), duration / 4, "easeOut")
|
||||
shake_x.start(frame)
|
||||
|
||||
# Schedule return to center
|
||||
def return_to_center(timer_name):
|
||||
anim = mcrfpy.Animation("x", float(original_x), duration / 2, "easeInOut")
|
||||
anim.start(frame)
|
||||
|
||||
mcrfpy.Timer("shake_return", return_to_center, int(duration * 250), once=True)
|
||||
|
||||
# Usage - wrap your game content in a Frame
|
||||
game_container = mcrfpy.Frame(0, 0, 1024, 768)
|
||||
# ... add game elements to game_container.children ...
|
||||
screen_shake(game_container, intensity=8, duration=0.3)
|
||||
58
docs/cookbook/effects/effects_screen_shake_multi.py
Normal file
58
docs/cookbook/effects/effects_screen_shake_multi.py
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
"""McRogueFace - Screen Shake Effect (multi)
|
||||
|
||||
Documentation: https://mcrogueface.github.io/cookbook/effects_screen_shake
|
||||
Repository: https://github.com/jmccardle/McRogueFace/blob/master/docs/cookbook/effects/effects_screen_shake_multi.py
|
||||
|
||||
This code is extracted from the McRogueFace documentation and can be
|
||||
run directly with: ./mcrogueface path/to/this/file.py
|
||||
"""
|
||||
|
||||
import mcrfpy
|
||||
import math
|
||||
|
||||
def directional_shake(shaker, direction_x, direction_y, intensity=10, duration=0.2):
|
||||
"""
|
||||
Shake in a specific direction (e.g., direction of impact).
|
||||
|
||||
Args:
|
||||
shaker: ScreenShakeManager instance
|
||||
direction_x, direction_y: Direction vector (will be normalized)
|
||||
intensity: Shake strength
|
||||
duration: Shake duration
|
||||
"""
|
||||
# Normalize direction
|
||||
length = math.sqrt(direction_x * direction_x + direction_y * direction_y)
|
||||
if length == 0:
|
||||
return
|
||||
|
||||
dir_x = direction_x / length
|
||||
dir_y = direction_y / length
|
||||
|
||||
# Shake in the direction, then opposite, then back
|
||||
shaker._animate_position(
|
||||
shaker.original_x + dir_x * intensity,
|
||||
shaker.original_y + dir_y * intensity,
|
||||
duration / 3
|
||||
)
|
||||
|
||||
def reverse(timer_name):
|
||||
shaker._animate_position(
|
||||
shaker.original_x - dir_x * intensity * 0.5,
|
||||
shaker.original_y - dir_y * intensity * 0.5,
|
||||
duration / 3
|
||||
)
|
||||
|
||||
def reset(timer_name):
|
||||
shaker._animate_position(
|
||||
shaker.original_x,
|
||||
shaker.original_y,
|
||||
duration / 3
|
||||
)
|
||||
shaker.is_shaking = False
|
||||
|
||||
mcrfpy.Timer("dir_shake_rev", reverse, int(duration * 333), once=True)
|
||||
mcrfpy.Timer("dir_shake_reset", reset, int(duration * 666), once=True)
|
||||
|
||||
# Usage: shake away from impact direction
|
||||
hit_from_x, hit_from_y = -1, 0 # Hit from the left
|
||||
directional_shake(shaker, hit_from_x, hit_from_y, intensity=12)
|
||||
Loading…
Add table
Add a link
Reference in a new issue