Breakout – Del 5

Vi kommer att fortsätta med att bygga på med fler funktioner för att göra spelet roligare att spela. I denna delen ska vi lägga till två specialrutor, en ruta som inte ska gå att ha sönder och en ruta som ska tåla att bli träffad ett visst antal gånger innan den försvinner. För att göra spelet lite roligare så ska vi även skriva ut antal liv som spelaren har på skärmen samt poäng.

Lägg till 2 specialrutor

För att kunna göra lite roligare banor så behövs rutor som fungerar lite annorlunda än "vanliga" rutor. Vi ska skapa två typer av rutor. En typ som inte går att ha sönder och en typ som försvinner efter ett visst antal träffar. För att göra detta behöver hålla koll på hur många träffar varje ruta tål. Detta kan vi lösa genom att skapa ännu en lista där vi sparar hur många träffar som varje ruta tål och minska detta värde varje gång bollen träffar en ruta.

Tillägg av variabler

        List<int> tile_life = new List<int>();

Vi skapar en lista som vi kallar för tile_life där vi sparar element av typen int.

För att detta ska fungera så måste vi först göra några tillägg till vår funktion LaddaLevel(). Det rör sig om ca 15 rader men för att inte förvirra allt för mycket så återges hela LaddaLevel()med de nya tilläggen. Tilläggen markeras med kommentaren "Nytt del5".

Tillägg till LaddaLevel()

public void LaddaLevel(int nummer)
{
	StreamReader SR = new StreamReader(nummer.ToString());

	string bana = SR.ReadToEnd();
	SR.Close();
	int temp_positionY = 0;
	int temp_positionX = 0;

	tile_position.Clear(); //Nytt del5
	tile_type.Clear();     //Nytt del5
	tile_life.Clear();     //Nytt del5

	for (int i = 0; i < bana.Length; i++)
	{
		switch (bana[i])
		{
			case ' ':
				temp_positionX++;
				break;
			case '0':
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
				tile_life.Add(1);  //Nytt del5
				tile_position.Add(new Vector2((temp_positionX * 40), (temp_positionY * 20)));
				temp_positionX++;
				tile_type.Add(int.Parse(bana[i].ToString()));
				break;
			case '8': //Nytt del5 (hela case 8)
				tile_position.Add(new Vector2((temp_positionX * 40), (temp_positionY * 20)));
				temp_positionX++;
				tile_type.Add(int.Parse(bana[i].ToString()));
				tile_life.Add(4);
				break;
			case '9': //Nytt del5 (hela case 9)
				tile_position.Add(new Vector2((temp_positionX * 40), (temp_positionY * 20)));
				temp_positionX++;
				tile_type.Add(int.Parse(bana[i].ToString()));
				tile_life.Add(5);
				break;
			case '\n':
				temp_positionY++;
				temp_positionX = 0;
				break;
		}
	}
}

Vi börjar med att tömma listorna med tile_position.Clear(); , tile_type.Clear(); och tile_life.Clear();. Detta eftersom vi kanske vill kunna ladda en ny bana när spelet är igång och då måste listorna tömmas innan vi kan fylla dem igen, annars blir det knasigt.

Läses en "normal" ruta in, dvs case 0-5 så får den rutan värdet 1 i listan för "liv", alltså tile_life.Add(1);. Skulle det vara en ruta av typ "8" så får den värdet 4, dvs att den rutan kommer att tåla 4 träffar innan den försvinner. Skulle vi ha en ruta av typ "9" så får den 5 i liv. Vi kommer i följande exempel använda rutor av typen "9" som oförstörbara rutor.

Vi gör följande ändringar till Update()

Tillägg till Update()

//tile_position.RemoveAt(i); Dessa rader ersätts
//tile_type.RemoveAt(i);     Dessa rader ersätts
//i--;                       Dessa rader ersätts
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--;

}

Vi ändrar i kollisionsdetekteringen mellan boll och tile i GameState==1. För att vara extra tydliga har vi kommenterat ut de 3 rader som skall ersättas med följande if-satser. Istället för att enbart ta bort den tile som träffas samt dess typ från listorna så kolla vi först om värdet för tile_life är mindre än 5 (dvs alla rutor med liv på 5 eller mer kommer att bli oförstörbara). Stämmer detta så minskar vi värdet med ett. Skulle tile_life vara mindre än ett så tar vi bort aktuell tile_position samt tile_type och tile_life.

De nya tile-typerna måste också ritas ut. Vi väljer en metall-grå färg för rutan som skall tåla fyra tillslag och en guldfärg för den oförstörbara rutan.

