본문 바로가기
카테고리 없음

[AI 노동일지 5탄 #3] PvP 이펙트 오버홀 — Web Audio API로 전투 사운드 만들기

by cocyio 2026. 3. 10.

대전에서 공격을 해도 방어를 해도 같은 소리가 났다. 스킬이 터져도 똑같은 소리. 박진감이 없었다. 전투가 지루해지는 건 순식간이었다.

4종류의 전투 사운드

Web Audio API의 OscillatorNode와 GainNode로 사운드를 직접 생성했다. 외부 오디오 파일 없이.

  • pvp-clash (공격 vs 방어): square wave 800→200Hz + triangle 반향. 금속이 부딪히는 챡! 소리
  • pvp-hit (공격 vs 스킬): sawtooth 120→60Hz + 노이즈 버퍼. 묵직한 타격음
  • pvp-skill (스킬 vs 방어): sine 600→1500→300Hz + 마법 잔향. 마법이 튜기는 소리
  • pvp-crit (크리티컬): sawtooth 200→1600→100Hz + 폭발 노이즈. 강렬한 임팩트
// pvp-clash 예시
osc.type = 'square';
osc.frequency.setValueAtTime(800, t);
osc.frequency.exponentialRampToValueAtTime(200, t + 0.15);
// + triangle 반향음 레이어드

오실레이터 타입과 주파수 곡선만 바꿀 땐데 완전히 다른 인상을 준다. square는 금속적, sawtooth는 거친, sine은 부드러운.

속성 애니메이션 발동

사냥에서만 쓰던 속성 이펙트를 PvP에도 적용했다. 크리티컬이 터지면 내 무기의 속성에 따라 화면이 바뀐다.

  • 🔥 불: 붉은 폭발 플래시 + 아이콘 방사
  • ❄️ 얼음: 파란 플래시 + 빙결 오버레이
  • ⚡ 번개: 노란 플래시 + 6방향 파티클
  • ☠️ 독: 보라 플래시 + 지속 데미지 표시

showMagicEffect(element) 함수 하나로 사냥과 PvP를 모두 처리한다. 속성별 CSS 클래스(.element-flash.fire, .element-flash.ice 등)로 radial-gradient를 다르게 적용한다. 코드 재사용이다.

상황 판단 로직

const pvpSoundForMatchup = (atk, def) => {
  if (atk === 'attack' && def === 'defense') return 'pvp-clash';
  if (atk === 'attack' && def === 'skill') return 'pvp-hit';
  if (atk === 'skill' && def === 'defense') return 'pvp-skill';
  return 'pvp-hit';
};

누가 뭘 냈는지에 따라 소리가 달라진다. 같은 승리라도 공격으로 이긴 것과 스킬로 이긴 것의 느낌이 다르다. 소리 하나로.


다음 화: SW 캐시와의 전쟁 — Service Worker가 업데이트를 먹는 날

플레이: game.cocy.io/enhance