From dab5590077fc7ecb73cc4a02871861bea836fbc8 Mon Sep 17 00:00:00 2001 From: John McCardle Date: Sat, 25 Oct 2025 22:41:11 +0000 Subject: [PATCH] Add "Rendering-and-Visuals" --- Rendering-and-Visuals.-.md | 386 +++++++++++++++++++++++++++++++++++++ 1 file changed, 386 insertions(+) create mode 100644 Rendering-and-Visuals.-.md diff --git a/Rendering-and-Visuals.-.md b/Rendering-and-Visuals.-.md new file mode 100644 index 0000000..55b0a34 --- /dev/null +++ b/Rendering-and-Visuals.-.md @@ -0,0 +1,386 @@ +# Rendering and Visuals + +How to create and display visual elements in McRogueFace. + +## Quick Reference + +**Systems:** [[UI-Component-Hierarchy]], [[Grid-System]], [[Animation-System]] + +**Key Types:** +- `Frame` - Rectangles and containers +- `Caption` - Text rendering +- `Sprite` - Images and sprite sheets +- `Grid` - Tilemaps +- `Entity` - Grid-based sprites + +--- + +## Basic Rendering + +### Creating UI Elements + +```python +import mcrfpy + +# Create scene +mcrfpy.createScene("game") + +# Rectangle/Frame +frame = mcrfpy.Frame(100, 100, 200, 150) +frame.fill_color = mcrfpy.Color(50, 50, 50) +frame.outline_color = mcrfpy.Color(255, 255, 255) +frame.outline_thickness = 2 + +# Text +label = mcrfpy.Caption((10, 10), "Hello World!") +label.font_size = 24 +label.fill_color = mcrfpy.Color(255, 255, 255) + +# Sprite +sprite = mcrfpy.Sprite("player.png", 50, 50) +sprite.scale_x = 2.0 +sprite.scale_y = 2.0 + +# Add to scene +scene_ui = mcrfpy.sceneUI("game") +scene_ui.append(frame) +scene_ui.append(label) +scene_ui.append(sprite) +``` + +--- + +## Textures and Sprite Sheets + +### Loading Textures + +```python +# Load single image +texture = mcrfpy.createTexture("sprites/player.png") + +# Use with sprite +sprite = mcrfpy.Sprite("dummy.png", 0, 0) # Path doesn't matter +sprite.texture = texture +``` + +### Sprite Sheets + +```python +# Load sprite sheet (multiple sprites in one image) +sheet = mcrfpy.createTexture("spritesh eet.png") + +# Use specific sprite from sheet +sprite = mcrfpy.Sprite("dummy.png", 100, 100) +sprite.texture = sheet +sprite.sprite_index = 5 # Use 6th sprite (0-indexed) + +# Grid with tileset +grid = mcrfpy.Grid(50, 50, 16, 16) # Each tile is 16x16 +grid.texture = mcrfpy.createTexture("tileset.png") + +# Set tiles +for x in range(50): + for y in range(50): + grid.at((x, y)).tilesprite = 0 # Floor tile +``` + +--- + +## Z-Order Layering + +Control render order with `z_index` (higher = front): + +```python +# Background layer (z=0) +background = mcrfpy.Sprite("bg.png", 0, 0) +background.z_index = 0 + +# Game layer (z=10) +grid = mcrfpy.Grid(50, 50, 16, 16) +grid.z_index = 10 + +# UI layer (z=100) +hud = mcrfpy.Frame(0, 0, 800, 50) +hud.z_index = 100 + +# Add to scene (order doesn't matter, z_index controls rendering) +ui = mcrfpy.sceneUI("game") +ui.append(hud) +ui.append(background) +ui.append(grid) + +# Renders: background → grid → hud +``` + +**Implementation:** Automatic sorting by z_index in `src/Scene.cpp::render()` + +--- + +## Colors + +### Color Creation + +```python +# RGB +red = mcrfpy.Color(255, 0, 0) + +# RGBA (with alpha/transparency) +semi_transparent = mcrfpy.Color(255, 255, 255, 128) + +# Access components +color = mcrfpy.Color(100, 150, 200, 255) +print(f"R: {color.r}, G: {color.g}, B: {color.b}, A: {color.a}") +``` + +### Color Application + +```python +# Frame colors +frame.fill_color = mcrfpy.Color(50, 50, 50) +frame.outline_color = mcrfpy.Color(255, 255, 255) + +# Text color +caption.fill_color = mcrfpy.Color(255, 255, 0) # Yellow text + +# Grid point colors +grid.at((x, y)).color = mcrfpy.Color(255, 0, 0) # Red tint + +# Opacity +sprite.opacity = 0.5 # 50% transparent +``` + +--- + +## Visual Effects + +### Animations + +See [[Animation-System]] for complete animation documentation. + +```python +# Fade in +mcrfpy.animate(sprite, "opacity", 1.0, 1000, "ease_in_quad") + +# Color transition +mcrfpy.animate(frame, "fill_color", mcrfpy.Color(255, 0, 0), 500, "linear") + +# Movement +mcrfpy.animate(entity, "x", target_x, 300, "ease_out_cubic") +mcrfpy.animate(entity, "y", target_y, 300, "ease_out_cubic") + +# Scaling +mcrfpy.animate(sprite, "scale_x", 2.0, 200, "bounce_out") +``` + +### Visibility + +```python +# Show/hide elements +sprite.visible = False # Hidden +sprite.visible = True # Visible + +# Opacity +sprite.opacity = 0.0 # Invisible +sprite.opacity = 0.5 # Semi-transparent +sprite.opacity = 1.0 # Opaque +``` + +--- + +## Common Patterns + +### HUD/UI Overlay + +```python +def create_hud(): + # HUD container + hud = mcrfpy.Frame(0, 0, 800, 60) + hud.fill_color = mcrfpy.Color(30, 30, 30, 200) + hud.z_index = 100 # Front layer + + # Health text + health_label = mcrfpy.Caption((10, 10), "HP: 100/100") + health_label.font_size = 18 + health_label.fill_color = mcrfpy.Color(255, 255, 255) + + hud.children.append(health_label) + return hud, health_label + +# Update HUD +def update_hud(health_label, current_hp, max_hp): + health_label.text = f"HP: {current_hp}/{max_hp}" + + # Color code health + if current_hp < max_hp * 0.3: + health_label.fill_color = mcrfpy.Color(255, 0, 0) # Red + elif current_hp < max_hp * 0.6: + health_label.fill_color = mcrfpy.Color(255, 255, 0) # Yellow + else: + health_label.fill_color = mcrfpy.Color(0, 255, 0) # Green +``` + +### Particle-Like Effects + +```python +def create_explosion(x, y): + """Create explosion effect using animated sprites.""" + particles = [] + + for i in range(10): + particle = mcrfpy.Sprite("particle.png", x, y) + particle.z_index = 50 + + # Random direction + import random + target_x = x + random.randint(-50, 50) + target_y = y + random.randint(-50, 50) + + # Animate outward + mcrfpy.animate(particle, "x", target_x, 500, "ease_out_quad") + mcrfpy.animate(particle, "y", target_y, 500, "ease_out_quad") + mcrfpy.animate(particle, "opacity", 0.0, 500, "linear") + + particles.append(particle) + mcrfpy.sceneUI("game").append(particle) + + # Remove after animation + def cleanup(runtime_ms): + for p in particles: + mcrfpy.sceneUI("game").remove(p) + + mcrfpy.setTimer("explosion_cleanup", cleanup, 600) +``` + +### Health Bars + +```python +class HealthBar: + def __init__(self, x, y, width, height, max_hp): + self.max_hp = max_hp + self.current_hp = max_hp + + # Background (red) + self.bg = mcrfpy.Frame(x, y, width, height) + self.bg.fill_color = mcrfpy.Color(255, 0, 0) + self.bg.z_index = 90 + + # Foreground (green) + self.fg = mcrfpy.Frame(x, y, width, height) + self.fg.fill_color = mcrfpy.Color(0, 255, 0) + self.fg.z_index = 91 + + def set_hp(self, current): + self.current_hp = max(0, min(current, self.max_hp)) + + # Scale foreground to represent HP + ratio = self.current_hp / self.max_hp + target_width = int(self.bg.w * ratio) + + # Animate width change + mcrfpy.animate(self.fg, "w", target_width, 200, "ease_out_quad") + + # Color code + if ratio < 0.3: + self.fg.fill_color = mcrfpy.Color(255, 0, 0) + elif ratio < 0.6: + self.fg.fill_color = mcrfpy.Color(255, 255, 0) +``` + +--- + +## Grid Rendering + +See [[Grid-System]] for complete grid documentation. + +### Basic Grid + +```python +# Create grid +grid = mcrfpy.Grid(50, 50, 16, 16) +grid.texture = mcrfpy.createTexture("tiles.png") +grid.pos = (100, 100) + +# Set tiles +for x in range(50): + for y in range(50): + if x == 0 or x == 49 or y == 0 or y == 49: + grid.at((x, y)).tilesprite = 1 # Wall + else: + grid.at((x, y)).tilesprite = 0 # Floor +``` + +### Grid Colors + +```python +# Tint specific tiles +grid.at((10, 10)).color = mcrfpy.Color(255, 0, 0) # Red highlight + +# Background color +grid.background_color = mcrfpy.Color(8, 8, 8) # Dark background +``` + +### Grid Viewport + +```python +# Zoom +grid.zoom = 2.0 # 2x zoom + +# Pan/scroll +grid.left_edge = 10 # Start viewing from tile (10, 0) +grid.top_edge = 5 # Start viewing from tile (0, 5) + +# Animate viewport +mcrfpy.animate(grid, "zoom", 1.5, 1000, "ease_in_out_quad") +mcrfpy.animate(grid, "left_edge", 20, 1000, "ease_in_out_quad") +``` + +--- + +## Performance Tips + +### Minimize Draw Calls + +```python +# Good: Group related UI in Frames +hud_frame = mcrfpy.Frame(0, 0, 800, 600) +hud_frame.children.append(label1) +hud_frame.children.append(label2) +hud_frame.children.append(label3) + +# Avoid: Many top-level UI elements +# (Each top-level element is a separate draw call) +``` + +### Use Visibility + +```python +# Hide off-screen elements +for element in all_elements: + if not in_viewport(element): + element.visible = False +``` + +### Sprite Sheet Benefits + +```python +# Good: One texture, many sprites +texture = mcrfpy.createTexture("all_sprites.png") +for i in range(100): + sprite = mcrfpy.Sprite("dummy.png", x, y) + sprite.texture = texture # Reuse texture + sprite.sprite_index = i + +# Avoid: Loading same texture multiple times +# (Wastes memory and loading time) +``` + +--- + +## Related Documentation + +- [[UI-Component-Hierarchy]] - UI element details +- [[Grid-System]] - Grid rendering details +- [[Animation-System]] - Animating visual properties +- [[Performance-and-Profiling]] - Rendering performance + +**API Reference:** [mcrfpy UI Classes](../../docs/api_reference_dynamic.html) \ No newline at end of file