Breakout – Del 6

Lägga till ljudeffekter - Ljud

Vi ska nu lägga till lite ljudeffekter som drastiskt kommer att förbättra upplevelsen av vårt lilla spel. Vi kommer att använda oss av XNA när vi hanterar och spelar upp ljud, precis som i artikeln "Ljud i XNA". Vi kommer dock att repetera tillvägagångssättet.

Först och främst måste vi ha lite ljud. Antigen skapar vi egna ljud eller så laddar vi hem Breakout_Sounds.zip och extraherar innehållet i vår content mapp.

bild

Vi ser till så att vi har tile.wav, tile_hard.wav, death.wav, paddle.wav och death.wav i vårt content mapp. Namnet på filerna är ganska beskrivande. Vi kommer alltså att ha ljud för när bollen träffar en normal tile, när bollen träffar en speciell (hård) tile, när bollen träffar paddeln, när vi missat bollen och "dör" samt när spelet börjar (när GameState byts från 0 till 1).

När vi gjort detta så startar vi XACT Auditioning Utility som vi hittar under Microsoft XNA Game Studio 3.1 - Tools.

bild

Startar vi XACT Auditioning Utility så möts vi av ett kommandotolksfönster med lite information. Det är bara att låta programmet köras.

bild

Nästa steg blir att starta Microsoft Cross-Platform Audio Creation Tool (XACT3) som vi hittar under Microsoft XNA Game Studio 3.1 - Tools.

bild

När vi startat Microsoft Cross-Platform Audio Creation Tool (XACT3) så väljer vi New Project under menyn File. Bläddra sedan fram till din Content-mapp för ditt projekt och spara den som "sounds". Ändelsen .xap kommer automatiskt att läggas till.

Välj New Wave Bank under menyn Wave Banks. Använd standardnamnet.

Välj New Sound Bank under menyn Sound Banks. Använd standardnamnet.

bild

När vi gjort detta så ska vi dra och släpp wav-filerna från Content-mappen till Wave Bank i projektet. Alternativt kan vi välja Insert Wave File(s) under menyn Wave Banks.

bild

Sedan markerar vi alla filer i vår Wave Bank och drar och släpper dem i fönstret Sound Bank.

bild

Och till sist ska vi nu dra filerna från vår Sound Bank till den nedre delan av samma fönster, den där det står Cue Name. Det vi gör är något som kallas för cues. Dessa cues bygger på ljud från vår Sound bank. För varje sound kan vi sedan göra en massa inställningar, t.ex. volym, panorering, pitch etc etc. Vi kan alltså göra flera olika sounds och cues (med olika namn) från en o samma wav-fil. Vi kontrollerar att vi har 5 cues med namnen tile_hard, paddle, respawn, tile och death.

bild

Vi sparar projektet och avslutar med File - Build (F7). Följande ruta ska då dyka upp.

bild

Vi klickar på Finish så är allt klart.

Vi får inte glömma att lägga till filen sounds.xap som nu ska ligga i cår content-mapp till vårt projekt via Solution Explorer. Vi högerklicka och väljer Add - Existing item..

bild

Nu är vi klara med det förberedande arbetet med ljudfilerna. Nu är det dags för lite tillägg i koden.

Eftersom vi bara ska spela upp färdiga ljud och inte manipulera dem eller göra något mer avancerat så skulle vi lika gärna kunnat skippa hela biten med Microsoft Cross-Platform Audio Creation Tool (XACT3) och istället bara lagt till våra wav-filer i vårt projekt och spelat dem på ett enklare sätt. Det skadar dock inte att känna till de möjligheter som vi har med XNA och ljud.

Lägga till ljudeffekter - Kod

Vi börjar med att lägga till lite globala variabler som vi kommer att använda oss av för att kunna spela upp våra ljud som vi nyss förberett. Vi lägger till följande variabler:

Tillägg av variabler

        AudioEngine audioEngine;
        WaveBank waveBank;
        SoundBank soundBank;
        Cue paddle;
        Cue tile;
        Cue respawn;
        Cue tile_hard;
        Cue death;

Vi kommer inte här att gå in på detalj hur ljud fungerar i XNA eller alla möjligheter som finns utan konstatera att det vi gör här är väldigt "basic" och det finns betydligt mer möjligheter och funktioner för den intresserade att fördjupa sig i.

Vi gör följande tillägg till LoadContent():

Tillägg till LoadContent()

        audioEngine = new AudioEngine("Content\\sounds.xgs");
        waveBank = new WaveBank(audioEngine, "Content\\Wave Bank.xwb");
        soundBank = new SoundBank(audioEngine, "Content\\Sound Bank.xsb");
        paddle = soundBank.GetCue("paddle");
        tile = soundBank.GetCue("tile");
        respawn = soundBank.GetCue("respawn");
        tile_hard = soundBank.GetCue("tile_hard");
        death = soundBank.GetCue("death");

Vi gör sedan lite tillägg till Update().

Tillägg till Update()

        soundBank.PlayCue("paddle");
	soundBank.PlayCue("tile");
	soundBank.PlayCue("death");
	soundBank.PlayCue("respawn");
	soundBank.PlayCue("tile_hard");

