domingo, 20 de novembro de 2011

Tocando Sons em UnrealScript

SoundCue é um conjunto de instruções que informa a Unreal engine como tocar determinado som. SoundCues são bem flexíveis e podem ser criados no SoundCue Editor do UDK. Tocar um SoundCue em UnrealScript é muito simples, como pode ser visto no código abaixo:
class TesteSom1 extends Actor
      placeable;

var SoundCue exemploSom; 

event PostBeginPlay()
{
   SetTimer( 3 );    
}
function Timer()
{
   PlaySound( exemploSom );
}
defaultproperties
{        
    exemploSom = SoundCue'A_Music_GoDown.MusicMix.A_Music_GoDownMixCue'    
}

No exemplo acima usei um SoundCue que representa uma música. Então em algum momento posso querer parar essa música. Já que usamos a função PlaySound() então deve haver uma função StopSound(), certo? Errado, pois não existe a função StopSound() :(

Isto limita o uso da função PlaySound() para efeitos sonoros pequenos e sem loop. Para podermos usar música e sons em loop, teremos de usar a classe AudioComponent. O exemplo abaixo cria um AudioComponent que representa um som ambiente de cachoeira. Para testá-lo basta colocar em algum lugar do cenário.
class TesteSom2 extends Actor
      placeable;

defaultproperties
{
    Begin Object Class=AudioComponent Name=AudioComp
        SoundCue=A_Ambient_Loops.Water.Waterfall_Medium_02_Cue
        bAutoPlay=true        
    End Object    
    Components.Add( AudioComp )
}

A classe AudioComponent possui algumas funções úteis:
  • function Play();
  • function Stop();
  • function bool IsPlaying();
  • function FadeIn( float FadeInDuration, float FadeVolumeLevel );
  • function FadeOut( float FadeOutDuration, float FadeVolumeLevel );
Como exemplo, criei um mini game onde o jogador precisa coletar as Botas (classe TesteSomItem) que estão no cenário. Quando o jogador pega uma Bota um som é tocado. Este exemplo usa duas músicas. Uma música durante o jogo e uma música de vitória que é iniciada quando o jogador coletar todas as Botas. Não esqueça de definir o GameType como TesteSomGameInfo.
class TesteSomGameInfo extends UTGame;

var SoundCue itemSom; 
var AudioComponent musicaJogo, musicaVitoria;
var int itemCont;

function StartMatch()
{
   local TesteSomItem itemLocal;
   
   Super.StartMatch();
   
   itemCont = 0;
   
   //Verificar quantos Itens tem no cenário
   foreach AllActors( class'TesteSomItem', itemLocal )
   {
      itemCont++;
   }
      
   musicaJogo.Play();      
}

function RemoveItem( TesteSomItem item )
{      
   PlaySound( itemSom );
   item.Destroy();
   itemCont--;
   
   if ( itemCont <= 0 ) 
   {
      Broadcast( self, " Voce Coletou todos os Itens.") ;      
      musicaJogo.FadeOut( 2, 0 );
      musicaVitoria.FadeIn( 2, 1 );
   }
}
defaultproperties
{        
    itemSom = SoundCue'A_Pickups_Powerups.PowerUps.A_Powerup_JumpBoots_PickupCue'
    
    Begin Object Class=AudioComponent Name=Musica01Comp
        SoundCue=A_Music_GoDown.MusicMix.A_Music_GoDownMixCue                
    End Object
    
    musicaJogo = Musica01Comp        
    
    Begin Object Class=AudioComponent Name=Musica02Comp
        SoundCue=A_Music_RomNecris01.MusicSegments.A_Music_RomNecris01_Victory01Cue            
    End Object
        
    musicaVitoria = Musica02Comp
}

Classe que representa as Botas:
class TesteSomItem extends Actor
      placeable;

event Touch(Actor Other, PrimitiveComponent OtherComp, vector HitLocation, vector HitNormal)
{
   local TesteSomGameInfo testeSomGameInfo;    
   
   testeSomGameInfo = TesteSomGameInfo( worldinfo.game );
   
   if( testeSomGameInfo != None)
   {    
    if( Pawn(Other) != None && Pawn(Other).controller.bIsPlayer )
    {               
        testeSomGameInfo.RemoveItem( self );      
    }
   }
}     
defaultproperties
{        
    bCollideActors=true    
    bBlockActors=false
    
    Begin Object Class=CylinderComponent Name=CylinderComp
        CollisionRadius=20
        CollisionHeight=28
        CollideActors=true        
        BlockActors=false
    End Object    
    Components.Add( CylinderComp )
    CollisionComponent=CylinderComp    
        
    Begin Object Class=DynamicLightEnvironmentComponent Name=LightEnvironmentComp
        bEnabled = true
    End Object    
    Components.add( LightEnvironmentComp )
    
    Begin Object Class=StaticMeshComponent Name=StaticMeshComp
        StaticMesh = Pickups.JumpBoots.Mesh.S_UN_Pickups_Jumpboots002    
        LightEnvironment = LightEnvironmentComp
        Scale = 2
    End Object    
    Components.add( StaticMeshComp )    
}     


Para mais informações sobre Sons:
Audio System