Förstå och implementera 3D-ljud i GameMaker Studio

Vad du ska skapa

Ljud är ett viktigt element i den övergripande spelupplevelsen, och GameMaker: Studio ger ett relativt enkelt sätt för dig att implementera 3D-ljud i dina projekt. 

För att bättre förstå konceptet med 3D-ljud, tänk dig att lägga till ett par digitala öron till ett spelarstyrt spelobjekt. Eftersom spelaren närmar sig en ljudkälla inom spelet blir volymen av den här källan högre. När spelaren rör sig bort minskar volymen tills den slutligen blir tyst. Spelarens position i förhållande till ljudkällan kommer också att resultera i riktad stereoljud och ljudhastigheten som appliceras på ett rörligt objekt kan appliceras för att skapa en Doppler-effekt. 

Denna uppsättning immersiva ljudfunktioner kan åstadkommas genom ett system av ljudsändare och en ljudlyssnare. I den här handledningen skapar vi två scener som innehåller 3D-ljud på olika sätt, vilket ses i demovideoen. Du kan ladda ner källfilerna och sammanställa demo EXE från GitHub.

Förstå 3D-ljud

Koncepten som är involverade i 3D-ljud är likartade i alla spelutvecklingsmiljöer, eftersom de är baserade på välbekanta verkliga regler: ljudet blir starkare när du närmar dig källan, och ljudet från höger kommer att bli högre i ditt högra öra. Dessa grundläggande principer kan uppnås manuellt genom att beräkna och produktion av en ljudkälla i förhållande till ett specifikt spelobjekt, men GameMaker: Studio ger en uppsättning kraftfulla och lättanvända funktioner som ger dig direkt kontroll över ljud API.

Emiteraren

Ljuduppgivaren fungerar som källa till en 3D-ljudtillgång i GameMaker: Studio. Emittern definieras av en användardefinierad variabel och en position (x, y, z) det kan också vara statisk eller dynamisk. Emitterens volym styrs av och falla av värden och realtidseffekter kan appliceras genom kasta och hastighet värden. Hur emitteren hanterar ljudfallet bestäms av den avståndsmodell som tillämpas. Flera ljudemitterare kan existera inom samma scen.

Lyssnaren

Audio-lyssnaren fungerar som "öronen" som tar emot 3D-ljudet som sänds av emitern. Lyssnaren är placerad i en position (x, y, z) som också kan vara statisk eller dynamisk, men orientering av lyssnaren är lika viktigt. 

Listener orientering bestämmer den exakta riktningen och vinkeln som lyssnaren tittar på. Standardlärarens orientering i GameMaker: Studio resulterar i att vänster och höger ljudkanal vänds för 3D Audio, vilket vi kommer att korrigera senare under genomförandet.

Doppler-effekten

Utan att gå in i en lång och grundlig förklaring av Doppler-effekten kan den beskrivas som ljudfrekvensförändringen i förhållande till emitterens eller lyssnarens rörelse och hastighet. I GameMaker: Studio uppnås Doppler-effekten genom att tilldela vektorerna till ljudsändaren för ljudsändaren eller lyssnaren. För en fördjupad förklaring, läs Doppler-effekten på Wikipedia.

Implementera 3D-ljud

Genomförandet av 3D-ljud i ditt GameMaker-projekt är en tre stegs process. Du måste ordentligt definiera emitteren inom ett befintligt spelobjekt, placera det här objektet i rummet och berätta emitteren när och hur man spelar ett ljud. Du måste då definiera lyssnarens orientering och position inom ett befintligt spelobjekt som finns i samma rum som emitteren. 

Det första steget innebär emellertid att importera och definiera ljudtillgångarna.

Importera tillgångar

Börja med att klicka på Medel i huvudverktyget för GameMaker och välj Skapa ljud från rullgardinsmenyn. Ange ett namn för ljudtillgången och välj önskade ljudattribut för streaming och filkomprimering. Då, i Målalternativ del av Ljudegenskaper fönster, klicka på den första rullgardinsmenyn och välj 3D från listan med alternativ.

Genom att ange denna tillgång som ett 3D-ljud kan vi utnyttja GameMakers ljud API på unika sätt.

En stationär emitter

I vårt första exempel kommer vi att skapa en typ av isometrisk Sim City-stil instans av 3D-ljud med en stationär emitter. Vår lyssnare kommer att vara knuten till ett spelobjekt som följer muspekaren, och emitteren till 3D-ljudet kommer att ligga inom ett objekt som inte rör sig. Detta objekt kommer att representeras av ett litet kluster av byggnader, och emitern kommer att spela ett omgivande city-scape ljud med livlig trafik och bilhorn. 

Detta kommer att göra det möjligt för oss att testa ljudförlustegenskaperna för 3D-ljudsystemet, och vi kommer att kunna bättre förstå vikten av lyssnarorientering.

Skapa lyssnaren

