Multiplayer Tank – Del 4

GameStates

Precis som i tidigare projekt så behöver vi strukturera upp vårt spel i olika "GameStates". Eftersom vi ska ha nätverksstöd så behövs fler Gamestates än vad vi annars hade haft utan nätverksstöd. Vi kommer nu att gå igenom varje Gamestate i tur och ordning och lägga till nätverksstödet till vårt spel.

bild

Vi börjar med att deklarera lite variabler i Game1.cs.

Tillägg till Game1.cs

public enum GameState
{
	TitleScreen,
	NotSignedIn,
	SelectingRole,
	WaitingAsHost,
	WaitingAsPlayer,
	PlayingAsPlayer,
	PlayingAsHost
}
GameState state = GameState.TitleScreen;

Vi skapar en global variabel av typen enum och anger namnet på de GameStates som vi kommer att använda oss av.

Ändringar i Update() och Draw()

protected override void Update(GameTime gameTime)
{
    switch (state)
    {
       case GameState.TitleScreen:
           break;
       case GameState.NotSignedIn:
           break;
       case GameState.SelectingRole:
           break;
       case GameState.WaitingAsHost:
           break;
       case GameState.WaitingAsPlayer:
           break;
       case GameState.PlayingAsHost:
           // Här lägger vi all tidigare kod som vi hade i Update()
           break;
       case GameState.PlayingAsPlayer:
           break;
    }
    base.Update(gameTime);
}

protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);
            spriteBatch.Begin();
            switch (state)
            {
                case GameState.TitleScreen:
                    break;
                case GameState.NotSignedIn:
                    break;
                case GameState.SelectingRole:
                    break;
                case GameState.WaitingAsHost:
                    break;
                case GameState.WaitingAsPlayer:
                    break;
                case GameState.PlayingAsHost:
                    //Här lägger vi allt som tidigare fanns i Draw()
                    break;
                case GameState.PlayingAsPlayer:
                    break;
            }
            spriteBatch.End();
            base.Draw(gameTime);
        }

Vi gör en switch-sats för våra GameStates i både Update() och Draw() och lägger den kod vi tidigare skapat i case GameState.PlayingAsHost:

TitleScreen

Spelet startar i GameState TitleScreen. I detta läge så händer inte så mycket. Vi behöver välkomna våra spelare och ge dem instruktioner för att fortsätta. För att göra detta så använder vi en titelskärm med lite härlig retro-stuk.

bild

Bilden laddar ni hem som zip-fil nedan.

Precis som innan så packar vi upp bilden i content-mappen till vårt projekt och lägger till den i content-manager. Nästa steg blir att skapa den kod som ska köras för gamestate TitleScreen.

OBS - Vi kommer nu att göra tillägg på flera ställen i Game1.cs, se kommentarerna i koden.

Tillägg till Game1.cs

Texture2D titleScreenGfx; //Grafik till titelskärmen - Global variabel

titleScreenGfx = Content.Load<Texture2D>("title_screen"); //Tillägg till LoadContent()

//Tillägg till Update()
 KeyboardState key = Keyboard.GetState();

//Tillägg till Update() - case TitleScreen
case GameState.TitleScreen:
     if (key.IsKeyDown(Keys.Space))
     {
        state = GameState.NotSignedIn;
     }
     break;

//Tillägg till Draw() - case TitleScreen
case GameState.TitleScreen:
	spriteBatch.Draw(titleScreenGfx, new Vector2(0, 0), Color.White);
	break;

Vi har nu gjort så att titelskärmen visas tills dess att vi trycker ner SPACE-tangenten och då ändras GameState till NotSignedIn.

NotSignedIN

Nu börjar det bli intressant för nu ska vi (äntligen) börja implementera vårt nätverksstöd. För att göra ett program med nätverksstöd så behövs oftast kunskaper om hur nätverk fungerar på protokollnivå. Använder vi XNA så är det dock så pass enkelt att även de med lite eller ingen kunskap om nätverk klarar av att skapa ett program med nätverksstöd (grundläggande kunskaper om datorkommunikation rekommenderas alltid för att bättre förstå vad som händer).

System Link och XNA

Vi kommer att använda oss av något som heter System Link som är en nätverksteknik för spel och som är en del av XNA. Genom att använda System Link så kan vi enkelt utbyta information mellan datorer och Xbox 360-maskiner via nätverket. Hur den informationen formateras och vad som skall skickas är upp till oss som programmerar. Enda begränsningen med System Link är att det enbart fungerar för LAN (Local Area Network). Det betyder alltså att vi inte kan ansluta via Internet och spela med varandra (ifall man inte använder någon VPN-tunnel eller liknande..).

Alternativt kan vi välja att använda Xbox Live med vilket vi kan ansluta både PC- och Xbox 360-maskiner till varandra via Internet. Att göra detta är betydligt mer omständigt och kräver bl a flera medlemskap i XNA Creators Club samt mer komplex kod. Till vårt projekt väljer vi den betydligt enklare varianten med System Link.

