Tetris Dreams – Del 2

Inledning

I några kommande artiklar fortsätter vi med att titta på intressanta detaljer och några av de problem vi stötte på under produktionen av vårt spel TetrisDreams.

Det hackar..

När vi började arbeta på vår bakgrundsgrafik upptäcker vi till vår fasa att spelet hackar till med jämna intervall. Ungerfär en gång varannan sekund hoppar grafiken över ett pixelsteg och den jämna animeringen störs. Fram tills nu har har mest jobbat med menyer och statisk grafik och här märker vi inte att vi har problem men så fort vi börjar lägga in snabbt uppdaterande grafik är det tydligt. Har vi redan problem med prestanda? Vi tappar alltså en och annan renderings frame från och till. Vi har drabbats av ett vanligt problem som kan te sig förbryllande till en början men som har en fullt logisk förklaring.

I vilka lägen kan vi tappa en frame?

Möjliga förklaringar

  • 1. Vår maskin är överbelastad av andra program, tjänster eller drivrutiner i bakgrunden . Ibland får vårt spel inte tillräcklig tid av systemet.
  • 2. Vi försöker göra för mycket samtidigt och vårt spel hinner helt enkelt inte med. Detta får till följd att vår update metod tar för lång tid på sig och nästa gång det är dags för update har det gått så lång tid att vi uppdaterar fram grafiken ett ”extra” steg.
  • 3. Synkning mellan vår monitors uppdateringsfrekvens och spelets uppdatering är inte 100% perfekt. Det räcker med att monitorns frekvens ligger på 59.50hz och vårt spel ligger på stabila 60hz och vi får osync varannan sekund. (1/0.5 = 2sek). Samma sak om monitorn t.ex ger 60hz och vårt spel hoppar mellan 58-60hz.

Troliga förklaringar

1: Överbelastad maskin

Med hjälp av windows aktivetetshanterare kan vi konstatera att vi har en stabil miljö utan externa processer som påverkar systemresurserna som är tillängliga till vårt spel. Vi har dessutom samma problem när vi kör spelet på Xbox och där är miljön ren.

Slutsats: Vi har inte problem med vår miljö.

2: Överbelastat spel

Vi ser här att enligt windows så använder vårt spel i närheten av 100% av den core i CPU som kör spelet. Frågan är om detta är normal eller om det tyder på att vi har problem med prestanda. För att undersöka detta gör vi ett test. Det finns nämligen ett sätt att just titta på detta i XNA. Gametime.IsRunningSlowly är vad vi är ute efter.

GameTime.IsRunningSlowly Property

”Gets a value indicating that the game loop is taking longer than its TargetElapsedTime. In this case, the game loop can be considered to be running too slowly and should do something to "catch up." ”

MSDN GameTime.IsRunningSlowly

Vi lägger nu till följande kod snutt i vårt TetrisDreams update metod

TetrisModel.cs

protected override void Update(GameTime gameTime)
	{
	..
	if(gameTime.IsRunningSlowly)
		{
		Debug.WriteLine("slow: " + gameTime.TotalGameTime.ToString());
		slow = Color.Red;
		}
	else
		slow = Color.CornflowerBlue;
	..
	}

I draw lägger vi till följande rad

TetrisModel.cs

protected override void Draw(GameTime gameTime)
	{
	..
	graphics.GraphicsDevice.Clear(slow);
	..
	}

Vi kan nu starta spelet och helt enkelt studera bakgrundsfärgen. När vi tappar en frame blir bakgrunden röd. I annat fall är den blå. En plötslig röd bakgrund är helt tydlig och går inte att missa. I vårt fall kan vi konstatera att vi visserligen har en och annan röd färg precis när spelet drar igång men efter någon sekund stabiliserar det sig och bakgrunden är helt blå.

Slutsats: vi har inte problem med prestanda!

3: Syncproblem mellan spel och skärm

Återstår att undersöka möjligheten att vi har en osync mellan skärmens och spelets uppdatering.

Game.IsFixedTimeStep Property

Genom att sätta följande property till false talar vi om för XNA att vårt spel inte skall gå i fast antal bilder per sekund utan uppdateras maximal vad som hinns med.

MSDN Game.IsFixedTimeStep

Vi ändrar även en inställning som bestämmer om vi ska försöka att synkronisera våra grafik med systemets (skärmens) vertical trace (vsync). Dvs den tidpunkt som vår skärm/TV ritar om sig.

GraphicsDeviceManager.SynchronizeWithVerticalRetrace Property

MSDN GraphicsDeviceManager.SynchronizeWithVerticalRetrace

Följande kod läggs till i vår Konstruktor.

TetrisModel.cs

public GameStateManagementGame()
	{
	..
	IsFixedTimeStep = false;
	graphics.SynchronizeWithVerticalRetrace = true;
	..
	}

Vårt hack är nu borta både på PC och Xbox 360!!

Slutsats

Ska man alltid använda ovan två rader och aldrig ha fasta tidssteg? I vårt fall löste det problemet men det är inte säkert att det fungerar på ett annat system med en annan skärm. Enligt erfarenhet är det olika från system till system, från PC till PC. Det kan därför t.ex vara en bra idé att lägga till vsync av/på till options så att en användare själv kan rätta till osync vid behov. Timestep av/på är antagligen ingenting man vill att användaren ska kunna ändra på. Här får vi välja en filosofi och arbeta med vår uppdatering där efter. I kommersiella spel används båda delar. Forza till Xbox 360 kör t.ex med fast bilduppdatering 60/sek medan Colin McRae: Dirt kör med variabel hastighet.

bild

Obs: Det skall nämnas att i TetrisDreams och även många andra mindre spel här på Csharpskolan så gör vi inte våra update beräkningar på ett helt korrekt sätt. I och med att vi inte alltid får exakt jämna interuppt till vår Update så måste vi egentligen korrigera för detta. Vi kan ju dessutom tappa en eller flera frames någon gång. Om det t.ex är viktigt att en animering körs exakt ett varv var 3:e sekund så måste vi titta på GameTime och se exakt hur lång tid som har gått innan vi förändrar något. I många fall så ändrar vi t.ex ett värde på en animation med ett steg varje gång vi får en Update. Tänk då på att om du kör variabel uppdateringshastighet så har du inte längre kontroll över hur snabbt saker sker på olika system.

I Tetris dreams går vi en mellanväg och har ”tidsmätning” när det gäller viktiga saker t.ex hur fort blocket faller. Den animerade bakgrunden med tetris block som snurrar omkring vid våra menyer uppdateras däremot en gång varje update oavsett vad som händer. Detta är ett fel och ett resultat av artikelförfattarens lathet.

Övningar

Övning 1

Använd vårt projekt från Del 1 och utöka TetrisDreams.cs. Lägg till funktionalitet för att mäta om vi tappar frames. Eventuellt kan det behövas små ändringar i fler klasser för att t.ex ändring av bakgrundsfärgen inte skall skrivas över.

(svårighetsgrad 1)

Kommande artikel

Nästa artikel i serien TetrisDreams kommer att fortsätta med fler vanliga problem som kan dyka upp på vägen mot ett komplett XNA spel.

Lämna ett svar

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

Scroll to top