Inventario de RPG
Un inventario donde la rareza es luz: los objetos raros tienen glow, los épicos y legendarios bloom, y los legendarios palpitan. Al hacer clic en un objeto, presence cambia el panel de detalles de cristal y sus barras crecen con transition(width=...).

uv run --with pyzed-ui python examples/showcase/inventory.pypython3 -m venv .venvsource .venv/bin/activatepython -m pip install pyzed-uipython examples/showcase/inventory.pypy -m venv .venv.venv\Scripts\Activate.ps1python -m pip install pyzed-uipython examples\showcase\inventory.pypython3 examples/showcase/inventory.pypy examples\showcase\inventory.pyLas brasas del fondo son el grafo embers.pzshad; míralo en Shaders y efectos.
Cómo está hecho
Sección titulada «Cómo está hecho»La rareza como luz
Sección titulada «La rareza como luz»Glow para los raros; bloom para épicos y legendarios.
style.update(bloom=(color, 0.8))tile.animate("glow_pulse", repeat="infinite", duration=2000)Estadísticas animadas
Sección titulada «Estadísticas animadas»El ancho de las barras es una propiedad de layout, así que se anima sin descolocar nada.
bar.transition(width=240 * value, duration=320, easing="ease_out_cubic")Cambio de panel
Sección titulada «Cambio de panel»pz.presence saca el panel anterior y hace entrar el nuevo.
pz.presence(panel, key=self.selected, enter="fade_in_right", exit="fade_out")Prueba esto
Sección titulada «Prueba esto»- Añade un objeto con una rareza nueva, y un color y una luz para ella en la tabla de rarezas.
- Haz que las barras de estadísticas crezcan más lento subiendo la
durationde la transición. - Cambia la variable
risedel shader de brasas para que las chispas vayan más rápido.
Código completo
Sección titulada «Código completo»"""An RPG inventory: a grid of items whose rarity glows, and a glass details panel.
python examples/showcase/inventory.py
- Rarity is light: rare items ``glow``, epic and legendary ones ``bloom`` (and legendary ones pulse with ``animate("glow_pulse")``).- The details panel is ``glass`` over an ember backdrop, a shader graph made of nodes in Pyzed Design (``shaders/embers.pzshad``); stat bars and the selected slot animate with ``transition``.- Click an item to inspect it."""
from pathlib import Path
import pyzed as pz
SHADER = Path(__file__).parent / "shaders" / "embers.pzshad"
RARITY = { "common": ("#9ca3af", None), "rare": ("#60a5fa", "glow"), "epic": ("#c084fc", "bloom"), "legendary": ("#fb923c", "bloom"),}ITEMS = ( ("sword", "Dawnbreaker", "legendary", "Weapon", {"Attack": 0.92, "Speed": 0.64, "Crit": 0.71}), ("shield", "Aegis of Tides", "epic", "Off-hand", {"Armor": 0.81, "Block": 0.66, "Weight": 0.40}), ("wand", "Ember Wand", "rare", "Weapon", {"Attack": 0.58, "Speed": 0.80, "Crit": 0.35}), ("gem", "Star Shard", "epic", "Material", {"Purity": 0.88, "Power": 0.62, "Value": 0.74}), ("flask-conical", "Health Potion", "common", "Consumable", {"Heal": 0.45, "Duration": 0.10, "Value": 0.08}), ("scroll", "Scroll of Return", "common", "Consumable", {"Range": 0.30, "Value": 0.12, "Weight": 0.05}), ("crown", "Crown of Ash", "legendary", "Helm", {"Armor": 0.55, "Wisdom": 0.95, "Charm": 0.86}), ("key", "Old Key", "common", "Quest", {"Value": 0.02, "Weight": 0.04, "Rust": 0.90}), ("feather", "Phoenix Plume", "rare", "Material", {"Power": 0.70, "Purity": 0.52, "Value": 0.61}), ("bow-arrow", "Windstring", "rare", "Weapon", {"Attack": 0.66, "Speed": 0.87, "Crit": 0.50}), ("shirt", "Silk Tunic", "common", "Chest", {"Armor": 0.20, "Speed": 0.60, "Weight": 0.10}), ("apple", "Golden Apple", "epic", "Consumable", {"Heal": 0.95, "Duration": 0.60, "Value": 0.70}),)#: Each rarity's slot color.TINT = {"common": "#1f1d24", "rare": "#16233a", "epic": "#2a1a3d", "legendary": "#3a2112"}COLUMNS, ROWS = 6, 4SLOT = 76
class Inventory(pz.App): title = "Inventory" size = (1180, 640) theme = pz.themes.ONE_DARK
def __init__(self): self.selected = 0
def select(self, index): self.selected = index
def slot(self, index): if index >= len(ITEMS): return pz.container(None, width=SLOT, height=SLOT).style( background="#ffffff08", radius=12, border=(1, "#ffffff12")) icon, name, rarity, _, _ = ITEMS[index] color, light = RARITY[rarity] selected = index == self.selected # A plain color, not a gradient: the GPU renderer draws halos only around solid boxes. style = dict(radius=12, background=TINT[rarity], border=(2 if selected else 1, color if selected else color + "66")) if light == "glow": style.update(glow=(color + "88", 10)) elif light == "bloom": style.update(bloom=(color, 0.55 if rarity == "epic" else 0.8)) tile = pz.container(pz.icon(icon, size=32, color="#ffffff"), width=SLOT, height=SLOT, align_x="center", align_y="center").style(**style) if rarity == "legendary": tile = tile.animate("glow_pulse", repeat="infinite", duration=2000) tile = pz.mouse_area(tile, on_press=lambda: self.select(index)) return tile.animate("grow", on="hover").animate("shrink", on="press")
def grid(self): rows = [pz.row([self.slot(r * COLUMNS + c) for c in range(COLUMNS)], spacing=10) for r in range(ROWS)] gold = pz.row([pz.icon("coins", size=16, color="#fbbf24"), pz.text("12,480", size=14, weight="bold", color="#fde68a"), pz.space(width="fill"), pz.text(f"{len(ITEMS)} / {COLUMNS * ROWS}", size=12, color="#ffffff88")], spacing=8, align="center", width=COLUMNS * SLOT + (COLUMNS - 1) * 10) return pz.column([ pz.text("INVENTORY", size=13, weight="bold", color="#fdba74"), pz.column(rows, spacing=10), gold, ], spacing=14).style(glass={"tint": "#140b0b", "strength": 0.35, "blur": 16}, radius=20, padding=20)
def details(self): icon, name, rarity, kind, stats = ITEMS[self.selected] color, _ = RARITY[rarity] bars = [] for label, value in stats.items(): bars.append(pz.column([ pz.row([pz.text(label, size=12, color="#ffffffbb"), pz.space(width="fill"), pz.text(str(round(value * 100)), size=12, weight="bold", color="#ffffff")], width=240), pz.container(pz.container(None, height=8).style( background=pz.Gradient([color + "88", color], angle=90), radius=4).transition( width=240 * value, duration=320, easing="ease_out_cubic"), width=240).style(background="#ffffff14", radius=4), ], spacing=4)) hero = pz.container(pz.icon(icon, size=56, color="#ffffff").style(bloom=(color, 0.9)), width=240, height=150, align_x="center", align_y="center").style( background=pz.Gradient([color + "44", "#00000000"], angle=180), radius=16) panel = pz.column([ hero, pz.text(name, size=22, weight="bold", color="#ffffff"), pz.row([pz.text(rarity.upper(), size=11, weight="bold", color=color), pz.text("·", size=11, color="#ffffff66"), pz.text(kind, size=11, color="#ffffffaa")], spacing=6), *bars, pz.row([ pz.text("Equip", size=13, weight="bold", color="#1c1917").style( background=color, radius=8, padding=(8, 18)).animate("lift", on="hover"), pz.text("Drop", size=13, color="#ffffffcc").style( background="#ffffff14", radius=8, padding=(8, 18), border=(1, "#ffffff22")), ], spacing=10), ], spacing=12, width=240) return pz.presence(panel.style(glass={"tint": "#1c1012", "strength": 0.3, "blur": 18}, radius=20, padding=20), key=self.selected, enter="fade_in_right", exit="fade_out", id="details")
def view(self): body = pz.row([self.grid(), self.details()], spacing=24, align="start") return pz.stack([ pz.shader(SHADER, width="fill", height="fill", fallback=pz.Gradient(["#0f0707", "#2a0e05"], angle=180)), pz.container(body, width="fill", height="fill", align_x="center", align_y="center"), ])
if __name__ == "__main__": pz.run(Inventory)