Skip to content

Monogame del 2, [Rita rektanglar]

Välkommen tillbaka.

Från och med nu så ska jag försöka hålla mig till lite kortare avsnitt och ämnen
Idag tänkte jag att vi ska försöka rita något i vårat fönster. Men vi börjar städa upp lite ifrån föregående avsnitt då vi testade ordningen som monogame anropar våran applikation. Vi återkommer till det vartefter som det blir aktuellt att ta upp det.

Vi städar bort alla funktioner utom konstruktorn, Initialize, Update och Draw. Så kvar har vi följande kod:

  1.  
  2. using Microsoft.Xna.Framework;
  3. using Microsoft.Xna.Framework.Input;
  4.  
  5. namespace GameTutorial
  6. {
  7.     public class GameTutorialGame : Game
  8.     {
  9.         GraphicsDeviceManager graphics;
  10.  
  11.         public GameTutorialGame()
  12.         {
  13.             graphics = new GraphicsDeviceManager(this);
  14.         }
  15.  
  16.         protected override void Initialize()
  17.         {
  18.             base.Initialize();
  19.         }
  20.  
  21.         protected override void Update(GameTime gameTime)
  22.         {
  23.             if (Keyboard.GetState().IsKeyDown(Keys.Escape)) Exit();
  24.             base.Update(gameTime);
  25.         }
  26.  
  27.         protected override void Draw(GameTime gameTime)
  28.         {
  29.             base.Draw(gameTime);
  30.         }
  31.     }
  32. }
  33.  


Vårat svarta fönster ska fortfarande köras om vi trycker på F5.


För att kunna rita nånting på skärmen så måste vi ha två saker. En Textur och en Batcher eller SpriteBatcher som det heter i Monogame.

En Textur är ett objekt som närmast kan beskrivas som ett genomskinligt papper. När vi sen kommer rita i fönstret så är det som att vi slänger på fler och fler av dessa Textur-papper. PÅ ett papper har vi ett träd, ett annat ett hus och kanske en bakgrund med lite berg. alla dessa papper bygger tillsammans upp en färdig bild som vi sedan vill visa upp i fönstret.

Och det är med spritebatchen som hjälper oss med just den delen att komponera ihop och lagra alla papper i ordning. För det är något som är ganska tidskrävande för en dator.

Vi börjar med att skapa en textur, (ett genomskinligt papper). Det gör vi genom att deklarera en variabel som vi döper till papper av typen Texture2D, Texture2D ligger i ett nytt namespace som heter Graphics under MonogameFramework. Så vi måste lägga till det namespacet också.
Vi ska prata mer om vad en texture faktiskt egentligen är senare någon gång, papper kanske inte är den bästa liknelsen, men det tar vi då.

När vi deklarerat våran texture utanför konstruktorn så behöver vi i initiera den. Det gör vi i funktionen Initialize genom att skriva:
papper = new Texture2D(GraphisDevice, 1,1); GraphicsDevice är ett objekt som vi får av Monogame, men om vi skriver den här koden i konstruktor istället så har inte graphicsdevice blivit initierad än och vi kommer få ett null exception error på graphicsdevice. Om ett objekt inte initierats så har det värdet null. Vilket innebär att det inte har något värde alls. det är som en tom ballong.

GraphicsDevice måste iallafall vara med för att hjälpa oss bygga upp texturen, 1, 1 säger att texturen ska vara en pixel bred och en pixel hög.

Vi ska nu ha följande kod.

  1.  
  2. using Microsoft.Xna.Framework;
  3. using Microsoft.Xna.Framework.Graphics;
  4. using Microsoft.Xna.Framework.Input;
  5.  
  6. namespace GameTutorial
  7. {
  8.     public class GameTutorialGame : Game
  9.     {
  10.         GraphicsDeviceManager graphics;
  11.         Texture2D papper;
  12.  
  13.         public GameTutorialGame()
  14.         {
  15.             graphics = new GraphicsDeviceManager(this);
  16.         }
  17.  
  18.         protected override void Initialize()
  19.         {
  20.             papper = new Texture2D(GraphicsDevice, 1, 1);
  21.             base.Initialize();
  22.         }
  23.  
  24.         protected override void Update(GameTime gameTime)
  25.         {
  26.             if (Keyboard.GetState().IsKeyDown(Keys.Escape)) Exit();
  27.             base.Update(gameTime);
  28.         }
  29.  
  30.         protected override void Draw(GameTime gameTime)
  31.         {
  32.             base.Draw(gameTime);
  33.         }
  34.     }
  35. }
  36.  


