McRogueFace/tests/cookbook/primitives/demo_stat_bar.py

332 lines
9.6 KiB
Python
Raw Permalink Normal View History

#!/usr/bin/env python3
"""Stat Bar Widget Demo - Progress bars for health, mana, XP, etc.
Interactive controls:
1-4: Decrease stat bars
Shift+1-4: Increase stat bars
F: Flash the health bar
R: Reset all bars
ESC: Exit demo
"""
import mcrfpy
import sys
# Add parent to path for imports
sys.path.insert(0, str(__file__).rsplit('/', 2)[0])
from lib.stat_bar import StatBar, create_stat_bar_group
class StatBarDemo:
def __init__(self):
self.scene = mcrfpy.Scene("stat_bar_demo")
self.ui = self.scene.children
self.bars = {}
self.setup()
def setup(self):
"""Build the demo scene."""
# Background
bg = mcrfpy.Frame(
pos=(0, 0),
size=(1024, 768),
fill_color=mcrfpy.Color(20, 20, 25)
)
self.ui.append(bg)
# Title
title = mcrfpy.Caption(
text="Stat Bar Widget Demo",
pos=(512, 30),
font_size=28,
fill_color=mcrfpy.Color(255, 255, 255)
)
title.outline = 2
title.outline_color = mcrfpy.Color(0, 0, 0)
self.ui.append(title)
# Section 1: Basic stat bars with labels
section1_label = mcrfpy.Caption(
text="Character Stats (press 1-4 to decrease, Shift+1-4 to increase)",
pos=(50, 90),
font_size=16,
fill_color=mcrfpy.Color(150, 150, 150)
)
self.ui.append(section1_label)
# Health bar
self.bars['hp'] = StatBar(
pos=(50, 120),
size=(250, 25),
current=75,
maximum=100,
fill_color=StatBar.HEALTH_COLOR,
label="HP"
)
self.ui.append(self.bars['hp'].frame)
# Mana bar
self.bars['mp'] = StatBar(
pos=(50, 155),
size=(250, 25),
current=50,
maximum=80,
fill_color=StatBar.MANA_COLOR,
label="MP"
)
self.ui.append(self.bars['mp'].frame)
# Stamina bar
self.bars['stamina'] = StatBar(
pos=(50, 190),
size=(250, 25),
current=90,
maximum=100,
fill_color=StatBar.STAMINA_COLOR,
label="Stamina"
)
self.ui.append(self.bars['stamina'].frame)
# XP bar
self.bars['xp'] = StatBar(
pos=(50, 225),
size=(250, 25),
current=250,
maximum=1000,
fill_color=StatBar.XP_COLOR,
label="XP"
)
self.ui.append(self.bars['xp'].frame)
# Section 2: Different sizes
section2_label = mcrfpy.Caption(
text="Different Sizes",
pos=(50, 290),
font_size=16,
fill_color=mcrfpy.Color(150, 150, 150)
)
self.ui.append(section2_label)
# Thin bar
thin_bar = StatBar(
pos=(50, 320),
size=(200, 10),
current=60,
maximum=100,
fill_color=mcrfpy.Color(100, 150, 200),
show_text=False
)
self.ui.append(thin_bar.frame)
thin_label = mcrfpy.Caption(
text="Thin (no text)",
pos=(260, 315),
font_size=12,
fill_color=mcrfpy.Color(120, 120, 120)
)
self.ui.append(thin_label)
# Wide bar
wide_bar = StatBar(
pos=(50, 345),
size=(400, 35),
current=450,
maximum=500,
fill_color=StatBar.SHIELD_COLOR,
label="Shield",
font_size=16
)
self.ui.append(wide_bar.frame)
# Section 3: Stat bar group
section3_label = mcrfpy.Caption(
text="Stat Bar Group (auto-layout)",
pos=(500, 90),
font_size=16,
fill_color=mcrfpy.Color(150, 150, 150)
)
self.ui.append(section3_label)
group = create_stat_bar_group([
{"name": "Strength", "current": 15, "max": 20, "color": mcrfpy.Color(200, 80, 80)},
{"name": "Dexterity", "current": 18, "max": 20, "color": mcrfpy.Color(80, 200, 80)},
{"name": "Intelligence", "current": 12, "max": 20, "color": mcrfpy.Color(80, 80, 200)},
{"name": "Wisdom", "current": 14, "max": 20, "color": mcrfpy.Color(200, 200, 80)},
{"name": "Charisma", "current": 10, "max": 20, "color": mcrfpy.Color(200, 80, 200)},
], start_pos=(500, 120), spacing=10, size=(220, 22))
for bar in group.values():
self.ui.append(bar.frame)
# Section 4: Edge cases
section4_label = mcrfpy.Caption(
text="Edge Cases",
pos=(50, 420),
font_size=16,
fill_color=mcrfpy.Color(150, 150, 150)
)
self.ui.append(section4_label)
# Empty bar
empty_bar = StatBar(
pos=(50, 450),
size=(200, 20),
current=0,
maximum=100,
fill_color=StatBar.HEALTH_COLOR,
label="Empty"
)
self.ui.append(empty_bar.frame)
# Full bar
full_bar = StatBar(
pos=(50, 480),
size=(200, 20),
current=100,
maximum=100,
fill_color=StatBar.STAMINA_COLOR,
label="Full"
)
self.ui.append(full_bar.frame)
# Overfill attempt (should clamp)
overfill_bar = StatBar(
pos=(50, 510),
size=(200, 20),
current=150, # Will be clamped to 100
maximum=100,
fill_color=StatBar.XP_COLOR,
label="Overfill"
)
self.ui.append(overfill_bar.frame)
# Section 5: Animation demo
section5_label = mcrfpy.Caption(
text="Animation Demo (watch the bars change)",
pos=(500, 290),
font_size=16,
fill_color=mcrfpy.Color(150, 150, 150)
)
self.ui.append(section5_label)
self.anim_bar = StatBar(
pos=(500, 320),
size=(250, 30),
current=50,
maximum=100,
fill_color=mcrfpy.Color(150, 100, 200),
label="Animated"
)
self.ui.append(self.anim_bar.frame)
# Start animation loop
self._anim_direction = 1
mcrfpy.Timer("anim_bar", self._animate_bar, 2000)
# Section 6: Flash effect
section6_label = mcrfpy.Caption(
text="Flash Effect (press F)",
pos=(500, 400),
font_size=16,
fill_color=mcrfpy.Color(150, 150, 150)
)
self.ui.append(section6_label)
self.flash_bar = StatBar(
pos=(500, 430),
size=(250, 30),
current=80,
maximum=100,
fill_color=StatBar.HEALTH_COLOR,
label="Flash Me"
)
self.ui.append(self.flash_bar.frame)
# Instructions
instr = mcrfpy.Caption(
text="1-4: Decrease bars | Shift+1-4: Increase bars | F: Flash | R: Reset | ESC: Exit",
pos=(50, 730),
font_size=14,
fill_color=mcrfpy.Color(120, 120, 120)
)
self.ui.append(instr)
# Status display
self.status = mcrfpy.Caption(
text="Status: Ready",
pos=(50, 600),
font_size=16,
fill_color=mcrfpy.Color(100, 200, 100)
)
self.ui.append(self.status)
def _animate_bar(self, runtime):
"""Animate the demo bar back and forth."""
current = self.anim_bar.current
if self._anim_direction > 0:
new_val = min(100, current + 30)
if new_val >= 100:
self._anim_direction = -1
else:
new_val = max(10, current - 30)
if new_val <= 10:
self._anim_direction = 1
self.anim_bar.set_value(new_val, animate=True)
def on_key(self, key, state):
"""Handle keyboard input."""
if state != "start":
return
if key == "Escape":
sys.exit(0)
# Number keys to modify bars
bar_keys = ['hp', 'mp', 'stamina', 'xp']
key_map = {"Num1": 0, "Num2": 1, "Num3": 2, "Num4": 3}
if key in key_map:
idx = key_map[key]
if idx < len(bar_keys):
bar = self.bars[bar_keys[idx]]
# Decrease by 10
bar.set_value(bar.current - 10, animate=True)
self.status.text = f"Status: Decreased {bar_keys[idx].upper()}"
elif key == "F":
self.flash_bar.flash()
self.status.text = "Status: Flash effect triggered!"
elif key == "R":
# Reset all bars
self.bars['hp'].set_value(75, 100, animate=True)
self.bars['mp'].set_value(50, 80, animate=True)
self.bars['stamina'].set_value(90, 100, animate=True)
self.bars['xp'].set_value(250, 1000, animate=True)
self.status.text = "Status: All bars reset"
def activate(self):
"""Activate the demo scene."""
self.scene.on_key = self.on_key
mcrfpy.current_scene = self.scene
def main():
"""Run the stat bar demo."""
demo = StatBarDemo()
demo.activate()
# Headless mode: capture screenshot and exit
try:
if mcrfpy.headless_mode():
from mcrfpy import automation
mcrfpy.Timer("screenshot", lambda rt: (
automation.screenshot("screenshots/primitives/stat_bar_demo.png"),
sys.exit(0)
), 100)
except AttributeError:
pass
if __name__ == "__main__":
main()