"""Offline normalization and sound design; none of this runs inside the game.""" from pathlib import Path import math import random import struct import wave from PIL import Image ROOT = Path(__file__).resolve().parents[2] def sound(name,seconds,style): rate = 22050 rng = random.Random(713+style) samples = [] previous = 0.0 low = 0.0 for i in range(int(rate*seconds)): t = i/rate noise = rng.uniform(-1,1) low = low*.72+noise*.28 high = noise-previous previous = noise envelope = min(1,t/.012)*min(1,(seconds-t)/.04) if style==0: value = (high*.16+low*.22)*(0.65+0.35*math.sin(t*79)**2) elif style==1: value = low*.22+high*.08 envelope *= math.sin(math.pi*t/seconds)**.7 else: value = 0.0 for offset in (0,.065,.135,.23): age = t-offset if age>=0: value += (math.sin(age*math.tau*1760)+math.sin(age*math.tau*2410)*.4)*math.exp(-age*34)*.15 value += high*.04*math.exp(-t*12) samples.append(max(-32767,min(32767,round(value*envelope*20000)))) path = ROOT/"assets/audio/generated"/name with wave.open(str(path),"wb") as out: out.setparams((1,2,rate,0,"NONE","not compressed")) out.writeframes(struct.pack(f"<{len(samples)}h",*samples)) def main(): image = Image.open(ROOT/"assets/sprites/scratch/payout-chips-v1.png").convert("RGBA") alpha = image.getchannel("A").point(lambda a:255 if a>=32 else 0) image = image.crop(alpha.getbbox()) image.thumbnail((96,72),Image.Resampling.LANCZOS) canvas = Image.new("RGBA",(96,72)) canvas.paste(image,((96-image.width)//2,72-image.height)) canvas.putalpha(canvas.getchannel("A").point(lambda a:255 if a>=128 else 0)) raw = canvas.tobytes("raw","BGRA") (ROOT/"assets/animations/scratch/payout-chips-v1.bin").write_bytes(struct.pack("<4s4I",b"ANM1",96,72,1,len(raw))+raw) canvas.save(ROOT/"build/scratch/payout-chips-packed.png") sound("scratch-scrape.wav",.155,0) sound("scratch-paper.wav",.42,1) sound("scratch-payout.wav",.48,2) print("Packed grounded 96x72 payout sprite and three short original scratch/paper/payout sounds") if __name__=="__main__": main()