Nu vill vi såklart rita ut vårat nya fina papper i fönstret. Det gör vi i Draw funktionen. Men först behöver vi ett nytt objekt. SpriteBatch som vi talade om tidigare. Det är ett ganska stort och invecklat objekt men vi tar en sak i taget utan att gå alldeles för långt ner på djupet.
Spritebatchen måste vi skapa sälva så vi deklarerar den tillsammans med vårat papper så här

  1.  
  2.         SpriteBatch spriteBatch;
  3.  

och i Initialize initierar vi den genom att skriva
  1.  
  2.         spriteBatch = new SpriteBatch(GraphicsDevice);
  3.  


Toppen, nu är allt klart för att börja rita.
Vi hoppar över till Draw funktionen och lägger till följande kod.

  1.  
  2.             spriteBatch.Begin();
  3.             spriteBatch.Draw(papper, new Rectangle(10,10,100,100), Color.White);
  4.             spriteBatch.End();
  5.  
  6.             base.Draw(gameTime);
  7.  


spriteBatch.Begin(); Säger att vi vill börja rita, talar vi inte omd et så kommer inte spritebatchen tillåta oss att rita nånting.
spriteBatch.Draw(papper, new Rectangle(10,10,100,100), Color.White); säger att vi vill rita vårat papper, vart den ska ritas anger vi med new Rectangel(10,10,100,100) vilket säger att vårat papper börjar 10 pixlar ifrån vänster och 10 pixlar ifrån toppen av vårat fönster. Sen säger den att vårat papper är 100 pixlar bred och 100 pixlar hög.


Rectangel(horisontellposition, vertikal position, bredd, höjd)



Color.White är lite krånglig, men den talar om vilken färg vi vill blanda med. Så den färgen vi skriver här kommer blanda sig med den färg som är på texturen som vi ritar. Det är också något som vi kommer till senare.

Men vad händer då om vi kör vårat program. Det händer ju ingenting..? Samma gamla svarta fönster... Som vi pratade om så är vårat papper genomskinligt och ett genomskinligt papper ska ju såklart vara osynligt att se. För att rita något på vårat papper så måste vi skriva en ny lite invecklad rad kod uppe i Initialize, efter att vi initierat vårat papper.


  1.  
  2. papper.SetData<Color>(new Color[] { Color.White });
  3.  


när vi initierade vårat papper sa vi att det skulle vara 1 pixel brett och 1 pixel högt. totalt består vårat papper av en pixel totalt och den pixeln fyller vi med fägen vit.
papper.SetData anger att vi vill ange färg som data för vad texturen ska inehålla. (För en textur kan vara och inehålla mycket annat än färg) sen anger vi en array av färger med endast en komponent, Vit.

Våran kod i sin helhet ser nu ut så här

  1.  
  2. using Microsoft.Xna.Framework;
  3. using Microsoft.Xna.Framework.Graphics;
  4. using Microsoft.Xna.Framework.Input;
  5. using System;
  6.  
  7. namespace GameTutorial
  8. {
  9.     public class GameTutorialGame : Game
  10.     {
  11.         GraphicsDeviceManager graphics;
  12.         SpriteBatch spriteBatch;
  13.         Texture2D papper;
  14.  
  15.         public GameTutorialGame()
  16.         {
  17.             graphics = new GraphicsDeviceManager(this);
  18.            
  19.         }
  20.  
  21.         protected override void Initialize()
  22.         {
  23.             spriteBatch = new SpriteBatch(GraphicsDevice);
  24.             papper = new Texture2D(GraphicsDevice, 1, 1);
  25.             papper.SetData<Color>(new Color[] { Color.White });
  26.  
  27.             base.Initialize();
  28.         }
  29.  
  30.         protected override void Update(GameTime gameTime)
  31.         {
  32.             if (Keyboard.GetState().IsKeyDown(Keys.Escape)) Exit();
  33.             base.Update(gameTime);
  34.         }
  35.  
  36.         protected override void Draw(GameTime gameTime)
  37.         {
  38.             spriteBatch.Begin();
  39.             spriteBatch.Draw(papper, new Rectangle(10,10,100,100), Color.White);
  40.             spriteBatch.End();
  41.  
  42.             base.Draw(gameTime);
  43.         }
  44.     }
  45. }
  46.  
  47.  


