Improve level-up animation and unit audio assets

This commit is contained in:
2026-06-24 15:23:26 +09:00
parent 44c017ab6c
commit 384ce7725c
8 changed files with 308 additions and 54 deletions

78
scripts/generate-sfx.mjs Normal file
View File

@@ -0,0 +1,78 @@
import { mkdir, writeFile } from 'node:fs/promises';
import { dirname, join } from 'node:path';
const sampleRate = 44100;
const outputPath = join('src', 'assets', 'audio', 'sfx', 'level-up.wav');
function envelope(time, start, duration) {
const local = time - start;
if (local < 0 || local > duration) {
return 0;
}
const attack = 0.018;
const release = 0.22;
if (local < attack) {
return local / attack;
}
if (local > duration - release) {
return Math.max(0, (duration - local) / release);
}
return 1;
}
function tone(time, frequency, start, duration, gain, wave = 'sine') {
const amp = envelope(time, start, duration) * gain;
if (amp <= 0) {
return 0;
}
const phase = Math.PI * 2 * frequency * (time - start);
if (wave === 'triangle') {
return amp * (2 / Math.PI) * Math.asin(Math.sin(phase));
}
return amp * Math.sin(phase);
}
function sampleAt(time) {
const notes = [
{ start: 0, frequency: 523.25, gain: 0.22, duration: 0.52 },
{ start: 0.09, frequency: 659.25, gain: 0.2, duration: 0.56 },
{ start: 0.18, frequency: 783.99, gain: 0.18, duration: 0.62 },
{ start: 0.31, frequency: 1046.5, gain: 0.16, duration: 0.7 }
];
const chord = notes.reduce((sum, note) => sum + tone(time, note.frequency, note.start, note.duration, note.gain), 0);
const shimmer =
tone(time, 1318.51, 0.42, 0.36, 0.055, 'triangle') +
tone(time, 1567.98, 0.52, 0.28, 0.042, 'triangle');
return Math.max(-0.92, Math.min(0.92, chord + shimmer));
}
function wavBuffer(samples) {
const bytesPerSample = 2;
const dataSize = samples.length * bytesPerSample;
const buffer = Buffer.alloc(44 + dataSize);
buffer.write('RIFF', 0);
buffer.writeUInt32LE(36 + dataSize, 4);
buffer.write('WAVE', 8);
buffer.write('fmt ', 12);
buffer.writeUInt32LE(16, 16);
buffer.writeUInt16LE(1, 20);
buffer.writeUInt16LE(1, 22);
buffer.writeUInt32LE(sampleRate, 24);
buffer.writeUInt32LE(sampleRate * bytesPerSample, 28);
buffer.writeUInt16LE(bytesPerSample, 32);
buffer.writeUInt16LE(16, 34);
buffer.write('data', 36);
buffer.writeUInt32LE(dataSize, 40);
samples.forEach((sample, index) => {
buffer.writeInt16LE(Math.round(sample * 32767), 44 + index * bytesPerSample);
});
return buffer;
}
await mkdir(dirname(outputPath), { recursive: true });
const duration = 1.12;
const samples = Array.from({ length: Math.floor(sampleRate * duration) }, (_, index) => sampleAt(index / sampleRate));
await writeFile(outputPath, wavBuffer(samples));
console.log(`Generated ${outputPath}`);