Operacje wykonywane w grach komputerowych przetwarzane są pętlach. W technologii XNA, specjalnie stworzonej do tworzenia gier, uporządkowano ten proces, porządkując logicznie wielość wykonywanych operacji w czasie tak, aby pewne metody uruchamiały się w tej samej kolejności tworząc jakby jeden obieg. Taki obieg w XNA 3.1 przedstawia się następująco (poniżej dodaję też przykłady kodu):
1. Główna aplikacja (Main) uruchamia konstruktor Gry
(klasy dziedziczącej po klasie Game).
{
using (GameXna game = new GameXna()) // 1. tutaj
{
game.Run(); // od 3. tutaj
}
}
2. Konstruktor gry tworzy komponenty gry i uruchamia ich konstruktory
(konkretnie to my jako programiści je dostarczamy implementując klasy dziedziczące po GameComponent i dodając je w konstruktorze do kolekcji Components naszej gry).
{
this.graphics = new GraphicsDeviceManager(this);
this.Content = new ContentManager(Services);
this.GameObjectManager = new GameObjectsManager();
Content.RootDirectory = "Content";
#if DEBUG
fps = new FPS(this); //2.tutaj
Components.Add(fps);
#endif
input = new InputHandler(this); //2.tutaj
Components.Add(input);
camera = new FirstPersonCamera(this); //2.tutaj
Components.Add(camera);
//itd.
}
3. XNA uruchamia metodę Initialize z głównej klasy Gry.
{
//3. tutaj (tworzymy podstawowe elementy, obiekty gry)
base.Initialize(); //tutaj punkt 4.
}
4. XNA uruchamia metodę Initialize z każdego zarejestrowanego komponentu gry.
(Musimy wywołać base.Initialize() powyżej)
5. XNA uruchamia metodę LoadGraphicsContent każdego zarejestrowanego „rysującego się” komponentu.
(Komponenty mogą dziedziczyć bezpośrednio po klasie DrawableGameComponent. Zwyczajowo w tej metodzie dodaje się tekstury, modele itp.)
6. Framework XNA uruchamia metodę LoadGraphicsContent.
{
texture = Content.Load<Texture2D>("Textures\\obraz");
if (loadAllContent)
{
this.GameObjectManager.GetObject("car").Model = Content.Load<Model>("Models\\ford");
}
}
7. Framework XNA uruchamia metodę LoadContent
{
// tworzymy SpriteBatch do rysowania tekstur
spriteBatch = new SpriteBatch(GraphicsDevice);
}
8. Framework XNA uruchamia metodę BeginRun()
9. Framework XNA uruchamia metodę Update.
{
//umożliwia wyjście z gry;]
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
{
this.Exit();
}
//tutaj jest miejsce na logikę gry
base.Update(gameTime); //10.tutaj
}
10. Framework XNA uruchamia metodę Update każdego zarejestrowanego komponentu.
(Musimy uruchomić base.Update z powyższego punktu)
11. Framework XNA uruchamia metodę Draw.
(Właściwie to każda taka metoda poprzedzana jest uruchomieniem metod BeginDraw i EndDraw, które też możemy oprogramować!)
12. Framework XNA uruchamia metodę Draw każdego zarejestrowanego „rysującego się” komponentu.
13. Framework XNA przechodzi do punktu 9.
14. Jeśli utracimy połączenie z urządzeniem, wtedy Framework XNA uruchamia metodę UnloadGraphicsContent.
(Utrata połączenia z urządzeniem (dostępu do device) może być spowodowana np. próbą przesunięcia okna gry na inny monitor, zmianą rozdzielczości, zminimalizowaniem okienka itp.)
15. Jeśli urządzenie jest zresetowane, wtedy Framework XNA przechodzi do punktu 6.
16. Gracz wychodzi z gry i XNA Framework uruchamia wtedy metodę EndRun
(Przy okazji wychodzenia z gry przed metodą EndRun „leci” zdarzenie OnExiting, które też możemy nadpisać)
17. Framework XNA uruchamia metodę Dispose gry.
18. Metoda Dispose uruchamia Dispose klasy bazowej, co powoduje, że…
19. Framework XNA uruchamia metodę Dispose każdego zarejestrowanego komponentu.
20. Framework XNA uruchamia metodę UnloadGraphicsContent gry.
21. Metoda Dispose gry przywraca spowrotem swój focus i gra się kończy.
I w zasadzie tyle:) Oczywiście są jeszcze pewne zdarzenia, które możemy zwyczajowo nadpisać, takie jak: OnActivated, OnDeactivated czy OnExiting, lecz nie jest tego już dużo (wszystkie możliwości ładnie podpowie nam Visual Studio po wpisaniu ‘public override’ i wciśnięciu spacji). Przede wszystkim jednak właściwie wszystko można ładnie obsłużyć dodając pewne nowe funkcjonalności do gry w postaci komponentów gier, które po umieszczeniu w kolekcji Components w konstruktorze gry… same się aktualizują wewnątrz głównej pętli (jak widać powyżej). Póki co u mnie takimi komponentami są FPS do wyświetlania szybkości działania gry, InputHandler do obsługi stanów klawiatury oraz myszki (można też obsłużyć „Pada”) oraz FirstPersonCamera do obsługi kamery z poziomu użytkownika. A wszystko to ładnie dodane i oprogramowane w oddzielnej bibliotece, z której korzysta mój projekt gry. Taka koncepcja naprawdę dobrze rokuje, a na dodatek przyśpiesza proces tworzenia gry od początku – mamy wszystko to czego potrzeba do szkieletu gry dostarczone wprost z frameworka XNA i nie musimy sami praktycznie niczego już pisać:)

