McRogueFace/tests/integration/3d_full_test.py

286 lines
8.3 KiB
Python
Raw Normal View History

2026-02-09 08:15:18 -05:00
# 3d_full_test.py - Integration tests for complete 3D system
# Tests all 3D features working together
import mcrfpy
import sys
def test_viewport_creation():
"""Test Viewport3D creation and basic properties"""
viewport = mcrfpy.Viewport3D(
pos=(0, 0),
size=(800, 600),
render_resolution=(320, 240),
fov=60.0,
camera_pos=(10.0, 10.0, 10.0),
camera_target=(0.0, 0.0, 0.0)
)
assert viewport.w == 800, f"Width mismatch: {viewport.w}"
assert viewport.h == 600, f"Height mismatch: {viewport.h}"
assert viewport.fov == 60.0, f"FOV mismatch: {viewport.fov}"
print("[PASS] test_viewport_creation")
return viewport
def test_navigation_grid(viewport):
"""Test navigation grid setup"""
viewport.set_grid_size(16, 16)
assert viewport.grid_size == (16, 16), f"Grid size mismatch: {viewport.grid_size}"
# Test cell access
cell = viewport.at(5, 5)
assert cell is not None, "Cell access failed"
assert cell.walkable == True, "Default cell should be walkable"
# Test setting cell properties
cell.walkable = False
cell2 = viewport.at(5, 5)
assert cell2.walkable == False, "Cell walkable not persisted"
cell.walkable = True # Reset
print("[PASS] test_navigation_grid")
def test_heightmap_and_terrain(viewport):
"""Test heightmap and terrain generation"""
hm = mcrfpy.HeightMap((16, 16))
hm.mid_point_displacement(roughness=0.4)
hm.normalize(0.0, 1.0)
# Check heightmap values are in range
for x in range(16):
for z in range(16):
h = hm[x, z]
assert 0.0 <= h <= 1.0, f"Height out of range at ({x},{z}): {h}"
# Build terrain
vertex_count = viewport.build_terrain(
layer_name="terrain",
heightmap=hm,
y_scale=2.0,
cell_size=1.0
)
assert vertex_count > 0, "No vertices generated"
# Apply heightmap to navigation
viewport.apply_heightmap(hm, 2.0)
print("[PASS] test_heightmap_and_terrain")
def test_terrain_colors(viewport):
"""Test terrain color application"""
r_map = mcrfpy.HeightMap((16, 16))
g_map = mcrfpy.HeightMap((16, 16))
b_map = mcrfpy.HeightMap((16, 16))
# Set all green
for x in range(16):
for z in range(16):
r_map[x, z] = 0.2
g_map[x, z] = 0.5
b_map[x, z] = 0.2
viewport.apply_terrain_colors("terrain", r_map, g_map, b_map)
print("[PASS] test_terrain_colors")
def test_entity_creation(viewport):
"""Test Entity3D creation and properties"""
entity = mcrfpy.Entity3D(pos=(8, 8), scale=1.0, color=mcrfpy.Color(255, 100, 50))
viewport.entities.append(entity)
assert entity.pos == (8, 8), f"Position mismatch: {entity.pos}"
assert entity.scale == 1.0, f"Scale mismatch: {entity.scale}"
assert entity.is_moving == False, "New entity should not be moving"
print("[PASS] test_entity_creation")
return entity
def test_pathfinding(viewport, entity):
"""Test A* pathfinding"""
# Find path to another location
path = entity.path_to(12, 12)
assert isinstance(path, list), "path_to should return list"
# Path may be empty if blocked, but should not error
if path:
assert len(path) > 0, "Path should have steps"
# First step should be adjacent to start or the start itself
# Test find_path on viewport
vp_path = viewport.find_path((8, 8), (12, 12))
assert isinstance(vp_path, list), "viewport.find_path should return list"
print("[PASS] test_pathfinding")
return path
def test_entity_movement(entity, path):
"""Test Entity3D movement via follow_path"""
if not path:
print("[SKIP] test_entity_movement - no path available")
return
# Test follow_path
entity.follow_path(path[:3]) # Just first 3 steps
# After queueing moves, entity should be moving
assert entity.is_moving == True, "Entity should be moving after follow_path"
# Test clear_path
entity.clear_path()
print("[PASS] test_entity_movement")
def test_fov_computation(viewport):
"""Test field of view computation"""
visible = viewport.compute_fov((8, 8), radius=5)
assert isinstance(visible, list), "compute_fov should return list"
assert len(visible) > 0, "FOV should see some cells"
# Origin should be visible
origin_visible = (8, 8) in [(c[0], c[1]) for c in visible]
assert origin_visible, "Origin should be in FOV"
# Test is_in_fov
assert viewport.is_in_fov(8, 8) == True, "Origin should be in FOV"
print("[PASS] test_fov_computation")
def test_screen_to_world(viewport):
"""Test screen-to-world ray casting"""
# Test center of viewport
result = viewport.screen_to_world(160, 120) # Half of 320x240 render resolution
# May return None if ray misses ground
if result is not None:
assert len(result) == 3, "Should return (x, y, z)"
assert result[1] == 0.0, "Y should be 0 (ground plane)"
print("[PASS] test_screen_to_world")
def test_camera_follow(viewport, entity):
"""Test camera follow method"""
original_pos = viewport.camera_pos
viewport.follow(entity, distance=10.0, height=5.0)
new_pos = viewport.camera_pos
# Camera should have moved
# (Position may or may not change significantly depending on entity location)
print("[PASS] test_camera_follow")
def test_layer_management(viewport):
"""Test mesh layer management"""
# Add layer
layer = viewport.add_layer("test_layer", z_index=5)
assert layer is not None, "add_layer should return layer dict"
# Get layer
layer2 = viewport.get_layer("test_layer")
assert layer2 is not None, "get_layer should find layer"
# Layer count
count = viewport.layer_count()
assert count >= 1, "Should have at least 1 layer"
# Remove layer
removed = viewport.remove_layer("test_layer")
assert removed == True, "remove_layer should return True"
# Verify removed
layer3 = viewport.get_layer("test_layer")
assert layer3 is None, "Layer should be removed"
print("[PASS] test_layer_management")
def test_threshold_and_slope(viewport):
"""Test walkability threshold and slope cost"""
hm = mcrfpy.HeightMap((16, 16))
hm.normalize(0.0, 1.0)
# Apply threshold - mark low areas unwalkable
viewport.apply_threshold(hm, 0.0, 0.2, False)
# Set slope cost
viewport.set_slope_cost(0.5, 2.0)
print("[PASS] test_threshold_and_slope")
def test_place_blocking(viewport):
"""Test place_blocking for marking cells"""
# Mark a 2x2 area as blocking
viewport.place_blocking((10, 10), (2, 2), walkable=False, transparent=False)
# Verify cells are blocked
cell = viewport.at(10, 10)
assert cell.walkable == False, "Cell should be unwalkable after place_blocking"
print("[PASS] test_place_blocking")
def run_all_tests():
"""Run all integration tests"""
print("=" * 60)
print("3D Full Integration Test Suite")
print("=" * 60)
passed = 0
failed = 0
try:
viewport = test_viewport_creation()
passed += 1
except Exception as e:
print(f"[FAIL] test_viewport_creation: {e}")
failed += 1
return
tests = [
lambda: test_navigation_grid(viewport),
lambda: test_heightmap_and_terrain(viewport),
lambda: test_terrain_colors(viewport),
lambda: test_layer_management(viewport),
lambda: test_threshold_and_slope(viewport),
lambda: test_place_blocking(viewport),
lambda: test_fov_computation(viewport),
lambda: test_screen_to_world(viewport),
]
for test in tests:
try:
test()
passed += 1
except Exception as e:
print(f"[FAIL] {test.__name__ if hasattr(test, '__name__') else 'test'}: {e}")
failed += 1
# Entity tests
try:
entity = test_entity_creation(viewport)
passed += 1
path = test_pathfinding(viewport, entity)
passed += 1
test_entity_movement(entity, path)
passed += 1
test_camera_follow(viewport, entity)
passed += 1
except Exception as e:
print(f"[FAIL] Entity tests: {e}")
failed += 1
print("=" * 60)
print(f"Results: {passed} passed, {failed} failed")
print("=" * 60)
return failed == 0
# Run tests
if __name__ == "__main__":
success = run_all_tests()
sys.exit(0 if success else 1)