Vi kör igen och se på tusan vår första vita rektangel är ritad...


Det var allt för den här delen, men jag lämnar lite kodändringar som kan vara spännade att testa och leka med för att se vad som händer.

  1.  
  2. papper.SetData<Color>(new Color[] { Color.Blue});
  3.  

  1.  
  2. papper.SetData<Color>(new Color[] { Color.Red});
  3.  

  1.  
  2. spriteBatch.Draw(papper, new Rectangle(200,200,100,100), Color.White);
  3.  

  1.  
  2. spriteBatch.Draw(papper, new Rectangle(0,10,800,10), Color.Orange);
  3.  

  1.  
  2. spriteBatch.Draw(papper, new Rectangle(10,10,100,100), Color.White);
  3. spriteBatch.Draw(papper, new Rectangle(300,10,100,100), Color.White);
  4. spriteBatch.Draw(papper, new Rectangle(150,200,100,100), Color.White);
  5.  

Lite mer avancerat, fundera kring vad som händer här...
  1.  
  2. papper = new Texture2D(GraphicsDevice, 2, 1);
  3. papper.SetData<Color>(new Color[] { Color.Red, Color.Blue });
  4.  

Monogame del 1

Monogame är ett .Net bibliotek för c# med stöd för dom flesta populära plattformarna idag. Så som Windows, mac, linux, Android, Ios, och även ett flertal konsoler. Jag kommer bara rikta mig till Windows men det är nog inte några större problem att porta över koden till någon av dom andra operativsystemen.

Jag kommer inte gå in på hur du installerar Visual Studio. Det finns en uppsjö andra guider som tar upp det förfarandet. Googla på på How to install Visual Studio så kommer du garanterat hitta en uppsjö guider. För stunden så är det Visual Studio Community 2019 som gäller.

När det är klart så kan vi installera Monogame, det görs numera genom något som heter Nugets. Starta Visual studio och klicka på "continue without code" i fönstret som öppnas. Efter det så öppnas Visual Studio i sin helhet utan att ha skapat någon kod. Där klickar vi på Extensions uppe i menyraden och sedan Manage Extensions. Då öppnas ett nytt fönster och uppe i högra hörnet av fönstret så finns en liten sökruta som vi skriver monogame i och trycker enter.

Ett extension som heter monogame project templates dyker upp och på den klickar vi install.
När det är klart kan vi stänga det fönstret och sedan klicka på File-> New->Project...



Så öppnas ett nytt fönster. I den listan letar vi upp Monogame Windows Project och trycker Next. Här får vi namnge vårat projekt, jag väljer att döpa mitt till GameTutorial och sedan klickar vi på Create. På så vis så skapas det två basklasser och lite annat åt oss så att vi snabbt kan komma igång och skriva spel.

När vi trycker på F5 så kommer ett blått fönster att öppnas vilket innebär att allt fungerar som det ska.
Låt oss grotta ner oss i den här koden lite.


Två klasser är skapta i vårat projekt, en heter Program.cs och ser ut så här

  1.  
  2. using System;
  3.  
  4. namespace GameTutorial
  5. {
  6. #if WINDOWS || LINUX
  7.     /// <summary>
  8.     /// The main class.
  9.     /// </summary>
  10.     public static class Program
  11.     {
  12.         /// <summary>
  13.         /// The main entry point for the application.
  14.         /// </summary>
  15.         [STAThread]
  16.         static void Main()
  17.         {
  18.             using (var game = new GameTutorialGame())
  19.                 game.Run();
  20.         }
  21.     }
  22. #endif
  23. }
  24.  


  1.  
  2. static void Main()
  3.  

Här börjar vårat program genom att skapa en ny klass av typen GameTutorialGame. Den här typen är genererad utifrån vad vi döpte vårat projekt. Sedan körs game.Run() och vårat program kör igång.
Det är inte så mycket att tala om i den här klassen så vi hoppar över till den dåligt döpta klassen GameTutorialGame klassen.
Men först så tänkte jag att vi gör en lite lite ändring här i program.cs.

  1.  
  2. using System;
  3.  
  4. namespace GameTutorial
  5. {
  6. #if WINDOWS || LINUX
  7.     /// <summary>
  8.     /// The main class.
  9.     /// </summary>
  10.     public static class Program
  11.     {
  12.         /// <summary>
  13.         /// The main entry point for the application.
  14.         /// </summary>
  15.         [STAThread]
  16.         static void Main()
  17.         {
  18.             using (var game = new GameTutorialGame())
  19.             {
  20.                 game.IsFixedTimeStep = false;
  21.                 game.Run();
  22.             }
  23.         }
  24.     }
  25. #endif
  26. }
  27.  