Vår 3D-ljudlistor kommer att finnas inom ett objekt som följer muspekaren. I det här exemplet identifieras objektet av en sprite som liknar en GPS-markör. De obj_listener Objektet innehåller två viktiga block av kod: en i Skapa händelse och en i Steg händelse.

Klicka på Lägg till händelse knappen och välj Skapa att lägga till en Skapa händelse till obj_listener. Dra Exekvera kod ikon från Kontrollera fliken på obj_listener egenskaper fönster in i Åtgärder del av Skapa händelse panel. Dubbelklicka på Exekvera kod ikonen för att öppna GML-kodredigeraren och lägg till följande kodrad:

audio_listener_orientation (0,1,0,0,0,1);

Den här koden säkerställer att så snart lyssnaren objekt skapas placeras det i 3D-utrymme för att se mot skärmen, höger sida uppåt. Ljud som kommer från en emitter som ligger till höger om lyssnaren kommer att vara mer närvarande i höger högtalare och vice versa. Det här är standardinställningen som du vill använda i nästan alla typer av lyssnarimplementering i GameMaker: Studio. 

Om du ville att det vänstra och högra ljudet skulle bytas skulle du använda följande kod för orientering:

audio_listener_orientation (0,1,0,0,0, -1);

Lägg till en Steg händelse till obj_listener och dra en annan Exekvera kod ikon till Åtgärder panel. Öppna GML-kodredigeraren igen och ange följande rader av kod:

x = mouse_x; y = mouse_y; audio_listener_position (x, y, 0);

Denna kod hittar den aktuella platsen för muspekaren och tilldelar dessa koordinater till positionen för obj_listener objekt. Positionen för ljudlyssnaren definieras också av dessa koordinater. Genom att placera den här koden i Steg händelse, vi ser till att obj_listener objekt, dess medföljande sprite och lyssnaren själv är alltid på samma plats, sedan Steg händelsekod utförs vid varje ram under körtiden. 

(De 0 I denna kod är lyssnarens z-position. Eftersom vårt spel är i 2D kommer vår lyssnare alltid att vara på 0 på z-axeln.)

Öppna rummet där du vill att lyssnaren ska visas. Klicka på Objekt fliken och klicka på panelen för att visa listan över tillgängliga objekt. Välj ditt lyssnareobjekt och klicka i rummet för att placera det. Utgångspunkten för det här objektet spelar ingen roll, eftersom det kommer att uppdateras för att matcha muspekarens position vid körning. 

Det är det för lyssnaren. Nu måste vi skapa något för lyssnaren att höra.

Skapa emitteren

Som med lyssnaren kommer vi att fokusera uteslutande på Skapa och Steg händelser av emitterobjektet. I det här fallet placerar vi emitteren i obj_city objekt. 

Lägg till Skapa och Steg händelser till obj_city ,och lägg till en Exekvera kod åtgärd för båda händelserna.

I GML-koden för Skapa händelse, lägg till följande:

s_emit = audio_emitter_create (); audio_falloff_set_model (audio_falloff_exponent_distance); audio_emitter_falloff (s_emit, 50, 200, 1); audio_play_sound_on (s_emit, snd_cityaudio, true, 1);

(s_emit är namnet på vår nya emitter.)

Vi valde Exponentiell Avstånd falloff modell för detta exempel eftersom det ger en stadig vinst falloff med en kraftig ökning när du möter Referensavstånd punkt. Detta gör det möjligt att minska 3D-ljudvolymen när du kommer längre bort från objektet, smidigt, utan några hårda hopp, tills du blir extremt nära källan. För en fullständig lista över falloff-modeller och deras djupgående beskrivningar, läs GameMakers falloff-modelleringsdokumentation.

audio_emitter_falloff (emitter, falloff_ref, falloff_max, falloff_factor) är där vi ställer in attributen för falloff-modellen:

  • emitter är vår s_emit variabel. 
  • falloff_ref är den punkt där volymen faller börjar börja. 
  • falloff_max är den punkt där lyssnaren inte längre kan höra emitteren.
  • falloff_factor är ett nummer som används i audio_falloff_set_model beräkning för att bestämma resultaten av nedfallet. I vårt exempel använder vi standardvärdet för 1 så att vår s_emit emitter kommer att börja falla av när lyssnaren är 100 pixlar bort från emitorn och lyssnaren kommer inte att kunna höra emitteren på ett avstånd av 300 pixlar eller mer.

audio_play_sound_on (emitter, ljud, loop, prioritet) är hur vi får emitern att börja spela vårt 3D-ljud: 

  • emitter är vår s_emit variabel. 
  • ljud är vår snd_cityaudio 3D-ljud tillgång som vi importerade tidigare. 
  • slinga bestämmer om ljudet ska upprepas eller inte. 
  • prioritet är ett värde från 0 till 100 som bestämmer "betydelsen" av ljudet som spelas-större tal representerar högre prioritetsljud. 

