123 lines
3.9 KiB
Python
123 lines
3.9 KiB
Python
|
|
"""McRogueFace - Health Bar Widget (enhanced)
|
||
|
|
|
||
|
|
Documentation: https://mcrogueface.github.io/cookbook/ui_health_bar
|
||
|
|
Repository: https://github.com/jmccardle/McRogueFace/blob/master/docs/cookbook/ui/ui_health_bar_enhanced.py
|
||
|
|
|
||
|
|
This code is extracted from the McRogueFace documentation and can be
|
||
|
|
run directly with: ./mcrogueface path/to/this/file.py
|
||
|
|
"""
|
||
|
|
|
||
|
|
import mcrfpy
|
||
|
|
|
||
|
|
class EnhancedHealthBar:
|
||
|
|
"""Health bar with text display, color transitions, and animations."""
|
||
|
|
|
||
|
|
def __init__(self, x, y, w, h, current, maximum, show_text=True):
|
||
|
|
self.x = x
|
||
|
|
self.y = y
|
||
|
|
self.w = w
|
||
|
|
self.h = h
|
||
|
|
self.current = current
|
||
|
|
self.maximum = maximum
|
||
|
|
self.show_text = show_text
|
||
|
|
|
||
|
|
# Color thresholds (ratio -> color)
|
||
|
|
self.colors = {
|
||
|
|
0.6: mcrfpy.Color(50, 205, 50), # Green when > 60%
|
||
|
|
0.3: mcrfpy.Color(255, 165, 0), # Orange when > 30%
|
||
|
|
0.0: mcrfpy.Color(220, 20, 20), # Red when <= 30%
|
||
|
|
}
|
||
|
|
|
||
|
|
# Background frame with dark fill
|
||
|
|
self.background = mcrfpy.Frame(x, y, w, h)
|
||
|
|
self.background.fill_color = mcrfpy.Color(30, 30, 30)
|
||
|
|
self.background.outline = 2
|
||
|
|
self.background.outline_color = mcrfpy.Color(100, 100, 100)
|
||
|
|
|
||
|
|
# Fill frame (nested inside background conceptually)
|
||
|
|
padding = 2
|
||
|
|
self.fill = mcrfpy.Frame(
|
||
|
|
x + padding,
|
||
|
|
y + padding,
|
||
|
|
w - padding * 2,
|
||
|
|
h - padding * 2
|
||
|
|
)
|
||
|
|
self.fill.outline = 0
|
||
|
|
|
||
|
|
# Text label
|
||
|
|
self.label = None
|
||
|
|
if show_text:
|
||
|
|
self.label = mcrfpy.Caption(
|
||
|
|
"",
|
||
|
|
mcrfpy.default_font,
|
||
|
|
x + w / 2 - 20,
|
||
|
|
y + h / 2 - 8
|
||
|
|
)
|
||
|
|
self.label.fill_color = mcrfpy.Color(255, 255, 255)
|
||
|
|
self.label.outline = 1
|
||
|
|
self.label.outline_color = mcrfpy.Color(0, 0, 0)
|
||
|
|
|
||
|
|
self._update()
|
||
|
|
|
||
|
|
def _get_color_for_ratio(self, ratio):
|
||
|
|
"""Get the appropriate color based on health ratio."""
|
||
|
|
for threshold, color in sorted(self.colors.items(), reverse=True):
|
||
|
|
if ratio > threshold:
|
||
|
|
return color
|
||
|
|
# Return the lowest threshold color if ratio is 0 or below
|
||
|
|
return self.colors[0.0]
|
||
|
|
|
||
|
|
def _update(self):
|
||
|
|
"""Update fill width, color, and text."""
|
||
|
|
ratio = max(0, min(1, self.current / self.maximum))
|
||
|
|
|
||
|
|
# Update fill width (accounting for padding)
|
||
|
|
padding = 2
|
||
|
|
self.fill.w = (self.w - padding * 2) * ratio
|
||
|
|
|
||
|
|
# Update color based on ratio
|
||
|
|
self.fill.fill_color = self._get_color_for_ratio(ratio)
|
||
|
|
|
||
|
|
# Update text
|
||
|
|
if self.label:
|
||
|
|
self.label.text = f"{int(self.current)}/{int(self.maximum)}"
|
||
|
|
# Center the text
|
||
|
|
text_width = len(self.label.text) * 8 # Approximate
|
||
|
|
self.label.x = self.x + (self.w - text_width) / 2
|
||
|
|
|
||
|
|
def set_health(self, current, maximum=None):
|
||
|
|
"""Update health values."""
|
||
|
|
self.current = max(0, current)
|
||
|
|
if maximum is not None:
|
||
|
|
self.maximum = maximum
|
||
|
|
self._update()
|
||
|
|
|
||
|
|
def damage(self, amount):
|
||
|
|
"""Apply damage (convenience method)."""
|
||
|
|
self.set_health(self.current - amount)
|
||
|
|
|
||
|
|
def heal(self, amount):
|
||
|
|
"""Apply healing (convenience method)."""
|
||
|
|
self.set_health(min(self.maximum, self.current + amount))
|
||
|
|
|
||
|
|
def add_to_scene(self, ui):
|
||
|
|
"""Add all components to scene UI."""
|
||
|
|
ui.append(self.background)
|
||
|
|
ui.append(self.fill)
|
||
|
|
if self.label:
|
||
|
|
ui.append(self.label)
|
||
|
|
|
||
|
|
|
||
|
|
# Usage
|
||
|
|
mcrfpy.createScene("demo")
|
||
|
|
mcrfpy.setScene("demo")
|
||
|
|
ui = mcrfpy.sceneUI("demo")
|
||
|
|
|
||
|
|
# Create enhanced health bar
|
||
|
|
hp = EnhancedHealthBar(50, 50, 250, 25, current=100, maximum=100)
|
||
|
|
hp.add_to_scene(ui)
|
||
|
|
|
||
|
|
# Simulate damage
|
||
|
|
hp.damage(30) # Now 70/100, shows green
|
||
|
|
hp.damage(25) # Now 45/100, shows orange
|
||
|
|
hp.damage(20) # Now 25/100, shows red
|