Den raden måste till för att vi ska kunna forcera våran main loop att snurra fortare än 60 frames per sekund. Det är möjligtvis inget som rekomenderas, men det kan vara bra medans man bygger för att testa prestanda och så att allt flyter på i rätt takt. Men vi kommer till det senare. Nu hoppar vi över till Game klassen eller GameTutorialGame som den heter för mig.

Den här klassen har betydligt mer kod i sig, uppemot 100 rader. Men mycket kod är kommentarer, jag kan rekomendera att läsa igenom alla kommentarer och när du är klar med det så tar vi och markerar all kod och trycker delete. Sådär... Då kan vi börja bygga upp klassen igen och gå igenom dom funktioner som fins. Vilka vi behöver kommer vi till senare och vilka som är viktiga.

Vi börjar med att lägga till namespace för klassen, så att klassen tillhör rätt namespace. En namespace är som en virtuell mapp, alla klasser som skapas och använder sig av samma namespace kommer att hitta varandra. Men om du skapar en klass med ett annat namespace så måste du referera till den klassen genom att ange namespace antingen via deklareringen eller med using statement längst upp i klassen.
eftersom det här är en basklass som ligger längst ner i namespace hierarkin så får den här namespacet samma namn som projektet. så i mitt fall GameTutorial.
Så nu har vi följande kod.


  1.  
  2. namespace GameTutorial
  3. {
  4.  
  5. }
  6.  


Fint, glöm inte hak-klammrarna. Då är vi redo att skapa klassen, det gör vi genom att skriva


  1.  
  2. namespace GameTutorial
  3. {
  4.     public class GameTutorialGame
  5.     {
  6.     }
  7. }
  8.  


Att klassen deklareras som publik gör att man kan anropa klassen från ett annat projekt, det är inget vi kommer göra i den här guiden, men det kan vara fint att känna till.
Men nu blir Visual Studio lite sur och kastar några fel från Program klassen som vi tittade på tidigare. Det är för att våran klass måste ärva lite funktioner från en basklass som heter Game. För att fixa det så lägger vi till : Game efter vårat klassnamn. Men för att det ska funka så måste vi lägga till vårat första using statement längst upp i klass filen.

Så nu ser våran fil ut så här och vi borde vara fria från felmeddelanden.

  1.  
  2. using Microsoft.Xna.Framework;
  3.  
  4. namespace GameTutorial
  5. {
  6.     public class GameTutorialGame : Game
  7.     {
  8.     }
  9. }
  10.  

när vi skriver using Microsoft.Xna.Framework; så talar vi om för klassen att den behöver använda kod ifrån det här kodbiblioteket. Det här är kod som på ett eller annat sätt ligger utanför vårat projekt och det måste finnas externa referenser till det för att fungera. Det är ett lite mer avancerat ämne så vi kan tala om det senare. Vi litar på att Visual Studio gör sitt jobb och lägger till dom referenser som behövs.

Vi har inga felmeddelanden, men om vi provar att köra programmet så kommer det att krascha. Så vi måste skriva lite till innan vi kan köra programmet igen.

Nu är det dax för oss att lägga till en klass konstuktor. Det är den första funktionen som anropas när en klass skapas med "new" Om du mins i program klassen så stog det

  1.  
  2. using (var game = new GameTutorialGame())
  3.  

när man skriver new GameTutorialGame() så kommer lämplig konstruktor att anropas.
I det här fallet en konstruktor utan argument, så då vet vi hur våran konstruktor måste se ut.

  1.  
  2. public GameTutorialGame()
  3. {
  4. }
  5.  


Så nu har vi följande kod

  1.  
  2.  
  3. using Microsoft.Xna.Framework;
  4.  
  5. namespace GameTutorial
  6. {
  7.     public class GameTutorialGame : Game
  8.     {
  9.         public GameTutorialGame()
  10.         {
  11.  
  12.         }
  13.     }
  14. }
  15.  



