#!/usr/bin/env python3 # complete_fixed_demo.py - Fixed with PyGame init and animation import os import pygame import numpy as np import time import threading from flask import Flask, Response # ===== CRITICAL FIXES ===== os.environ['SDL_VIDEODRIVER'] = 'dummy' os.environ['PYGAME_HIDE_SUPPORT_PROMPT'] = '1' PORT = int(os.getenv('PORT', 7860)) WIDTH, HEIGHT = 800, 600 app = Flask(__name__) # Shared state frame_data = { "pixels": None, "frame_id": 0, "lock": threading.Lock() } @app.route('/') def index(): return ''' Complete Demo

⚡ Complete Demo

Mode: Loading...
''' @app.route('/pygame_frame') def pygame_frame(): """PyGame animation endpoint""" with frame_data["lock"]: if frame_data["pixels"] is not None: return Response( frame_data["pixels"].tobytes(), mimetype='application/octet-stream', headers={'Cache-Control': 'no-cache'} ) # Fallback black = np.zeros((HEIGHT, WIDTH, 3), dtype=np.uint8).tobytes() return Response(black, mimetype='application/octet-stream') def pygame_animation(): """PyGame animation with proper initialization""" print("🎬 Starting PyGame animation...") try: # ===== FIX 1: Proper PyGame initialization ===== pygame.init() # Initialize display (CRITICAL for headless) pygame.display.init() pygame.display.set_mode((1, 1), pygame.HIDDEN) # Hidden window print("✅ PyGame display initialized") # Create surface surface = pygame.Surface((WIDTH, HEIGHT)) print(f"✅ Surface created: {WIDTH}x{HEIGHT}") except Exception as e: print(f"❌ PyGame init failed: {e}") import traceback traceback.print_exc() return # ===== FIX 2: Animated objects ===== particles = [] for _ in range(100): particles.append({ 'x': np.random.randint(0, WIDTH), 'y': np.random.randint(0, HEIGHT), 'dx': np.random.uniform(-3, 3), 'dy': np.random.uniform(-3, 3), 'size': np.random.randint(2, 10), 'color': ( np.random.randint(50, 255), np.random.randint(50, 255), np.random.randint(50, 255) ), 'life': np.random.randint(100, 300), 'type': np.random.choice(['circle', 'square', 'triangle']) }) # Rotating geometric shapes shapes = [] for i in range(8): shapes.append({ 'angle': i * np.pi / 4, 'radius': 100 + i * 20, 'speed': 0.5 + i * 0.1, 'size': 15 + i * 5, 'color': ( (i * 32) % 256, (i * 64) % 256, (i * 96) % 256 ) }) print(f"✅ Created {len(particles)} particles and {len(shapes)} shapes") frame_id = 0 start_time = time.time() while True: frame_start = time.time() # ===== FIX 3: Time-based animation ===== elapsed = time.time() - start_time # Clear with gradient for y in range(HEIGHT): color = int(20 + y / HEIGHT * 30) pygame.draw.line(surface, (color, color, color + 20), (0, y), (WIDTH, y)) # Draw rotating shapes for shape in shapes: shape['angle'] += shape['speed'] * 0.05 x = WIDTH // 2 + np.cos(shape['angle']) * shape['radius'] y = HEIGHT // 2 + np.sin(shape['angle']) * shape['radius'] # Draw shape if np.random.random() < 0.3: # 30% chance of triangle points = [ (x, y - shape['size']), (x - shape['size'], y + shape['size']), (x + shape['size'], y + shape['size']) ] pygame.draw.polygon(surface, shape['color'], points) else: pygame.draw.circle(surface, shape['color'], (int(x), int(y)), shape['size']) # Connect shapes with lines pygame.draw.circle(surface, (255, 255, 255, 100), (int(x), int(y)), shape['size'], 2) # Update and draw particles for p in particles: p['x'] += p['dx'] p['y'] += p['dy'] p['life'] -= 1 # Bounce or respawn if (p['x'] < 0 or p['x'] > WIDTH or p['y'] < 0 or p['y'] > HEIGHT or p['life'] <= 0): p['x'] = np.random.randint(0, WIDTH) p['y'] = np.random.randint(0, HEIGHT) p['dx'] = np.random.uniform(-3, 3) p['dy'] = np.random.uniform(-3, 3) p['life'] = np.random.randint(100, 300) p['color'] = ( np.random.randint(50, 255), np.random.randint(50, 255), np.random.randint(50, 255) ) # Draw particle with trail for i in range(3): trail_x = p['x'] - p['dx'] * i * 0.3 trail_y = p['y'] - p['dy'] * i * 0.3 trail_size = p['size'] * (1 - i * 0.3) trail_alpha = 200 - i * 60 pygame.draw.circle( surface, (*p['color'], trail_alpha), (int(trail_x), int(trail_y)), int(trail_size) ) # Add frame info font = pygame.font.Font(None, 28) info = [ f"Frame: {frame_id}", f"Time: {elapsed:.1f}s", f"FPS: {int(1/(time.time()-frame_start)) if frame_id>0 else 0}", f"Particles: {len(particles)}" ] for i, text in enumerate(info): text_surface = font.render(text, True, (255, 255, 200)) surface.blit(text_surface, (10, 10 + i * 30)) # Convert to NumPy array pixels = pygame.surfarray.pixels3d(surface) # Update shared memory with frame_data["lock"]: frame_data["pixels"] = pixels.copy() frame_data["frame_id"] = frame_id frame_id += 1 # Log every 30 frames if frame_id % 30 == 0: current_fps = 1 / (time.time() - frame_start) if frame_id > 0 else 0 print(f"📊 Frame {frame_id} | FPS: {current_fps:.1f}") # ===== FIX 4: Frame rate control ===== frame_time = time.time() - frame_start target_time = 1/30 # 30 FPS if frame_time < target_time: time.sleep(target_time - frame_time) # Start PyGame thread threading.Thread(target=pygame_animation, daemon=True).start() # Wait for initialization print("⏳ Waiting for PyGame to start...") time.sleep(3) print("🌐 Starting Flask server...") print(f"📡 Port: {PORT}") print("="*60) if __name__ == "__main__": app.run(host='0.0.0.0', port=PORT, threaded=True, use_reloader=False)