OBS OBS! Dessa rader skall in på lämpligt ställe och spelar de olika ljuden som vi har. "paddle" ska spelas då vi konstaterat en kollision mellan boll och paddeln, "tile" ska spelas när kollision mellan boll och tile konstaterats och tile'en tas bort, tas inte tile'en bort så har har bollen träffat en "hård" tile och då ska ljudet "tile_hard" spelas. Missar vi bollen så ska "death" spelas och när vi börjar spelet, alltså då GameState ändras från 0 till 1 så ska ljudet "respawn" spelas".

För er som får problem eller känner sig osäkra så återges hela Update() här nedan med ändringarna kommenterade.

Komplett Update() med ändringar - del6

protected override void Update(GameTime gameTime)
{
	// Allows the game to exit
	if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
		this.Exit();

	// TODO: Add your update logic here
	MouseState mouse = Mouse.GetState();
	if (mouse.X < 0 || mouse.X > 710)
	{
		if (mouse.X < 0) player_position.X = 0;
		if (mouse.X > 710) player_position.X = 710;
	}
	else
	{
		player_position.X = mouse.X;
	}

	if (game_state == 0)
	{
		ball_position.X = player_position.X + 30;
		ball_position.Y = player_position.Y - 12;

		if (mouse.LeftButton == ButtonState.Pressed)
		{
			ball_speed = new Vector2(1, -3);
			soundBank.PlayCue("respawn"); //NYTT DEL6
			game_state = 1;
		}
	}


	if (game_state == 1)
	{
		ball_position = ball_position + ball_speed * game_speed;


		tid += gameTime.ElapsedRealTime.Milliseconds;
		if (tid > 20000 * game_speed)
		{
			tid = 0;
			if (game_speed < 6) game_speed = game_speed + 1;
		}

		if (ball_position.Y >= 600)
		{
			game_state = 0;
			game_speed = 1;
			tid = 0;
			soundBank.PlayCue("death"); //NYTT DEL 6
			lives--;
			if (lives < 1)
			{
				score = 0;
				lives = 3;
				LaddaLevel(0);
			}
		}


		if (ball_position.X <= 0)  //Kontrollerar kollision med vänsterkanten
		{
			ball_position.X = 0;
			ball_speed.X = -ball_speed.X;
		}
		if (ball_position.X >= 788)  //Kontrollerar kollision med högerkanten
		{
			ball_position.X = 788;
			ball_speed.X = -ball_speed.X;
		}
		if (ball_position.Y <= 0)  //Kontrollerar kollision med övere kanten
		{
			ball_position.Y = 0;
			ball_speed.Y = -ball_speed.Y;
		}
		Rectangle ballBox = new Rectangle((int)ball_position.X, (int)ball_position.Y, 12, 12);
		Rectangle playerBox = new Rectangle((int)player_position.X, (int)player_position.Y, 90, 17);

		if (playerBox.Intersects(ballBox) && ball_speed.Y > 0)  //Kontrollerar kollision med spelaren
		{
			soundBank.PlayCue("paddle"); //NYTT DEL 6
			
			if (ball_position.X + 6 >= player_position.X && ball_position.X + 6 <= (player_position.X + 15)) ball_speed = new Vector2(-2.5F, -1.5F);
			if (ball_position.X + 6 >= player_position.X + 16 && ball_position.X + 6 <= (player_position.X + 31))
			{
				if (ball_speed.X > 0) ball_speed.X = -ball_speed.X;
				ball_speed.Y = -ball_speed.Y;
			}
			if (ball_position.X + 6 >= player_position.X + 59 && ball_position.X + 6 <= player_position.X + 74)
			{
				if (ball_speed.X < 0) ball_speed.X = -ball_speed.X;
				ball_speed.Y = -ball_speed.Y;
			}
			if (ball_position.X + 6 >= player_position.X + 75 && ball_position.X + 6 <= player_position.X + 90) ball_speed = new Vector2(2.5F, -1.5F);
			if (ball_position.X + 6 >= player_position.X + 32 && ball_position.X + 6 <= player_position.X + 58) ball_speed.Y = -ball_speed.Y;
		}

		for (int i = 0; i < tile_position.Count; i++)
		{

			Rectangle tileBox = new Rectangle((int)tile_position[i].X, (int)tile_position[i].Y, 40, 20);
			if (tileBox.Intersects(ballBox))
			{
				//Vi har en kollision här!

				ball_position -= ball_speed * game_speed; //backa bollen

				if (ball_position.X + 6 >= tile_position[i].X && ball_position.X + 6 <= tile_position[i].X + 40)
				{
					ball_speed.Y = -ball_speed.Y; //kolision uppifrån eller nerifrån
				}
				else
				{
					ball_speed.X = -ball_speed.X; //kollisions från sidan
				}

				//tile_position.RemoveAt(i);
				//tile_type.RemoveAt(i);
				//i--;
				if (tile_life[i] < 5) tile_life[i]--;
				if (tile_life[i] < 1)
				{
					tile_position.RemoveAt(i);
					tile_type.RemoveAt(i);
					tile_life.RemoveAt(i);
					i--;
					score += 10;
					soundBank.PlayCue("tile"); //NYTT DEL6
				}
				else soundBank.PlayCue("tile_hard"); //NYTT DEL6
			   
				break;
			}

		}
	}


	base.Update(gameTime);
}

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *

Scroll to top