Om vi kör programmet så kraschar det och säger att vi inte har någon "Graphics Device Service" Det löser vi lätt genom att deklarera en variabel som heter graphics av typen GraphicsDeviceManager och den måste vi initiera i konstuktorn av klassen.
Så nu ska koden se ut så här

  1.  
  2. using Microsoft.Xna.Framework;
  3.  
  4. namespace GameTutorial
  5. {
  6.     public class GameTutorialGame : Game
  7.     {
  8.         GraphicsDeviceManager graphics;
  9.  
  10.         public GameTutorialGame()
  11.         {
  12.             graphics = new GraphicsDeviceManager(this);
  13.         }
  14.  
  15.     }
  16. }
  17.  
  18.  


Trycker vi på F5 nu så körs vårat program utan fel och ett svart fönster öppnas. Inte illa med 17 rader kod.

Iomed att vi ärver våran klass från Game så finns det ett antal funktioner som vi kan skriva över, eller "överrida" ( override)
om vi skriver "protected override" så kommer Visual Studio visa ett antal funktioner som kan överridas, låt oss lägga till allihopa.

Jag har även lagg till en rad i varje funktion som skriver ut till terminalen varje gång funktionen anropas.
På så vis kan vi få lite klarhet vad respektive funktion gör och när den anropas.

Koden ser nu ut så här:


  1.  
  2. using Microsoft.Xna.Framework;
  3. using System;
  4.  
  5. namespace GameTutorial
  6. {
  7.  
  8.     public class GameTutorialGame : Game
  9.     {
  10.         GraphicsDeviceManager graphics;
  11.  
  12.         public GameTutorialGame()
  13.         {
  14.             graphics = new GraphicsDeviceManager(this);
  15.             Console.WriteLine("Konstuktor");
  16.         }
  17.  
  18.         protected override void Initialize()
  19.         {
  20.             Console.WriteLine("Initialize");
  21.             base.Initialize();
  22.         }
  23.  
  24.         protected override void LoadContent()
  25.         {
  26.             Console.WriteLine("LoadContent");
  27.             base.LoadContent();
  28.         }
  29.  
  30.         protected override void UnloadContent()
  31.         {
  32.             Console.WriteLine("UnloadContent");
  33.             base.UnloadContent();
  34.         }
  35.  
  36.         protected override void OnActivated(EventArgs args)
  37.         {
  38.             Console.WriteLine("OnActivated");
  39.             base.OnActivated(args);
  40.         }
  41.  
  42.         protected override void OnDeactivated(EventArgs args)
  43.         {
  44.             Console.WriteLine("OnDeactivated");
  45.             base.OnDeactivated(args);
  46.         }
  47.  
  48.         protected override void OnExiting(EventArgs args)
  49.         {
  50.             Console.WriteLine("OnExiting");
  51.             base.OnExiting(args);
  52.         }
  53.  
  54.         protected override void Dispose(bool disposing)
  55.         {
  56.             Console.WriteLine("Dispose");
  57.             base.Dispose(disposing);
  58.         }
  59.  
  60.         protected override void BeginRun()
  61.         {
  62.             Console.WriteLine("BeginRun");
  63.             base.BeginRun();
  64.         }
  65.  
  66.         protected override void Update(GameTime gameTime)
  67.         {
  68.             Console.WriteLine("Update");
  69.             base.Update(gameTime);
  70.         }
  71.  
  72.         protected override void EndRun()
  73.         {
  74.             Console.WriteLine("EndRun");
  75.             base.EndRun();
  76.         }
  77.  
  78.         protected override bool BeginDraw()
  79.         {
  80.             Console.WriteLine("BeginDraw");
  81.             return base.BeginDraw();
  82.         }
  83.  
  84.         protected override void Draw(GameTime gameTime)
  85.         {
  86.             Console.WriteLine("Draw");
  87.             base.Draw(gameTime);
  88.         }
  89.  
  90.         protected override void EndDraw()
  91.         {
  92.             Console.WriteLine("EndDraw");
  93.             base.EndDraw();
  94.         }
  95.     }
  96. }
  97.  
  98.  

Det börjar bli mycket nu, Console raderna kan vi ta bort senare men om vi kör programmet nu så kan vi se vilka funktioner som blivit anropade och i vilken ordning. Tryck på stopp knappen ganska omgående efter att du startat programmet annars kommer vissa funktioner spamma ut information och du kommer få svårt att se vad som händer i början.

Vi ser iallafall att följande funktioner anroppas i tur och ordning.
Konstuktor
OnActivated
Initialize
LoadContent
BeginRun
Update
Update
BeginDraw
Draw
EndDraw


