114 lines
No EOL
3.4 KiB
Python
114 lines
No EOL
3.4 KiB
Python
"""McRogueFace - Multi-Layer Tiles (basic)
|
|
|
|
Documentation: https://mcrogueface.github.io/cookbook/grid_multi_layer
|
|
Repository: https://github.com/jmccardle/McRogueFace/blob/master/docs/cookbook/grid/grid_multi_layer_basic.py
|
|
|
|
This code is extracted from the McRogueFace documentation and can be
|
|
run directly with: ./mcrogueface path/to/this/file.py
|
|
"""
|
|
|
|
class EffectLayer:
|
|
"""Manage visual effects with color overlays."""
|
|
|
|
def __init__(self, grid, z_index=2):
|
|
self.grid = grid
|
|
self.layer = grid.add_layer("color", z_index=z_index)
|
|
self.effects = {} # (x, y) -> effect_data
|
|
|
|
def add_effect(self, x, y, effect_type, duration=None, **kwargs):
|
|
"""Add a visual effect."""
|
|
self.effects[(x, y)] = {
|
|
'type': effect_type,
|
|
'duration': duration,
|
|
'time': 0,
|
|
**kwargs
|
|
}
|
|
|
|
def remove_effect(self, x, y):
|
|
"""Remove an effect."""
|
|
if (x, y) in self.effects:
|
|
del self.effects[(x, y)]
|
|
self.layer.set(x, y, mcrfpy.Color(0, 0, 0, 0))
|
|
|
|
def update(self, dt):
|
|
"""Update all effects."""
|
|
import math
|
|
|
|
to_remove = []
|
|
|
|
for (x, y), effect in self.effects.items():
|
|
effect['time'] += dt
|
|
|
|
# Check expiration
|
|
if effect['duration'] and effect['time'] >= effect['duration']:
|
|
to_remove.append((x, y))
|
|
continue
|
|
|
|
# Calculate color based on effect type
|
|
color = self._calculate_color(effect)
|
|
self.layer.set(x, y, color)
|
|
|
|
for pos in to_remove:
|
|
self.remove_effect(*pos)
|
|
|
|
def _calculate_color(self, effect):
|
|
"""Get color for an effect at current time."""
|
|
import math
|
|
|
|
t = effect['time']
|
|
effect_type = effect['type']
|
|
|
|
if effect_type == 'fire':
|
|
# Flickering orange/red
|
|
flicker = 0.7 + 0.3 * math.sin(t * 10)
|
|
return mcrfpy.Color(
|
|
255,
|
|
int(100 + 50 * math.sin(t * 8)),
|
|
0,
|
|
int(180 * flicker)
|
|
)
|
|
|
|
elif effect_type == 'poison':
|
|
# Pulsing green
|
|
pulse = 0.5 + 0.5 * math.sin(t * 3)
|
|
return mcrfpy.Color(0, 200, 0, int(100 * pulse))
|
|
|
|
elif effect_type == 'ice':
|
|
# Static blue with shimmer
|
|
shimmer = 0.8 + 0.2 * math.sin(t * 5)
|
|
return mcrfpy.Color(100, 150, 255, int(120 * shimmer))
|
|
|
|
elif effect_type == 'blood':
|
|
# Fading red
|
|
duration = effect.get('duration', 5)
|
|
fade = 1 - (t / duration) if duration else 1
|
|
return mcrfpy.Color(150, 0, 0, int(150 * fade))
|
|
|
|
elif effect_type == 'highlight':
|
|
# Pulsing highlight
|
|
pulse = 0.5 + 0.5 * math.sin(t * 4)
|
|
base = effect.get('color', mcrfpy.Color(255, 255, 0, 100))
|
|
return mcrfpy.Color(base.r, base.g, base.b, int(base.a * pulse))
|
|
|
|
return mcrfpy.Color(128, 128, 128, 50)
|
|
|
|
|
|
# Usage
|
|
effects = EffectLayer(grid)
|
|
|
|
# Add fire effect (permanent)
|
|
effects.add_effect(5, 5, 'fire')
|
|
|
|
# Add blood stain (fades over 10 seconds)
|
|
effects.add_effect(10, 10, 'blood', duration=10)
|
|
|
|
# Add poison cloud
|
|
for x in range(8, 12):
|
|
for y in range(8, 12):
|
|
effects.add_effect(x, y, 'poison', duration=5)
|
|
|
|
# Update in game loop
|
|
def game_update(runtime):
|
|
effects.update(0.016) # 60 FPS
|
|
|
|
mcrfpy.setTimer("effects", game_update, 16) |