feat(viewport): complete viewport-based rendering system (#8)

Implements a comprehensive viewport system that allows fixed game resolution
with flexible window scaling, addressing the primary wishes for issues #34, #49, and #8.

Key Features:
- Fixed game resolution independent of window size (window.game_resolution property)
- Three scaling modes accessible via window.scaling_mode:
  - "center": 1:1 pixels, viewport centered in window
  - "stretch": viewport fills window, ignores aspect ratio
  - "fit": maintains aspect ratio with black bars
- Automatic window-to-game coordinate transformation for mouse input
- Full Python API integration with PyWindow properties

Technical Implementation:
- GameEngine::ViewportMode enum with Center, Stretch, Fit modes
- SFML View system for efficient GPU-based viewport scaling
- updateViewport() recalculates on window resize or mode change
- windowToGameCoords() transforms mouse coordinates correctly
- PyScene mouse input automatically uses transformed coordinates

Tests:
- test_viewport_simple.py: Basic API functionality
- test_viewport_visual.py: Visual verification with screenshots
- test_viewport_scaling.py: Interactive mode switching and resizing

This completes the viewport-based rendering task and provides the foundation
for resolution-independent game development as requested for Crypt of Sokoban.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
John McCardle 2025-07-07 10:28:50 -04:00
commit 5a49cb7b6d
9 changed files with 626 additions and 12 deletions

View file

@ -0,0 +1,32 @@
#!/usr/bin/env python3
"""Simple viewport test"""
import mcrfpy
from mcrfpy import Window
import sys
print("Testing viewport system...")
# Get window singleton
window = Window.get()
print(f"Game resolution: {window.game_resolution}")
print(f"Scaling mode: {window.scaling_mode}")
print(f"Window resolution: {window.resolution}")
# Test changing scaling mode
window.scaling_mode = "center"
print(f"Changed to center mode: {window.scaling_mode}")
window.scaling_mode = "stretch"
print(f"Changed to stretch mode: {window.scaling_mode}")
window.scaling_mode = "fit"
print(f"Changed to fit mode: {window.scaling_mode}")
# Test changing game resolution
window.game_resolution = (800, 600)
print(f"Changed game resolution to: {window.game_resolution}")
print("Test completed!")
sys.exit(0)