Sedan körs update, begindraw Draw, endDraw i en oändlig loop.
Om vi lägger till följande kod utan någon närmare förklaring för tillfället

if (Keyboard.GetState().IsKeyDown(Keys.Escape)) Exit();

i Update(GameTime gameTime)
så kan vi avsluta programmet på ett korrekt sätt och se vad som händer när vi avslutar. Vi tar bort Consol -rader som vi redan sett anropas.
Den raden kräver att vi ladar in ett nytt namespace så om inte visula studio redan gjort det automatiskt så lägger vi till using Microsoft.Xna.Framework.Input; längst upp.

  1.  
  2. using Microsoft.Xna.Framework;
  3. using Microsoft.Xna.Framework.Input;
  4. using System;
  5.  
  6. namespace GameTutorial
  7. {
  8.  
  9.     public class GameTutorialGame : Game
  10.     {
  11.         GraphicsDeviceManager graphics;
  12.  
  13.         public GameTutorialGame()
  14.         {
  15.             graphics = new GraphicsDeviceManager(this);
  16.             Console.WriteLine("Konstuktor");
  17.         }
  18.  
  19.         protected override void Initialize()
  20.         {
  21.             Console.WriteLine("Initialize");
  22.             base.Initialize();
  23.         }
  24.  
  25.         protected override void LoadContent()
  26.         {
  27.             Console.WriteLine("LoadContent");
  28.             base.LoadContent();
  29.         }
  30.  
  31.         protected override void UnloadContent()
  32.         {
  33.             Console.WriteLine("UnloadContent");
  34.             base.UnloadContent();
  35.         }
  36.  
  37.         protected override void OnActivated(EventArgs args)
  38.         {
  39.             Console.WriteLine("OnActivated");
  40.             base.OnActivated(args);
  41.         }
  42.  
  43.         protected override void OnDeactivated(EventArgs args)
  44.         {
  45.             Console.WriteLine("OnDeactivated");
  46.             base.OnDeactivated(args);
  47.         }
  48.  
  49.         protected override void OnExiting(EventArgs args)
  50.         {
  51.             Console.WriteLine("OnExiting");
  52.             base.OnExiting(args);
  53.         }
  54.  
  55.         protected override void Dispose(bool disposing)
  56.         {
  57.             Console.WriteLine("Dispose");
  58.             base.Dispose(disposing);
  59.         }
  60.  
  61.         protected override void BeginRun()
  62.         {
  63.             Console.WriteLine("BeginRun");
  64.             base.BeginRun();
  65.         }
  66.  
  67.         protected override void Update(GameTime gameTime)
  68.         {
  69.             if (Keyboard.GetState().IsKeyDown(Keys.Escape)) Exit();
  70.             base.Update(gameTime);
  71.         }
  72.  
  73.         protected override void EndRun()
  74.         {
  75.             Console.WriteLine("EndRun");
  76.             base.EndRun();
  77.         }
  78.  
  79.         protected override bool BeginDraw()
  80.         {
  81.             return base.BeginDraw();
  82.         }
  83.  
  84.         protected override void Draw(GameTime gameTime)
  85.         {
  86.             base.Draw(gameTime);
  87.         }
  88.  
  89.         protected override void EndDraw()
  90.         {
  91.             base.EndDraw();
  92.         }
  93.     }
  94. }
  95.  
  96.  


Kör vi nu så får vi följande resultat
Konstuktor
OnActivated
Initialize
LoadContent
BeginRun

> Loopen startas här och följande funktioner körs tills programmet avslutas
Update
BeginDraw
Draw
EndDraw

> Här trycker vi på escape

OnDeactivated
EndRun
OnExiting
UnloadContent
Dispose


OnActivate och OnDeactivate anroppas var gång fönstret tappar och/eller återfår focus. Det kan vara bra att hålla reda på framöver ifall användaren tabbar ut från programmet, eller av annan aledning förlorar fokus från spelet, så man kan forcera in spelet i pause läge.
Det börjar bli ett jäkla längt inlägg nu så jag tror jag stannar här så kanske vi kan komma till lite mer roliga saker i nästa inlägg. Förhoppningsvis har vi lite koll på hur monogame anropar vårat spel. Inästa inlägg så ska vi se till att rita nånting i fönstret och kanske ta lite mer konfigurering av monogame.

Tack för visat intresse.