Ett spel som använder System Link är alltså "lokalt" och använder precis som Xbox Live ett gamertag system. En gamertag är det namn som en användare använder och identifierar sig med i ett (nätverks) spel. Alltså detsamma som ett alias/nickname/handle. Skulle man försöka sig på att översätta gamertag så blir det något i stil med "SpelarNamnBricka". En spelares gamertag är även kopplat till information och statistik över spelaren (exempelvis poäng och highscore för olika spel) som tillsammans sparas som en profil.

Innan en spelare kan ansluta eller starta ett nätverksspel så måste spelaren logga in (eng. Sign in). Använder vi nätverksstödet i XNA så kan man alltid göra detta genom att trycka på HOME-knappen på tangentbordet. För Xbox 360 spelare så är det den silverfärgade X-knappen som gäller. För att allt detta ska fungera så behöver vi bara lägga till en rad kod till vårt projekt, nämligen raden som laddar in GamerServicesComponent som är en del av XNA.

Vi lägger till följande rad i konstruktorn för vår Game1 klass (i Game1.cs):

Tillägg till Game1()

public Game1()
{
   graphics = new GraphicsDeviceManager(this);
   Content.RootDirectory = "Content";
   //Lägger till "nätverksstöd" 
   this.Components.Add(new GamerServicesComponent(this)); 
}

Det vi gör är att skapa en ny instans av GamerServicesComponent och kopplar den till vårt spel. Nu kan vi när som aktivera Games for Windows genom att trycka på HOME-knappen.

Games for Windows - Skapa en profil

Har vi lagt till GamerServicesComponent så startar konsolen till Games for Windows automatiskt första gången vi kör vårt program. Har man ingen lokal profil så ombeds man att skapa en.

bild

Vi väljer att skapa en ny "offline" profil.

bild

Namnet på vår profil blir alltså det namn om vi kommer att identifiera vår spelare med på nätverket.

bild

Har vi bara en profil på datorn så kommer den automatiskt att logga in så fort vi kör vårt program. Detta går dock att ändra i inställningar för profilen om man så vill. Under inställningar för vår profil kan vi ändra på en massa saker, bl a den bild som spelaren ska använda. Denna bild kan man sedan enkelt använda i vårt nätverksspel tillsammans med namnet på spelaren för att identifiera spelare och göra det hela lite mer personligt.

Vår gamestate NotSignedIn har som enda uppgift att se till så att vi är inloggade med en spelarprofil i Games for Windows. Eftersom detta i de allra flesta fall sker automatiskt så kommer vårt spel oftast gå vidare direkt till nästa gamestate. Men skulle det bli problem av någon anledning så att spelaren inte är inloggad så måste vi se till så att spelaren loggar in och att spelaren får information om detta.

Till detta behöver vi en ny skärmbild som skall visas ifall spelaren inte har loggat in med en profil. Skärmbilden kan ni ladda hem som en zip-fil via länken nedan.

bild

Vi packar upp filen not_signed_in_screen.png i vår content-mapp och lägger till den i content-manager som vanligt.

OBS - Vi kommer nu att göra tillägg på flera ställen i Game1.cs, se kommentarerna i koden.

Tillägg till Game1.cs

//Global variabel
Texture2D notSignedInGfx;

//Tillägg till LoadContent()
notSignedInGfx = Content.Load<Texture2D>("not_signed_in_screen");

//Tillägg till Update()
case GameState.NotSignedIn:
	if (Gamer.SignedInGamers.Count == 0)
	{
		if (!Guide.IsVisible)
		{
			Guide.ShowSignIn(1, false);
		}
	}
	else
	{
		state = GameState.SelectingRole;
	}
	break;

//Tillägg till Draw ()
case GameState.NotSignedIn:
	spriteBatch.Draw(notSignedInGfx, new Vector2(0, 0), Color.White);
	break;

Det vi gör nu är att kolla ifall vi har en inloggad användare och har vi inte det så ska guiden för att logga in med Games for Windows visas. Detta gör att vi inte kommer att se vår fina bild särskilt länge. Alternativt struntar vi i att starta guiden automatiskt och ändrar bara gamestate när spelaren loggat in. Kör vi programmet på en PC så kan endast 1 spelare vara inloggad samtidigt men körs programmet på en Xbox 360 så kan mer än en spelare vara inloggade samtidigt på en maskin. Notera att Guide.ShowSignIn tar två inparametrar. Dels ett nummer som är antalet inloggningsskärmar som skall visas (detta ska alltid vara ett för en PC) och dels en bool som anger ifall vi endast skall tillåta Online-profiler eller även lokala profiler. I vårt fall vill vi använda lokala profiler så således blir det false.

Vi kommer att fortsätta med nätverksimplementationen i del 5. To be Continued...

Lämna ett svar

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

Scroll to top