feat: add double-barrel shotgun weapon, player movement state machine, and procedural sound assets
This commit is contained in:
+149
-1
@@ -113,4 +113,152 @@ for i in range(len(reload_samples)):
|
||||
|
||||
write_wav('assets/sounds/shotgun_reload.wav', reload_samples)
|
||||
|
||||
print("Generated shotgun sounds!")
|
||||
# 3. Footstep Sound (Quiet Thud + Scrape)
|
||||
footstep_duration = 0.15
|
||||
footstep_samples = []
|
||||
for i in range(int(sample_rate * footstep_duration)):
|
||||
t = i / sample_rate
|
||||
noise = random.uniform(-1.0, 1.0)
|
||||
# Dull Thud (lower frequency, less metallic)
|
||||
thud_env = math.exp(-t * 25.0)
|
||||
thud = math.sin(t * 50.0 * 2 * math.pi) * thud_env * 0.15
|
||||
# Scrape (very quiet, low-passed)
|
||||
scrape_env = math.exp(-t * 50.0)
|
||||
scrape = noise * scrape_env * 0.03
|
||||
footstep_samples.append(thud + scrape)
|
||||
|
||||
# Filter footstep to ensure no tin-can high frequencies
|
||||
prev = 0.0
|
||||
for i in range(len(footstep_samples)):
|
||||
prev = prev + 0.3 * (footstep_samples[i] - prev)
|
||||
footstep_samples[i] = prev
|
||||
|
||||
write_wav('assets/sounds/footstep.wav', footstep_samples)
|
||||
|
||||
# 4. Dash Sound (Whoosh)
|
||||
dash_duration = 0.5
|
||||
dash_samples = []
|
||||
prev_dash = 0.0
|
||||
for i in range(int(sample_rate * dash_duration)):
|
||||
t = i / sample_rate
|
||||
noise = random.uniform(-1.0, 1.0)
|
||||
env = math.sin(t * math.pi / dash_duration) ** 2 # Smooth bell curve
|
||||
|
||||
alpha = 0.1
|
||||
filtered = prev_dash + alpha * (noise - prev_dash)
|
||||
prev_dash = filtered
|
||||
|
||||
dash_samples.append(filtered * env * 0.8)
|
||||
write_wav('assets/sounds/dash.wav', dash_samples)
|
||||
|
||||
# 5. Hit Confirm (Tink/Chirp)
|
||||
hit_duration = 0.2
|
||||
hit_samples = []
|
||||
for i in range(int(sample_rate * hit_duration)):
|
||||
t = i / sample_rate
|
||||
env = math.exp(-t * 30.0)
|
||||
# High pitch chirp sweeping slightly
|
||||
freq = 2000.0 + math.exp(-t * 20.0) * 1000.0
|
||||
tink = math.sin(t * freq * 2 * math.pi) * env * 0.3
|
||||
hit_samples.append(tink)
|
||||
write_wav('assets/sounds/hit_confirm.wav', hit_samples)
|
||||
|
||||
# 6. Wallrun (Continuous scrape)
|
||||
# We want this to seamlessly loop
|
||||
wallrun_duration = 1.0
|
||||
wallrun_samples = []
|
||||
for i in range(int(sample_rate * wallrun_duration)):
|
||||
t = i / sample_rate
|
||||
noise = random.uniform(-1.0, 1.0)
|
||||
# Give it a slight 4/4 rhythm
|
||||
rhythm = 0.8 + 0.2 * math.sin(t * 8.0 * math.pi)
|
||||
|
||||
# Low pass to keep it as a dull scrape
|
||||
alpha = 0.05
|
||||
sample = noise * alpha * rhythm * 0.4
|
||||
wallrun_samples.append(sample)
|
||||
write_wav('assets/sounds/wallrun.wav', wallrun_samples)
|
||||
|
||||
# 7. Slide (Continuous deep friction)
|
||||
slide_duration = 1.0
|
||||
slide_samples = []
|
||||
for i in range(int(sample_rate * slide_duration)):
|
||||
noise = random.uniform(-1.0, 1.0)
|
||||
# Deeper, steadier scrape than wallrun
|
||||
alpha = 0.02
|
||||
sample = noise * alpha * 0.5
|
||||
slide_samples.append(sample)
|
||||
write_wav('assets/sounds/slide.wav', slide_samples)
|
||||
|
||||
# 8. Wind (Subtle rushing air)
|
||||
wind_duration = 2.0 # Generate 2 seconds
|
||||
sample_count = int(sample_rate * wind_duration)
|
||||
raw_wind = []
|
||||
prev_wind = 0.0
|
||||
|
||||
# Generate extra long to stabilize filter
|
||||
for i in range(sample_count + int(sample_rate * 0.5)):
|
||||
noise = random.uniform(-1.0, 1.0)
|
||||
alpha = 0.015
|
||||
filtered = prev_wind + alpha * (noise - prev_wind)
|
||||
prev_wind = filtered
|
||||
if i >= int(sample_rate * 0.5):
|
||||
raw_wind.append(filtered * 0.5)
|
||||
|
||||
# Crossfade the last 0.1s into the first 0.1s to make it perfectly loop
|
||||
crossfade_samples = int(sample_rate * 0.1)
|
||||
loop_wind = raw_wind[:-crossfade_samples] # remove the tail
|
||||
|
||||
for i in range(crossfade_samples):
|
||||
# Blend the tail into the start
|
||||
tail_sample = raw_wind[-(crossfade_samples - i)]
|
||||
start_sample = loop_wind[i]
|
||||
t = i / float(crossfade_samples)
|
||||
loop_wind[i] = start_sample * t + tail_sample * (1.0 - t)
|
||||
|
||||
write_wav('assets/sounds/wind.wav', loop_wind)
|
||||
|
||||
# 9. Jump Sound (Quick exertion / push)
|
||||
jump_duration = 0.2
|
||||
jump_samples = []
|
||||
for i in range(int(sample_rate * jump_duration)):
|
||||
t = i / sample_rate
|
||||
noise = random.uniform(-1.0, 1.0)
|
||||
# Lower frequency push (less tin can)
|
||||
push_env = math.exp(-t * 25.0)
|
||||
push = math.sin(t * 60.0 * 2 * math.pi) * push_env * 0.3
|
||||
# High frequency clothing ruffle (quieter)
|
||||
ruffle_env = math.exp(-t * 30.0)
|
||||
ruffle = noise * ruffle_env * 0.05
|
||||
jump_samples.append(push + ruffle)
|
||||
|
||||
# Filter jump to ensure no tin-can high frequencies
|
||||
prev = 0.0
|
||||
for i in range(len(jump_samples)):
|
||||
prev = prev + 0.4 * (jump_samples[i] - prev)
|
||||
jump_samples[i] = prev
|
||||
|
||||
write_wav('assets/sounds/jump.wav', jump_samples)
|
||||
|
||||
# 10. Double Jump Sound (Airy, cloudy whoosh)
|
||||
dj_duration = 0.4
|
||||
dj_samples = []
|
||||
prev_dj = 0.0
|
||||
for i in range(int(sample_rate * dj_duration)):
|
||||
t = i / sample_rate
|
||||
noise = random.uniform(-1.0, 1.0)
|
||||
# Airy filter
|
||||
alpha = 0.05
|
||||
filtered = prev_dj + alpha * (noise - prev_dj)
|
||||
prev_dj = filtered
|
||||
|
||||
# Envelope: soft attack, long decay
|
||||
env = (math.exp(-t * 8.0) - math.exp(-t * 40.0)) * 1.5
|
||||
|
||||
# Slight pitch movement to give it a "lifting" feel
|
||||
lift = math.sin(t * 150.0 * 2 * math.pi * (1.0 + t)) * env * 0.1
|
||||
|
||||
dj_samples.append((filtered * 0.4 + lift) * env)
|
||||
write_wav('assets/sounds/double_jump.wav', dj_samples)
|
||||
|
||||
print("Generated all sounds!")
|
||||
|
||||
Reference in New Issue
Block a user