better basic example
This commit is contained in:
1 parent
1530b74d04
commit
934067f154
9 files changed
+129
-11
No files matched your search
@@ -0,0 +1,69 @@
|
||||
"""Generate the floor texture and music used by exercises/basics.py (no licensed sources)."""
|
||||
import array
|
||||
import binascii
|
||||
import math
|
||||
from pathlib import Path
|
||||
import random
|
||||
import struct
|
||||
import wave
|
||||
import zlib
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
|
||||
|
||||
def save_png(path, size, pixels):
|
||||
def chunk(kind, data):
|
||||
return struct.pack(">I", len(data)) + kind + data + struct.pack(">I", binascii.crc32(kind + data) & 0xffffffff)
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.write_bytes(b"\x89PNG\r\n\x1a\n" +
|
||||
chunk(b"IHDR", struct.pack(">IIBBBBB", size, size, 8, 2, 0, 0, 0)) +
|
||||
chunk(b"IDAT", zlib.compress(pixels, 9)) + chunk(b"IEND", b""))
|
||||
|
||||
|
||||
def floor_tiles(path, size=512, tiles=4, grout=5):
|
||||
"""Slate tiles that repeat seamlessly: 4x4 in one texture, each with its own shade."""
|
||||
rng = random.Random(7)
|
||||
step = size // tiles
|
||||
shades = [[rng.uniform(0.75, 1.15) for _ in range(tiles)] for _ in range(tiles)]
|
||||
pixels = bytearray()
|
||||
for y in range(size):
|
||||
pixels.append(0)
|
||||
for x in range(size):
|
||||
if x % step < grout or y % step < grout:
|
||||
pixels += bytes((24, 24, 26))
|
||||
else:
|
||||
shade = shades[y // step][x // step] * rng.uniform(0.94, 1.06)
|
||||
pixels += bytes(min(255, int(value * shade)) for value in (92, 100, 112))
|
||||
save_png(path, size, bytes(pixels))
|
||||
|
||||
|
||||
def music(path, seconds=8.0, rate=44100):
|
||||
"""Minor-key pad, bass and arpeggio: two bars at 120 BPM, fading out at the end."""
|
||||
chords = [(220.00, 261.63, 329.63), (174.61, 220.00, 261.63),
|
||||
(261.63, 329.63, 392.00), (196.00, 246.94, 293.66)]
|
||||
beat = 0.5
|
||||
samples = array.array("h")
|
||||
for index in range(int(seconds * rate)):
|
||||
time = index / rate
|
||||
chord = chords[int(time / (beat * 4)) % len(chords)]
|
||||
pad = sum(math.sin(2 * math.pi * frequency * time) for frequency in chord) / 3
|
||||
bass = math.sin(2 * math.pi * chord[0] / 2 * time)
|
||||
step = int(time / (beat / 2))
|
||||
note = chord[step % 3] * 2
|
||||
arpeggio = math.sin(2 * math.pi * note * time) * math.exp(-6 * (time - step * beat / 2))
|
||||
kick_time = time % beat if int(time / beat) % 2 == 0 else 1.0
|
||||
kick = math.sin(2 * math.pi * 60 * kick_time) * math.exp(-18 * kick_time)
|
||||
fade = min(1.0, time / 0.3, (seconds - time) / 1.0)
|
||||
value = 0.28 * pad + 0.22 * bass + 0.2 * arpeggio + 0.3 * kick
|
||||
samples.append(int(32767 * 0.8 * fade * max(-1.0, min(1.0, value))))
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
with wave.open(str(path), "wb") as target:
|
||||
target.setnchannels(1)
|
||||
target.setsampwidth(2)
|
||||
target.setframerate(rate)
|
||||
target.writeframes(samples.tobytes())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
floor_tiles(ROOT / "source_assets/textures/floor_tiles.png")
|
||||
music(ROOT / "source_assets/audio/basics_music.wav")
|
||||
Reference in new issue
Block a user