293 lines
9.7 KiB
Python
293 lines
9.7 KiB
Python
# entity3d_test.py - Unit test for Entity3D 3D game entities
|
|
|
|
import mcrfpy
|
|
import sys
|
|
|
|
def test_entity3d_creation():
|
|
"""Test basic Entity3D creation and default properties"""
|
|
e = mcrfpy.Entity3D()
|
|
|
|
# Default grid position (0, 0)
|
|
assert e.pos == (0, 0), f"Expected pos=(0, 0), got {e.pos}"
|
|
assert e.grid_pos == (0, 0), f"Expected grid_pos=(0, 0), got {e.grid_pos}"
|
|
|
|
# Default world position (at origin)
|
|
wp = e.world_pos
|
|
assert len(wp) == 3, f"Expected 3-tuple for world_pos, got {wp}"
|
|
assert wp[0] == 0.0, f"Expected world_pos.x=0, got {wp[0]}"
|
|
assert wp[2] == 0.0, f"Expected world_pos.z=0, got {wp[2]}"
|
|
|
|
# Default rotation
|
|
assert e.rotation == 0.0, f"Expected rotation=0, got {e.rotation}"
|
|
|
|
# Default scale
|
|
assert e.scale == 1.0, f"Expected scale=1.0, got {e.scale}"
|
|
|
|
# Default visibility
|
|
assert e.visible == True, f"Expected visible=True, got {e.visible}"
|
|
|
|
# Default color (orange: 200, 100, 50)
|
|
c = e.color
|
|
assert c.r == 200, f"Expected color.r=200, got {c.r}"
|
|
assert c.g == 100, f"Expected color.g=100, got {c.g}"
|
|
assert c.b == 50, f"Expected color.b=50, got {c.b}"
|
|
|
|
print("[PASS] test_entity3d_creation")
|
|
|
|
def test_entity3d_with_pos():
|
|
"""Test Entity3D creation with position argument"""
|
|
e = mcrfpy.Entity3D(pos=(5, 10))
|
|
|
|
assert e.pos == (5, 10), f"Expected pos=(5, 10), got {e.pos}"
|
|
assert e.grid_pos == (5, 10), f"Expected grid_pos=(5, 10), got {e.grid_pos}"
|
|
|
|
print("[PASS] test_entity3d_with_pos")
|
|
|
|
def test_entity3d_with_kwargs():
|
|
"""Test Entity3D creation with keyword arguments"""
|
|
e = mcrfpy.Entity3D(
|
|
pos=(3, 7),
|
|
rotation=90.0,
|
|
scale=2.0,
|
|
visible=False,
|
|
color=mcrfpy.Color(255, 0, 0)
|
|
)
|
|
|
|
assert e.pos == (3, 7), f"Expected pos=(3, 7), got {e.pos}"
|
|
assert e.rotation == 90.0, f"Expected rotation=90, got {e.rotation}"
|
|
assert e.scale == 2.0, f"Expected scale=2.0, got {e.scale}"
|
|
assert e.visible == False, f"Expected visible=False, got {e.visible}"
|
|
assert e.color.r == 255, f"Expected color.r=255, got {e.color.r}"
|
|
assert e.color.g == 0, f"Expected color.g=0, got {e.color.g}"
|
|
|
|
print("[PASS] test_entity3d_with_kwargs")
|
|
|
|
def test_entity3d_property_modification():
|
|
"""Test modifying Entity3D properties after creation"""
|
|
e = mcrfpy.Entity3D()
|
|
|
|
# Modify rotation
|
|
e.rotation = 180.0
|
|
assert e.rotation == 180.0, f"Expected rotation=180, got {e.rotation}"
|
|
|
|
# Modify scale
|
|
e.scale = 0.5
|
|
assert e.scale == 0.5, f"Expected scale=0.5, got {e.scale}"
|
|
|
|
# Modify visibility
|
|
e.visible = False
|
|
assert e.visible == False, f"Expected visible=False, got {e.visible}"
|
|
e.visible = True
|
|
assert e.visible == True, f"Expected visible=True, got {e.visible}"
|
|
|
|
# Modify color
|
|
e.color = mcrfpy.Color(0, 255, 128)
|
|
assert e.color.r == 0, f"Expected color.r=0, got {e.color.r}"
|
|
assert e.color.g == 255, f"Expected color.g=255, got {e.color.g}"
|
|
assert e.color.b == 128, f"Expected color.b=128, got {e.color.b}"
|
|
|
|
print("[PASS] test_entity3d_property_modification")
|
|
|
|
def test_entity3d_teleport():
|
|
"""Test Entity3D teleport method"""
|
|
e = mcrfpy.Entity3D(pos=(0, 0))
|
|
|
|
# Teleport to new position
|
|
e.teleport(15, 20)
|
|
|
|
assert e.pos == (15, 20), f"Expected pos=(15, 20), got {e.pos}"
|
|
assert e.grid_pos == (15, 20), f"Expected grid_pos=(15, 20), got {e.grid_pos}"
|
|
|
|
# World position should also update
|
|
wp = e.world_pos
|
|
# World position is grid * cell_size, but we don't know cell size here
|
|
# Just verify it changed from origin
|
|
assert wp[0] != 0.0 or wp[2] != 0.0, f"Expected world_pos to change, got {wp}"
|
|
|
|
print("[PASS] test_entity3d_teleport")
|
|
|
|
def test_entity3d_pos_setter():
|
|
"""Test setting position via pos property"""
|
|
e = mcrfpy.Entity3D(pos=(0, 0))
|
|
|
|
# Set position (this should trigger animated movement when in a viewport)
|
|
e.pos = (8, 12)
|
|
|
|
# The grid position should update
|
|
assert e.pos == (8, 12), f"Expected pos=(8, 12), got {e.pos}"
|
|
|
|
print("[PASS] test_entity3d_pos_setter")
|
|
|
|
def test_entity3d_repr():
|
|
"""Test Entity3D string representation"""
|
|
e = mcrfpy.Entity3D(pos=(5, 10))
|
|
e.rotation = 45.0
|
|
repr_str = repr(e)
|
|
|
|
assert "Entity3D" in repr_str, f"Expected 'Entity3D' in repr, got {repr_str}"
|
|
assert "5" in repr_str, f"Expected grid_x in repr, got {repr_str}"
|
|
assert "10" in repr_str, f"Expected grid_z in repr, got {repr_str}"
|
|
|
|
print("[PASS] test_entity3d_repr")
|
|
|
|
def test_entity3d_viewport_integration():
|
|
"""Test adding Entity3D to a Viewport3D"""
|
|
# Create viewport with navigation grid
|
|
vp = mcrfpy.Viewport3D()
|
|
vp.set_grid_size(32, 32)
|
|
|
|
# Create entity
|
|
e = mcrfpy.Entity3D(pos=(5, 5))
|
|
|
|
# Verify entity has no viewport initially
|
|
assert e.viewport is None, f"Expected viewport=None before adding, got {e.viewport}"
|
|
|
|
# Add to viewport
|
|
vp.entities.append(e)
|
|
|
|
# Verify entity count
|
|
assert len(vp.entities) == 1, f"Expected 1 entity, got {len(vp.entities)}"
|
|
|
|
# Verify entity was linked to viewport
|
|
# Note: viewport property may not be set until render cycle
|
|
# For now, just verify the entity is in the collection
|
|
retrieved = vp.entities[0]
|
|
assert retrieved.pos == (5, 5), f"Expected retrieved entity at (5, 5), got {retrieved.pos}"
|
|
|
|
print("[PASS] test_entity3d_viewport_integration")
|
|
|
|
def test_entitycollection3d_operations():
|
|
"""Test EntityCollection3D sequence operations"""
|
|
vp = mcrfpy.Viewport3D()
|
|
vp.set_grid_size(20, 20)
|
|
|
|
# Initially empty
|
|
assert len(vp.entities) == 0, f"Expected 0 entities initially, got {len(vp.entities)}"
|
|
|
|
# Add multiple entities
|
|
e1 = mcrfpy.Entity3D(pos=(1, 1))
|
|
e2 = mcrfpy.Entity3D(pos=(5, 5))
|
|
e3 = mcrfpy.Entity3D(pos=(10, 10))
|
|
|
|
vp.entities.append(e1)
|
|
vp.entities.append(e2)
|
|
vp.entities.append(e3)
|
|
|
|
assert len(vp.entities) == 3, f"Expected 3 entities, got {len(vp.entities)}"
|
|
|
|
# Access by index
|
|
assert vp.entities[0].pos == (1, 1), f"Expected entities[0] at (1,1)"
|
|
assert vp.entities[1].pos == (5, 5), f"Expected entities[1] at (5,5)"
|
|
assert vp.entities[2].pos == (10, 10), f"Expected entities[2] at (10,10)"
|
|
|
|
# Negative indexing
|
|
assert vp.entities[-1].pos == (10, 10), f"Expected entities[-1] at (10,10)"
|
|
|
|
# Contains check
|
|
assert e2 in vp.entities, "Expected e2 in entities"
|
|
|
|
# Iteration
|
|
positions = [e.pos for e in vp.entities]
|
|
assert (1, 1) in positions, "Expected (1,1) in iterated positions"
|
|
assert (5, 5) in positions, "Expected (5,5) in iterated positions"
|
|
|
|
# Remove
|
|
vp.entities.remove(e2)
|
|
assert len(vp.entities) == 2, f"Expected 2 entities after remove, got {len(vp.entities)}"
|
|
assert e2 not in vp.entities, "Expected e2 not in entities after remove"
|
|
|
|
# Clear
|
|
vp.entities.clear()
|
|
assert len(vp.entities) == 0, f"Expected 0 entities after clear, got {len(vp.entities)}"
|
|
|
|
print("[PASS] test_entitycollection3d_operations")
|
|
|
|
def test_entity3d_scene_integration():
|
|
"""Test Entity3D works when viewport is in a scene"""
|
|
scene = mcrfpy.Scene("entity3d_test")
|
|
|
|
vp = mcrfpy.Viewport3D(pos=(0, 0), size=(640, 480))
|
|
vp.set_grid_size(32, 32)
|
|
|
|
# Add viewport to scene
|
|
scene.children.append(vp)
|
|
|
|
# Add entity to viewport
|
|
e = mcrfpy.Entity3D(pos=(16, 16), rotation=45.0, color=mcrfpy.Color(0, 255, 0))
|
|
vp.entities.append(e)
|
|
|
|
# Verify everything is connected
|
|
assert len(scene.children) == 1, "Expected 1 child in scene"
|
|
|
|
viewport_from_scene = scene.children[0]
|
|
assert type(viewport_from_scene).__name__ == "Viewport3D"
|
|
assert len(viewport_from_scene.entities) == 1, "Expected 1 entity in viewport"
|
|
|
|
entity_from_vp = viewport_from_scene.entities[0]
|
|
assert entity_from_vp.pos == (16, 16), f"Expected entity at (16, 16), got {entity_from_vp.pos}"
|
|
assert entity_from_vp.rotation == 45.0, f"Expected rotation=45, got {entity_from_vp.rotation}"
|
|
|
|
print("[PASS] test_entity3d_scene_integration")
|
|
|
|
def test_entity3d_multiple_entities():
|
|
"""Test multiple entities in a viewport"""
|
|
vp = mcrfpy.Viewport3D()
|
|
vp.set_grid_size(50, 50)
|
|
|
|
# Create a grid of entities
|
|
entities = []
|
|
for x in range(0, 50, 10):
|
|
for z in range(0, 50, 10):
|
|
e = mcrfpy.Entity3D(pos=(x, z))
|
|
e.color = mcrfpy.Color(x * 5, z * 5, 128)
|
|
entities.append(e)
|
|
vp.entities.append(e)
|
|
|
|
expected_count = 5 * 5 # 0, 10, 20, 30, 40 for both x and z
|
|
assert len(vp.entities) == expected_count, f"Expected {expected_count} entities, got {len(vp.entities)}"
|
|
|
|
# Verify we can access all entities
|
|
found_positions = set()
|
|
for e in vp.entities:
|
|
found_positions.add(e.pos)
|
|
|
|
assert len(found_positions) == expected_count, f"Expected {expected_count} unique positions"
|
|
|
|
print("[PASS] test_entity3d_multiple_entities")
|
|
|
|
def run_all_tests():
|
|
"""Run all Entity3D tests"""
|
|
tests = [
|
|
test_entity3d_creation,
|
|
test_entity3d_with_pos,
|
|
test_entity3d_with_kwargs,
|
|
test_entity3d_property_modification,
|
|
test_entity3d_teleport,
|
|
test_entity3d_pos_setter,
|
|
test_entity3d_repr,
|
|
test_entity3d_viewport_integration,
|
|
test_entitycollection3d_operations,
|
|
test_entity3d_scene_integration,
|
|
test_entity3d_multiple_entities,
|
|
]
|
|
|
|
passed = 0
|
|
failed = 0
|
|
|
|
for test in tests:
|
|
try:
|
|
test()
|
|
passed += 1
|
|
except AssertionError as e:
|
|
print(f"[FAIL] {test.__name__}: {e}")
|
|
failed += 1
|
|
except Exception as e:
|
|
print(f"[ERROR] {test.__name__}: {type(e).__name__}: {e}")
|
|
failed += 1
|
|
|
|
print(f"\n=== Results: {passed} passed, {failed} failed ===")
|
|
return failed == 0
|
|
|
|
if __name__ == "__main__":
|
|
success = run_all_tests()
|
|
sys.exit(0 if success else 1)
|