I vårt exempel har vi bara ett ljud som spelas, så prioriteringen spelar ingen roll. Och eftersom den här koden exekveras i Skapa händelse och vi har valt att slingra ljudet kommer denna 3D-ljud tillgång att spelas så fort rummet är laddat och kommer att fortsätta spela tills det är uppmanat att stoppa. Och det tar oss till en mycket viktigt steg:

Denna ljudtillgång kommer att spelas även när du laddar ett annat rum som inte innehåller emitteren. För att effektivt stoppa denna tillgång från att spela i något annat rum än det rum som innehåller emitteren, måste vi lägga till en Room End händelse till obj_city

I Åtgärder panel av Room End händelse, lägg till en annan Exekvera kod ikon med följande GML-kod:

sound_stop (snd_cityaudio);

Nu är allt som är kvar att göra, placera obj_city objekt in i rummet som du placerat lyssnaren innan. Kör spelet och experimentera med muspekarens position för att ändra lyssnarens placering i förhållande till emitern för att se exakt hur 3D-ljud fungerar i praktiken.

En rörlig emitter med Doppler-effekten

I det andra exemplet kommer vi att bifoga emitern till ett rörligt föremål och tillämpa Doppler-effekten samtidigt som vi använder samma lyssnareobjekt som vi skapade tidigare. 

Ett punktobjekt flyttar från höger sida av skärmen till vänster. När kulan når kanten på skärmen, slingrar den runt och fortsätter från var den började. (Vi kommer inte att gå igenom hur man skapar den här rörelsen.) Kulobjektet avger ett loopingsljud som kan beskrivas som ett "whizzing" eller "buzzing" ljud. När objektet närmar sig lyssnaren, frekvens av ljudet ändras på grund av Doppler-effekten.

Skapa emitteren

Lägg till en Skapa och a Steg händelse till obj_bullet objekt och lägg till Exekvera kod åtgärd för båda händelserna.

I Skapa händelse, lägg till följande kod till GML-redigeraren:

s_emit2 = audio_emitter_create (); audio_emitter_falloff (s_emit2, 25, 200, 1,5); audio_play_sound_on (s_emit2, snd_bullet, true, 1);

Här, s_emit2 är namnet på vår nya emitter.

Denna emitter kommer att använda samma falloff-modell som definierades i föregående rum, eftersom endast en typ av fallmodell kan vara aktiv på en gång, och vår ursprungliga modell är lämplig för detta exempel. De nya falloffegenskaperna använder en falloffreferens av 25 pixlar, maximalt avsteg 200 pixlar och en falloff-faktor på 2,5 för beräkning. De snd_bullet 3D-ljudtillgången börjar spela så fort objektet skapas, med en prioritet på 1, och kommer slinga på obestämd tid.

I GML-redigeraren av Steg händelse, lägg till den här koden:

audio_emitter_position (s_emit2, x, y, 0);

Eftersom objektet rör sig och x- och y-värdena ständigt ändras, kommer emitterens position också att uppdateras till den nya positionen vid varje steg.

Glöm inte att lägga till kollobjektet i rummet och var noga med att lägga till sound_stop (snd_bullet) kod till objektets Room End händelse.

Skapa Doppler-effekten

3D-ljudsystemet är nu på plats för punktobjektet och lyssnaren fungerar ordentligt, men låt oss göra saker intressantare med Doppler-effekten. 

Att lägga till Doppler-effekten är väldigt enkelt, faktiskt. Bara öppna Exekvera kod handling i obj_bullet Skapa händelse och lägg till följande rad kod:

audio_emitter_velocity (s_emit2, -25, -25, 0);

audio_emitter_velocity (emitter, vx, vy, vz) tillåter oss att definiera egenskaperna hos Doppler-effekten: 

  • emitter är vår s_emit 2 variabel. 
  • vx är hastigheten (i pixlar per steg) längs x-axeln. 
  • vy är hastigheten (i pixlar per steg) längs y-axeln. 
  • vz gäller för hastighet längs z-axeln, men vårt spel är i 2D, så vi ställer in det här 0

Typiska Doppler-effektinställningar använder hspeed och vspeed variabler av ett objekt för att bestämma hastighetsvärdena, men i det här fallet använder vi bara ett värde av -25 för att skapa ett mer realistiskt kula ljud. Du kan testa objektet med följande kod för att märka skillnaden:

audio_emitter_velocity (s_emit2, hspeed, vspeed, 0);

Implementeringsidéer

3D-ljud kan lägga mycket djup och atmosfär i ditt spelprojekt, med minimal ansträngning som krävs. Här är några exempel för att komma igång:

  • Ett göm-och-sök-spel där du måste lyssna på ljudljud för att hitta ett doldt objekt.
  • Elektrisk eller brandrisk i en plattform som varnar dig för farorna när du kommer närmare.
  • Ett Frogger-stilspel där bilar zooma förbi dig med Doppler-effekten.
  • Rinnande vatten i en grotta eller vind blåser genom en luftkanal för att leda dig till utgången.
  • Ett spion spel där du måste komma nära ett mål för att höra en konversation.