667 lines
22 KiB
Python
667 lines
22 KiB
Python
"""Verify code snippets from Phase D wiki page updates."""
|
|
import mcrfpy
|
|
import sys
|
|
|
|
passes = 0
|
|
fails = 0
|
|
|
|
def check(name, fn):
|
|
global passes, fails
|
|
try:
|
|
fn()
|
|
passes += 1
|
|
print(f" [OK] {name}")
|
|
except Exception as e:
|
|
fails += 1
|
|
print(f" [FAIL] {name}: {e}")
|
|
|
|
# ===================================================================
|
|
print("=== GRID INTERACTION PATTERNS ===")
|
|
# ===================================================================
|
|
|
|
def test_gip_setup():
|
|
"""Setup template from Grid Interaction Patterns"""
|
|
scene = mcrfpy.Scene("gip_test")
|
|
ui = scene.children
|
|
|
|
texture = mcrfpy.Texture("assets/kenney_tinydungeon.png", 16, 16)
|
|
terrain = mcrfpy.TileLayer(name="terrain", z_index=-2, texture=texture)
|
|
highlight = mcrfpy.ColorLayer(name="highlight", z_index=-1)
|
|
overlay = mcrfpy.ColorLayer(name="overlay", z_index=1)
|
|
|
|
grid = mcrfpy.Grid(
|
|
grid_size=(20, 15),
|
|
pos=(50, 50),
|
|
size=(640, 480),
|
|
layers=[terrain, highlight, overlay]
|
|
)
|
|
grid.fill_color = mcrfpy.Color(20, 20, 30)
|
|
ui.append(grid)
|
|
|
|
player = mcrfpy.Entity(grid_pos=(10, 7), sprite_index=0)
|
|
grid.entities.append(player)
|
|
mcrfpy.current_scene = scene
|
|
|
|
check("GIP: setup template", test_gip_setup)
|
|
|
|
def test_gip_cell_hover():
|
|
"""Cell hover highlighting pattern"""
|
|
grid = mcrfpy.Grid(grid_size=(20, 15), pos=(0, 0), size=(320, 240), layers=[])
|
|
highlight = mcrfpy.ColorLayer(name="highlight", z_index=-1)
|
|
grid.add_layer(highlight)
|
|
current_highlight = [None]
|
|
|
|
def on_cell_enter(cell_pos):
|
|
x, y = int(cell_pos.x), int(cell_pos.y)
|
|
highlight.set((x, y), mcrfpy.Color(255, 255, 255, 40))
|
|
current_highlight[0] = (x, y)
|
|
|
|
def on_cell_exit(cell_pos):
|
|
x, y = int(cell_pos.x), int(cell_pos.y)
|
|
highlight.set((x, y), mcrfpy.Color(0, 0, 0, 0))
|
|
current_highlight[0] = None
|
|
|
|
grid.on_cell_enter = on_cell_enter
|
|
grid.on_cell_exit = on_cell_exit
|
|
|
|
check("GIP: cell hover highlighting", test_gip_cell_hover)
|
|
|
|
def test_gip_cell_click():
|
|
"""Cell click actions pattern"""
|
|
grid = mcrfpy.Grid(grid_size=(20, 15), pos=(0, 0), size=(320, 240))
|
|
for x in range(20):
|
|
for y in range(15):
|
|
grid.at(x, y).walkable = True
|
|
player = mcrfpy.Entity(grid_pos=(10, 7), sprite_index=0)
|
|
grid.entities.append(player)
|
|
|
|
def on_cell_click(cell_pos, button, action):
|
|
x, y = int(cell_pos.x), int(cell_pos.y)
|
|
point = grid.at(x, y)
|
|
if button == mcrfpy.MouseButton.LEFT and action == mcrfpy.InputState.PRESSED:
|
|
if point.walkable:
|
|
player.grid_x = x
|
|
player.grid_y = y
|
|
elif button == mcrfpy.MouseButton.RIGHT and action == mcrfpy.InputState.PRESSED:
|
|
pass # inspect
|
|
elif button == mcrfpy.MouseButton.MIDDLE and action == mcrfpy.InputState.PRESSED:
|
|
point.walkable = not point.walkable
|
|
|
|
grid.on_cell_click = on_cell_click
|
|
|
|
check("GIP: cell click actions", test_gip_cell_click)
|
|
|
|
def test_gip_wasd():
|
|
"""WASD movement pattern"""
|
|
scene = mcrfpy.Scene("gip_wasd")
|
|
grid = mcrfpy.Grid(grid_size=(20, 15), pos=(0, 0), size=(320, 240))
|
|
for x in range(20):
|
|
for y in range(15):
|
|
grid.at(x, y).walkable = True
|
|
player = mcrfpy.Entity(grid_pos=(10, 7), sprite_index=0)
|
|
grid.entities.append(player)
|
|
|
|
move_map = {
|
|
mcrfpy.Key.W: (0, -1),
|
|
mcrfpy.Key.A: (-1, 0),
|
|
mcrfpy.Key.S: (0, 1),
|
|
mcrfpy.Key.D: (1, 0),
|
|
}
|
|
|
|
def handle_key(key, action):
|
|
if action != mcrfpy.InputState.PRESSED:
|
|
return
|
|
if key in move_map:
|
|
dx, dy = move_map[key]
|
|
new_x = int(player.grid_x + dx)
|
|
new_y = int(player.grid_y + dy)
|
|
point = player.grid.at(new_x, new_y)
|
|
if point and point.walkable:
|
|
player.grid_x = new_x
|
|
player.grid_y = new_y
|
|
|
|
scene.on_key = handle_key
|
|
|
|
check("GIP: WASD movement", test_gip_wasd)
|
|
|
|
def test_gip_entity_selection():
|
|
"""Entity selection pattern"""
|
|
grid = mcrfpy.Grid(grid_size=(20, 15), pos=(0, 0), size=(320, 240), layers=[])
|
|
overlay = mcrfpy.ColorLayer(name="overlay", z_index=1)
|
|
grid.add_layer(overlay)
|
|
|
|
e1 = mcrfpy.Entity(grid_pos=(5, 5), sprite_index=0, name="sel_e1")
|
|
e2 = mcrfpy.Entity(grid_pos=(10, 10), sprite_index=1, name="sel_e2")
|
|
grid.entities.append(e1)
|
|
grid.entities.append(e2)
|
|
|
|
selected = [None]
|
|
def select_entity(entity):
|
|
if selected[0]:
|
|
ex, ey = int(selected[0].grid_x), int(selected[0].grid_y)
|
|
overlay.set((ex, ey), mcrfpy.Color(0, 0, 0, 0))
|
|
selected[0] = entity
|
|
if entity:
|
|
overlay.set((int(entity.grid_x), int(entity.grid_y)), mcrfpy.Color(255, 200, 0, 80))
|
|
|
|
def on_cell_click(cell_pos, button, action):
|
|
if button == mcrfpy.MouseButton.LEFT and action == mcrfpy.InputState.PRESSED:
|
|
x, y = int(cell_pos.x), int(cell_pos.y)
|
|
for entity in grid.entities:
|
|
if int(entity.grid_x) == x and int(entity.grid_y) == y:
|
|
select_entity(entity)
|
|
return
|
|
select_entity(None)
|
|
|
|
grid.on_cell_click = on_cell_click
|
|
select_entity(e1)
|
|
assert selected[0] == e1
|
|
|
|
check("GIP: entity selection", test_gip_entity_selection)
|
|
|
|
def test_gip_path_preview():
|
|
"""Path preview pattern"""
|
|
grid = mcrfpy.Grid(grid_size=(20, 15), pos=(0, 0), size=(320, 240), layers=[])
|
|
highlight = mcrfpy.ColorLayer(name="highlight", z_index=-1)
|
|
grid.add_layer(highlight)
|
|
for x in range(20):
|
|
for y in range(15):
|
|
grid.at(x, y).walkable = True
|
|
player = mcrfpy.Entity(grid_pos=(5, 5), sprite_index=0)
|
|
grid.entities.append(player)
|
|
|
|
def show_path_to(target_x, target_y):
|
|
path = grid.find_path(
|
|
(int(player.grid_x), int(player.grid_y)),
|
|
(target_x, target_y)
|
|
)
|
|
if path:
|
|
while len(path) > 0:
|
|
step = path.walk()
|
|
if step:
|
|
highlight.set((int(step.x), int(step.y)),
|
|
mcrfpy.Color(100, 200, 255, 60))
|
|
|
|
show_path_to(15, 10)
|
|
|
|
check("GIP: path preview", test_gip_path_preview)
|
|
|
|
def test_gip_tile_inspector():
|
|
"""Tile inspector panel pattern"""
|
|
scene = mcrfpy.Scene("gip_inspect")
|
|
ui = scene.children
|
|
grid = mcrfpy.Grid(grid_size=(20, 15), pos=(0, 0), size=(320, 240))
|
|
ui.append(grid)
|
|
|
|
inspector = mcrfpy.Frame(pos=(400, 50), size=(200, 150),
|
|
fill_color=mcrfpy.Color(30, 30, 40, 230))
|
|
inspector.visible = False
|
|
ui.append(inspector)
|
|
|
|
title = mcrfpy.Caption(text="Cell Info", pos=(10, 8))
|
|
inspector.children.append(title)
|
|
|
|
info = mcrfpy.Caption(text="", pos=(10, 30))
|
|
inspector.children.append(info)
|
|
|
|
def on_cell_click(cell_pos, button, action):
|
|
if button == mcrfpy.MouseButton.LEFT and action == mcrfpy.InputState.PRESSED:
|
|
x, y = int(cell_pos.x), int(cell_pos.y)
|
|
point = grid.at(x, y)
|
|
title.text = f"Cell ({x}, {y})"
|
|
info.text = f"Walkable: {point.walkable}"
|
|
inspector.visible = True
|
|
|
|
grid.on_cell_click = on_cell_click
|
|
|
|
check("GIP: tile inspector panel", test_gip_tile_inspector)
|
|
|
|
# ===================================================================
|
|
print("\n=== UI WIDGET PATTERNS ===")
|
|
# ===================================================================
|
|
|
|
def test_uwp_setup():
|
|
"""Setup template"""
|
|
scene = mcrfpy.Scene("uwp_test")
|
|
ui = scene.children
|
|
|
|
root = mcrfpy.Frame(pos=(50, 50), size=(300, 400),
|
|
fill_color=mcrfpy.Color(30, 30, 40))
|
|
root.outline_color = mcrfpy.Color(80, 80, 100)
|
|
root.outline = 2
|
|
ui.append(root)
|
|
mcrfpy.current_scene = scene
|
|
|
|
check("UWP: setup template", test_uwp_setup)
|
|
|
|
def test_uwp_button():
|
|
"""Button pattern"""
|
|
root = mcrfpy.Frame(pos=(0, 0), size=(300, 400))
|
|
def make_button(parent, pos, text, on_click):
|
|
btn = mcrfpy.Frame(pos=pos, size=(120, 32),
|
|
fill_color=mcrfpy.Color(60, 60, 80))
|
|
btn.outline_color = mcrfpy.Color(100, 100, 140)
|
|
btn.outline = 1
|
|
label = mcrfpy.Caption(text=text, pos=(10, 6))
|
|
label.fill_color = mcrfpy.Color(220, 220, 220)
|
|
btn.children.append(label)
|
|
btn.on_enter = lambda pos: setattr(btn, 'fill_color', mcrfpy.Color(80, 80, 110))
|
|
btn.on_exit = lambda pos: setattr(btn, 'fill_color', mcrfpy.Color(60, 60, 80))
|
|
btn.on_click = lambda pos, button, action: on_click() if button == mcrfpy.MouseButton.LEFT and action == mcrfpy.InputState.PRESSED else None
|
|
parent.children.append(btn)
|
|
return btn
|
|
|
|
b1 = make_button(root, (20, 20), "New Game", lambda: None)
|
|
b2 = make_button(root, (20, 60), "Options", lambda: None)
|
|
assert b1.w == 120
|
|
|
|
check("UWP: button pattern", test_uwp_button)
|
|
|
|
def test_uwp_toggle():
|
|
"""Toggle/checkbox pattern"""
|
|
root = mcrfpy.Frame(pos=(0, 0), size=(300, 400))
|
|
|
|
def make_toggle(parent, pos, label_text, initial=False, on_change=None):
|
|
state = {"checked": initial}
|
|
frame = mcrfpy.Frame(pos=pos, size=(160, 28),
|
|
fill_color=mcrfpy.Color(40, 40, 50))
|
|
indicator = mcrfpy.Frame(pos=(6, 6), size=(16, 16))
|
|
indicator.outline = 1
|
|
indicator.outline_color = mcrfpy.Color(120, 120, 140)
|
|
frame.children.append(indicator)
|
|
|
|
label = mcrfpy.Caption(text=label_text, pos=(30, 5))
|
|
label.fill_color = mcrfpy.Color(200, 200, 200)
|
|
frame.children.append(label)
|
|
|
|
def update_visual():
|
|
if state["checked"]:
|
|
indicator.fill_color = mcrfpy.Color(100, 180, 100)
|
|
else:
|
|
indicator.fill_color = mcrfpy.Color(50, 50, 60)
|
|
|
|
def toggle(pos, button, action):
|
|
if button == mcrfpy.MouseButton.LEFT and action == mcrfpy.InputState.PRESSED:
|
|
state["checked"] = not state["checked"]
|
|
update_visual()
|
|
if on_change:
|
|
on_change(state["checked"])
|
|
|
|
frame.on_click = toggle
|
|
update_visual()
|
|
parent.children.append(frame)
|
|
return state
|
|
|
|
t = make_toggle(root, (20, 20), "Music", initial=True)
|
|
assert t["checked"] == True
|
|
|
|
check("UWP: toggle pattern", test_uwp_toggle)
|
|
|
|
def test_uwp_vertical_menu():
|
|
"""Vertical menu with keyboard nav"""
|
|
scene = mcrfpy.Scene("uwp_menu")
|
|
root = mcrfpy.Frame(pos=(0, 0), size=(300, 400))
|
|
scene.children.append(root)
|
|
|
|
class VerticalMenu:
|
|
def __init__(self, parent, pos, options, on_select):
|
|
self.options = options
|
|
self.on_select = on_select
|
|
self.selected = 0
|
|
self.frame = mcrfpy.Frame(pos=pos, size=(180, len(options) * 28 + 8),
|
|
fill_color=mcrfpy.Color(35, 35, 45))
|
|
parent.children.append(self.frame)
|
|
self.items = []
|
|
for i, (label, value) in enumerate(options):
|
|
item = mcrfpy.Caption(text=label, pos=(12, 4 + i * 28))
|
|
item.fill_color = mcrfpy.Color(180, 180, 180)
|
|
self.frame.children.append(item)
|
|
self.items.append(item)
|
|
self._update_highlight()
|
|
|
|
def _update_highlight(self):
|
|
for i, item in enumerate(self.items):
|
|
if i == self.selected:
|
|
item.fill_color = mcrfpy.Color(255, 220, 100)
|
|
else:
|
|
item.fill_color = mcrfpy.Color(180, 180, 180)
|
|
|
|
def move_up(self):
|
|
self.selected = (self.selected - 1) % len(self.options)
|
|
self._update_highlight()
|
|
|
|
def move_down(self):
|
|
self.selected = (self.selected + 1) % len(self.options)
|
|
self._update_highlight()
|
|
|
|
def confirm(self):
|
|
_, value = self.options[self.selected]
|
|
self.on_select(value)
|
|
|
|
result = [None]
|
|
menu = VerticalMenu(root, (20, 20), [
|
|
("Continue", "continue"),
|
|
("New Game", "new"),
|
|
("Quit", "quit")
|
|
], on_select=lambda v: result.__setitem__(0, v))
|
|
|
|
def handle_key(key, action):
|
|
if action != mcrfpy.InputState.PRESSED:
|
|
return
|
|
if key == mcrfpy.Key.UP:
|
|
menu.move_up()
|
|
elif key == mcrfpy.Key.DOWN:
|
|
menu.move_down()
|
|
elif key == mcrfpy.Key.ENTER:
|
|
menu.confirm()
|
|
|
|
scene.on_key = handle_key
|
|
menu.confirm()
|
|
assert result[0] == "continue"
|
|
|
|
check("UWP: vertical menu", test_uwp_vertical_menu)
|
|
|
|
def test_uwp_modal():
|
|
"""Modal dialog pattern"""
|
|
scene = mcrfpy.Scene("uwp_modal")
|
|
ui = scene.children
|
|
|
|
dismissed = [False]
|
|
backdrop = mcrfpy.Frame(pos=(0, 0), size=(1024, 768),
|
|
fill_color=mcrfpy.Color(0, 0, 0, 160))
|
|
backdrop.z_index = 900
|
|
backdrop.on_click = lambda pos, btn, action: None # Block clicks
|
|
ui.append(backdrop)
|
|
|
|
dialog = mcrfpy.Frame(pos=(312, 284), size=(400, 200),
|
|
fill_color=mcrfpy.Color(50, 50, 65))
|
|
dialog.outline_color = mcrfpy.Color(120, 120, 150)
|
|
dialog.outline = 2
|
|
dialog.z_index = 901
|
|
ui.append(dialog)
|
|
|
|
msg = mcrfpy.Caption(text="Game saved!", pos=(20, 20))
|
|
msg.fill_color = mcrfpy.Color(220, 220, 220)
|
|
dialog.children.append(msg)
|
|
|
|
ok_btn = mcrfpy.Frame(pos=(150, 140), size=(100, 36),
|
|
fill_color=mcrfpy.Color(70, 100, 70))
|
|
ok_btn.outline = 1
|
|
ok_btn.on_click = lambda pos, btn, action: dismissed.__setitem__(0, True)
|
|
dialog.children.append(ok_btn)
|
|
|
|
ok_label = mcrfpy.Caption(text="OK", pos=(35, 8))
|
|
ok_label.fill_color = mcrfpy.Color(220, 255, 220)
|
|
ok_btn.children.append(ok_label)
|
|
|
|
check("UWP: modal dialog", test_uwp_modal)
|
|
|
|
def test_uwp_hotbar():
|
|
"""Hotbar / quick slots pattern"""
|
|
scene = mcrfpy.Scene("uwp_hotbar")
|
|
root = mcrfpy.Frame(pos=(0, 0), size=(800, 600))
|
|
scene.children.append(root)
|
|
|
|
slot_count = 9
|
|
slots = []
|
|
hotbar_frame = mcrfpy.Frame(pos=(200, 500), size=(slot_count * 36 + 8, 44),
|
|
fill_color=mcrfpy.Color(30, 30, 40, 200))
|
|
root.children.append(hotbar_frame)
|
|
|
|
for i in range(slot_count):
|
|
slot = mcrfpy.Frame(pos=(4 + i * 36, 4), size=(32, 32),
|
|
fill_color=mcrfpy.Color(50, 50, 60))
|
|
slot.outline = 1
|
|
slot.outline_color = mcrfpy.Color(80, 80, 100)
|
|
hotbar_frame.children.append(slot)
|
|
num = mcrfpy.Caption(text=str((i + 1) % 10), pos=(2, 2))
|
|
num.fill_color = mcrfpy.Color(100, 100, 120)
|
|
slot.children.append(num)
|
|
slots.append(slot)
|
|
|
|
selected = [0]
|
|
def select_slot(index):
|
|
if 0 <= index < len(slots):
|
|
slots[selected[0]].outline_color = mcrfpy.Color(80, 80, 100)
|
|
slots[selected[0]].outline = 1
|
|
selected[0] = index
|
|
slots[index].outline_color = mcrfpy.Color(200, 180, 80)
|
|
slots[index].outline = 2
|
|
|
|
select_slot(0)
|
|
|
|
def handle_key(key, action):
|
|
if action != mcrfpy.InputState.PRESSED:
|
|
return
|
|
num_keys = {
|
|
mcrfpy.Key.NUM_1: 0, mcrfpy.Key.NUM_2: 1, mcrfpy.Key.NUM_3: 2,
|
|
mcrfpy.Key.NUM_4: 3, mcrfpy.Key.NUM_5: 4, mcrfpy.Key.NUM_6: 5,
|
|
mcrfpy.Key.NUM_7: 6, mcrfpy.Key.NUM_8: 7, mcrfpy.Key.NUM_9: 8,
|
|
}
|
|
if key in num_keys:
|
|
select_slot(num_keys[key])
|
|
|
|
scene.on_key = handle_key
|
|
assert slots[0].outline == 2
|
|
|
|
check("UWP: hotbar/quick slots", test_uwp_hotbar)
|
|
|
|
def test_uwp_draggable():
|
|
"""Draggable window pattern"""
|
|
root = mcrfpy.Frame(pos=(0, 0), size=(800, 600))
|
|
|
|
frame = mcrfpy.Frame(pos=(100, 100), size=(250, 300),
|
|
fill_color=mcrfpy.Color(45, 45, 55))
|
|
frame.outline = 1
|
|
frame.outline_color = mcrfpy.Color(100, 100, 120)
|
|
root.children.append(frame)
|
|
|
|
title_bar = mcrfpy.Frame(pos=(0, 0), size=(250, 24),
|
|
fill_color=mcrfpy.Color(60, 60, 80))
|
|
frame.children.append(title_bar)
|
|
|
|
title_label = mcrfpy.Caption(text="Inventory", pos=(8, 4))
|
|
title_label.fill_color = mcrfpy.Color(200, 200, 220)
|
|
title_bar.children.append(title_label)
|
|
|
|
content = mcrfpy.Caption(text="Items here...", pos=(10, 38))
|
|
frame.children.append(content)
|
|
|
|
check("UWP: draggable window", test_uwp_draggable)
|
|
|
|
# ===================================================================
|
|
print("\n=== RENDERING AND VISUALS ===")
|
|
# ===================================================================
|
|
|
|
def test_rv_basic_elements():
|
|
"""Creating basic UI elements"""
|
|
scene = mcrfpy.Scene("rv_test")
|
|
ui = scene.children
|
|
|
|
frame = mcrfpy.Frame(pos=(100, 100), size=(200, 150),
|
|
fill_color=mcrfpy.Color(50, 50, 50))
|
|
frame.outline_color = mcrfpy.Color(255, 255, 255)
|
|
frame.outline = 2
|
|
ui.append(frame)
|
|
|
|
label = mcrfpy.Caption(text="Hello World!", pos=(10, 10))
|
|
label.font_size = 24
|
|
label.fill_color = mcrfpy.Color(255, 255, 255)
|
|
ui.append(label)
|
|
|
|
sprite = mcrfpy.Sprite(x=50, y=50, sprite_index=0)
|
|
ui.append(sprite)
|
|
|
|
check("RV: basic UI elements", test_rv_basic_elements)
|
|
|
|
def test_rv_textures():
|
|
"""Texture loading and sprite sheets"""
|
|
texture = mcrfpy.Texture("assets/kenney_tinydungeon.png", 16, 16)
|
|
sprite = mcrfpy.Sprite(x=100, y=100)
|
|
sprite.texture = texture
|
|
sprite.sprite_index = 5
|
|
|
|
check("RV: textures and sprite sheets", test_rv_textures)
|
|
|
|
def test_rv_z_order():
|
|
"""Z-order layering"""
|
|
scene = mcrfpy.Scene("rv_z")
|
|
ui = scene.children
|
|
|
|
background = mcrfpy.Frame(pos=(0, 0), size=(800, 600),
|
|
fill_color=mcrfpy.Color(20, 20, 20))
|
|
background.z_index = 0
|
|
ui.append(background)
|
|
|
|
grid = mcrfpy.Grid(grid_size=(20, 15), pos=(50, 50), size=(400, 300))
|
|
grid.z_index = 10
|
|
ui.append(grid)
|
|
|
|
hud = mcrfpy.Frame(pos=(0, 0), size=(800, 50),
|
|
fill_color=mcrfpy.Color(30, 30, 30, 200))
|
|
hud.z_index = 100
|
|
ui.append(hud)
|
|
|
|
check("RV: z-order layering", test_rv_z_order)
|
|
|
|
def test_rv_colors():
|
|
"""Color creation and application"""
|
|
red = mcrfpy.Color(255, 0, 0)
|
|
semi_transparent = mcrfpy.Color(255, 255, 255, 128)
|
|
|
|
frame = mcrfpy.Frame(pos=(0, 0), size=(100, 100))
|
|
frame.fill_color = mcrfpy.Color(50, 50, 50)
|
|
frame.outline_color = mcrfpy.Color(255, 255, 255)
|
|
|
|
caption = mcrfpy.Caption(text="Test", pos=(0, 0))
|
|
caption.fill_color = mcrfpy.Color(255, 255, 0)
|
|
|
|
assert red.r == 255
|
|
assert semi_transparent.a == 128
|
|
|
|
check("RV: colors", test_rv_colors)
|
|
|
|
def test_rv_animations():
|
|
"""Animation patterns"""
|
|
frame = mcrfpy.Frame(pos=(0, 0), size=(100, 100))
|
|
frame.animate("opacity", 1.0, 1.0, mcrfpy.Easing.EASE_IN_QUAD)
|
|
frame.animate("fill_color", (255, 0, 0, 255), 0.5, mcrfpy.Easing.LINEAR)
|
|
frame.animate("x", 200.0, 0.3, mcrfpy.Easing.EASE_OUT_CUBIC)
|
|
|
|
check("RV: animations", test_rv_animations)
|
|
|
|
def test_rv_visibility():
|
|
"""Visibility control"""
|
|
sprite = mcrfpy.Sprite(x=0, y=0, sprite_index=0)
|
|
sprite.visible = False
|
|
sprite.visible = True
|
|
sprite.opacity = 0.5
|
|
assert sprite.opacity == 0.5
|
|
|
|
check("RV: visibility", test_rv_visibility)
|
|
|
|
def test_rv_hud():
|
|
"""HUD overlay pattern"""
|
|
scene = mcrfpy.Scene("rv_hud")
|
|
ui = scene.children
|
|
|
|
hud = mcrfpy.Frame(pos=(0, 0), size=(800, 60),
|
|
fill_color=mcrfpy.Color(30, 30, 30, 200))
|
|
hud.z_index = 100
|
|
ui.append(hud)
|
|
|
|
health_label = mcrfpy.Caption(text="HP: 100/100", pos=(10, 10))
|
|
health_label.font_size = 18
|
|
health_label.fill_color = mcrfpy.Color(255, 255, 255)
|
|
hud.children.append(health_label)
|
|
|
|
def update_hud(current_hp, max_hp):
|
|
health_label.text = f"HP: {current_hp}/{max_hp}"
|
|
if current_hp < max_hp * 0.3:
|
|
health_label.fill_color = mcrfpy.Color(255, 0, 0)
|
|
elif current_hp < max_hp * 0.6:
|
|
health_label.fill_color = mcrfpy.Color(255, 255, 0)
|
|
else:
|
|
health_label.fill_color = mcrfpy.Color(0, 255, 0)
|
|
|
|
update_hud(50, 100)
|
|
assert health_label.text == "HP: 50/100"
|
|
|
|
check("RV: HUD overlay", test_rv_hud)
|
|
|
|
def test_rv_health_bar():
|
|
"""Health bar pattern"""
|
|
bg = mcrfpy.Frame(pos=(10, 10), size=(100, 10),
|
|
fill_color=mcrfpy.Color(255, 0, 0))
|
|
bg.z_index = 90
|
|
|
|
fg = mcrfpy.Frame(pos=(10, 10), size=(100, 10),
|
|
fill_color=mcrfpy.Color(0, 255, 0))
|
|
fg.z_index = 91
|
|
|
|
ratio = 0.5
|
|
target_width = int(100 * ratio)
|
|
fg.animate("w", float(target_width), 0.2, mcrfpy.Easing.EASE_OUT_QUAD)
|
|
|
|
check("RV: health bar", test_rv_health_bar)
|
|
|
|
def test_rv_grid_rendering():
|
|
"""Grid rendering basics"""
|
|
texture = mcrfpy.Texture("assets/kenney_tinydungeon.png", 16, 16)
|
|
terrain = mcrfpy.TileLayer(name="terrain", z_index=-1, texture=texture)
|
|
grid = mcrfpy.Grid(grid_size=(20, 15), pos=(100, 100), size=(400, 300),
|
|
layers=[terrain])
|
|
|
|
for x in range(20):
|
|
for y in range(15):
|
|
if x == 0 or x == 19 or y == 0 or y == 14:
|
|
terrain.set((x, y), 1)
|
|
else:
|
|
terrain.set((x, y), 0)
|
|
|
|
check("RV: grid rendering", test_rv_grid_rendering)
|
|
|
|
def test_rv_camera():
|
|
"""Camera/viewport control"""
|
|
grid = mcrfpy.Grid(grid_size=(50, 50), pos=(0, 0), size=(400, 400))
|
|
grid.zoom = 2.0
|
|
grid.center_camera((25, 25))
|
|
grid.animate("zoom", 1.5, 1.0, mcrfpy.Easing.EASE_IN_OUT)
|
|
|
|
check("RV: camera control", test_rv_camera)
|
|
|
|
def test_rv_particle_pattern():
|
|
"""Particle-like effects pattern"""
|
|
scene = mcrfpy.Scene("rv_particles")
|
|
ui = scene.children
|
|
import random
|
|
|
|
def create_explosion(x, y):
|
|
particles = []
|
|
for i in range(5):
|
|
p = mcrfpy.Frame(pos=(x, y), size=(4, 4),
|
|
fill_color=mcrfpy.Color(255, 200, 50))
|
|
p.z_index = 50
|
|
target_x = x + random.randint(-50, 50)
|
|
target_y = y + random.randint(-50, 50)
|
|
p.animate("x", float(target_x), 0.5, mcrfpy.Easing.EASE_OUT_QUAD)
|
|
p.animate("y", float(target_y), 0.5, mcrfpy.Easing.EASE_OUT_QUAD)
|
|
p.animate("opacity", 0.0, 0.5, mcrfpy.Easing.LINEAR)
|
|
particles.append(p)
|
|
ui.append(p)
|
|
return particles
|
|
|
|
particles = create_explosion(100, 100)
|
|
assert len(particles) == 5
|
|
|
|
check("RV: particle effects", test_rv_particle_pattern)
|
|
|
|
# ===================================================================
|
|
print("\n" + "=" * 60)
|
|
print(f"PHASE D VERIFICATION: {passes} passed, {fails} failed")
|
|
print("=" * 60)
|
|
|
|
if fails:
|
|
sys.exit(1)
|
|
else:
|
|
sys.exit(0)
|