Skip to content

Instantly share code, notes, and snippets.

@DanielHabib
Created September 2, 2025 01:31
Show Gist options
  • Select an option

  • Save DanielHabib/bfebb1dc3a264942ad6235e61a416410 to your computer and use it in GitHub Desktop.

Select an option

Save DanielHabib/bfebb1dc3a264942ad6235e61a416410 to your computer and use it in GitHub Desktop.
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