Tillägg till Draw()

case 8: spriteBatch.Draw(tile_gfx, tile_position[i], Color.Gray);
   break;
case 9: spriteBatch.Draw(tile_gfx, tile_position[i], Color.Gold);
   break;

Vi lägger alltså till ovanstående rader till vår switch-sats i Draw()

För att kunna testa förbättringarna måste göra en bana som innehåller någon av de nya tile-typerna. Enklast är att editera filen "0" som vi skapade i förra delen eller ladda hem filen 0_ny_bana.zip och extrahera innehållet till Projects\Breakout\Breakout\bin\x86\Debug för att skriva över den gamla banan med en ny.

Ändrar vi banan och provkör vårt projekt så ska vi nu ha lite roligare tiles och resultatet bör likna detta

bild

Skriva ut poäng och liv på skärmen

För att göra spelet ännu roligare så ska vi nu se till så att antal liv som spelaren har samt poäng skrivs ut på skärmen. För att göra detta kommer vi att använda oss av en SpriteFont såsom beskrivits i tidigare artiklar här på csharpskolan. Vi kommer här att repetera förfarandet lite snabbt.

bild

Vi högerklickar på content i Solution Explorer och väljer Add - New Item ..

bild

Vi väljer Sprite Font och klickar på Add. Vi kan döpa vår SpriteFont till valfritt namn men vi väljer här det förvalda namnförslaget SpriteFont1.

bild

När vi lagt till vår SpriteFont så öppnas filen SpriteFont1.spritefont för redigering. Vi kan här enkelt ändra inställningar för vår SpriteFont såsom typsnitt och teckenstorlek. För att få lite mer "Retro"-känsla ändrar vi FontName till Courier New och Style ändrar vi från "regular" till Bold. Det är givetvis fritt fram att experimentera.

Vi lägger till följande globala variabler:

Tillägg av variabler

        SpriteFont font;
        int score = 0;
        int lives = 3;

Vi skapar en variabel med namnet font av typen SpriteFont. Vi skapar även 2 variabler av typen int som vi ska använda för att hålla koll på poängen, score, samt antal liv som spelaren har, lives. Vi ger dessa variabler lämpliga värden.

Följande tillägg görs till LoadContent()

Tillägg till LoadContent()

        font = Content.Load<SpriteFont>("SpriteFont1");

Vi laddar in vår SpriteFont.

Vi gör sedan följande tillägg till Update() när vi konstaterat att en kollision inträffat mellan bollen och en tile:

Tillägg till Update()

        if (tile_life[i] < 1)
        {
           tile_position.RemoveAt(i);
           tile_type.RemoveAt(i);
           tile_life.RemoveAt(i);
           i--;
           score += 10;  //Tillägg!
        }

Vi lägger bara till raden som markerats med "Tillägg!" övriga rader är bara för att göra det enkelt för oss att hitta var tillägget ska göras i koden. Vi kommer alltså med denna ändringen öka värdet för score med 10 för varje ruta som försvinner.

Inte nog med detta utan vi måste även göra ytterligare tillägg i Update() när vi kollar om vi missat bollen. Vi gör följande tillägg:

Tillägg till Update() #2

if (ball_position.Y >= 600)
{
	game_state = 0;  //Inget nytt
	game_speed = 1;  //Inget nytt
	tid = 0;         //Inget nytt

	lives--;
	if (lives < 1)
	{
		score = 0;
		lives = 3;
		LaddaLevel(0);
	}
}       

I if-satsen som kontrollerar ifall vi missat bollen så ser vi till att vi minskar variabeln lives med ett. Vi lägger även till en if-sats som kollar ifall vi har slut på liv. Om så är fallet så nollställer vi poängen (score), återställer livet (lives) samt laddar om banan noll, Laddalevel(0).

Sist men inte minst så ska vi göra lite tillägg i Draw() så att vi skriver ut poängen och antal liv med vår SpriteFont

Tillägg till Draw()

spriteBatch.DrawString(font, "Lives:" + lives + "   Score:" + score + "   Speed:" + game_speed, new Vector2(10, 10), Color.White);

Vi skriver ut antal liv, poäng och även hastigheten för spelet (game_speed). spriteBatch.DrawString fungerar ungefär som en blandning av spriteBatch.Draw och Console.Write. Se grundläggande programmering för mer information om grundläggande stränghantering.

Provkör vi vårt projekt så ser vi något i stil med:

bild

Lämna ett svar

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

Scroll to top