-
-
Save DanielHabib/bfebb1dc3a264942ad6235e61a416410 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| from spatialstudio import splv | |
| import math | |
| import time | |
| import random | |
| def create_matrix_rain(): | |
| """ | |
| Create a pure Matrix-style digital rain effect with green characters | |
| cascading down in 3D space - just like the iconic movie effect! | |
| """ | |
| # Video parameters - wider and shallower | |
| W, H, D = 400, 256, 64 | |
| framerate = 30.0 | |
| total_duration = 30.0 # 30 seconds of pure Matrix rain | |
| total_frames = int(total_duration * framerate) | |
| encoder = splv.Encoder( | |
| W, H, D, | |
| framerate=framerate, | |
| outputPath="matrix_rain.splv" | |
| ) | |
| print(f"Creating Matrix rain: {total_frames} frames at {framerate} FPS") | |
| # Initialize rain columns - more columns for wider space | |
| rain_columns = initialize_rain_columns(120, W, H, D) | |
| for frame_num in range(total_frames): | |
| frame = splv.Frame(W, H, D) | |
| # Calculate time-based variables | |
| t = frame_num / framerate | |
| # Create the Matrix rain effect | |
| create_falling_characters(frame, t, rain_columns, W, H, D) | |
| # Update rain columns | |
| update_rain_columns(rain_columns, H) | |
| encoder.encode(frame) | |
| if frame_num % 90 == 0: | |
| progress = frame_num / total_frames | |
| print(f"Progress: {frame_num}/{total_frames} ({progress*100:.1f}%)") | |
| encoder.finish() | |
| print("Matrix rain completed!") | |
| def initialize_rain_columns(num_columns, W, H, D): | |
| """Initialize rain columns with random properties""" | |
| columns = [] | |
| for _ in range(num_columns): | |
| column = { | |
| 'x': random.randint(0, W - 1), | |
| 'z': random.randint(0, D - 1), | |
| 'drops': [], | |
| 'spawn_rate': random.uniform(0.1, 0.3), # Probability of spawning new drop | |
| 'last_spawn': random.uniform(0, 2.0) | |
| } | |
| # Initialize with some drops already falling | |
| num_initial_drops = random.randint(3, 8) | |
| for i in range(num_initial_drops): | |
| drop = { | |
| 'y': random.randint(0, H - 1), | |
| 'speed': random.uniform(2.0, 5.0), | |
| 'intensity': random.uniform(0.6, 1.0), | |
| 'char_offset': random.randint(0, 50), | |
| 'trail_length': random.randint(8, 15) | |
| } | |
| column['drops'].append(drop) | |
| columns.append(column) | |
| return columns | |
| def update_rain_columns(columns, H): | |
| """Update all rain columns""" | |
| for column in columns: | |
| # Update existing drops | |
| for drop in column['drops'][:]: # Copy list to avoid modification during iteration | |
| drop['y'] -= drop['speed'] | |
| # Remove drops that have fallen off screen | |
| if drop['y'] < -drop['trail_length']: | |
| column['drops'].remove(drop) | |
| # Spawn new drops occasionally | |
| if random.random() < column['spawn_rate']: | |
| new_drop = { | |
| 'y': H + random.randint(5, 20), | |
| 'speed': random.uniform(2.0, 5.0), | |
| 'intensity': random.uniform(0.6, 1.0), | |
| 'char_offset': random.randint(0, 50), | |
| 'trail_length': random.randint(8, 15) | |
| } | |
| column['drops'].append(new_drop) | |
| def create_falling_characters(frame, t, columns, W, H, D): | |
| """Create the falling Matrix characters""" | |
| # Matrix-style characters (mix of Japanese katakana, numbers, and letters) | |
| matrix_chars = [ | |
| # Numbers | |
| "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", | |
| # Letters | |
| "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", | |
| "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", | |
| # Special characters | |
| "+", "-", "*", "=", "/", "\\", "|", "_", "^", "~", ":", ";", ".", ",", | |
| # Katakana-like substitutes | |
| "7", "L", "F", "T", "Y", "U", "I", "O", "P" | |
| ] | |
| # Matrix character names and themed words | |
| matrix_words = [ | |
| "NEO", "TRINITY", "MORPHEUS", "AGENT", "SMITH", "ORACLE", "ZION", | |
| "MATRIX", "REALITY", "DREAM", "WAKE", "UP", "PILL", "RED", "BLUE", | |
| "CODE", "SYSTEM", "PROGRAM", "VIRUS", "HUMAN", "MACHINE", "CHOICE", | |
| "BELIEVE", "TRUTH", "ILLUSION", "ESCAPE", "FREEDOM", "CONTROL", | |
| "SIMULATION", "REAL", "FAKE", "MIND", "BODY", "SOUL", "DESTINY", | |
| "PATH", "DOOR", "KEY", "LOCK", "OPEN", "CLOSE", "ENTER", "EXIT" | |
| ] | |
| for column in columns: | |
| for drop in column['drops']: | |
| # Create trail of characters | |
| for trail_pos in range(drop['trail_length']): | |
| char_y = int(drop['y'] + trail_pos * 3) | |
| if 0 <= char_y < H: | |
| # Calculate fade for trail effect | |
| trail_factor = 1.0 - (trail_pos / drop['trail_length']) | |
| intensity = int(drop['intensity'] * trail_factor * 255) | |
| # Brightest character at the head of the drop | |
| if trail_pos == 0: | |
| # Head character is brightest white/green | |
| color = (200, 255, 200) | |
| outline = (100, 200, 100) | |
| else: | |
| # Trail characters fade from bright green to dark green | |
| green_value = max(50, intensity) | |
| color = (0, green_value, 0) | |
| outline = (0, max(20, green_value // 3), 0) | |
| # Decide what type of character to show | |
| if random.random() < 0.15: # 15% chance of Matrix word/name | |
| # Show Matrix-themed words occasionally | |
| word = random.choice(matrix_words) | |
| if len(word) > trail_pos: | |
| char = word[trail_pos % len(word)] | |
| else: | |
| char = matrix_chars[(drop['char_offset'] + trail_pos + int(t * 10)) % len(matrix_chars)] | |
| elif random.random() < 0.1: # 10% chance of random character change | |
| char = matrix_chars[random.randint(0, len(matrix_chars) - 1)] | |
| else: | |
| # Normal character sequence | |
| char_index = (drop['char_offset'] + trail_pos + int(t * 10)) % len(matrix_chars) | |
| char = matrix_chars[char_index] | |
| frame.write_string( | |
| text=char, | |
| startPos=(column['x'], char_y, column['z']), | |
| voxel=color, | |
| outlineVoxel=outline, | |
| axis="z", # Changed to Z-axis so text faces the camera | |
| scale=1 | |
| ) | |
| if __name__ == "__main__": | |
| start_time = time.time() | |
| create_matrix_rain() | |
| end_time = time.time() | |
| print(f"Total generation time: {end_time - start_time:.2f} seconds") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment