[tutorail][C#][XNA 4.0] 2 - Ogólna budowa aplikacji w frameworku


Witam w 2 części tutka. Teraz będzie mowa o ogólnej budowie gry w XNA 4.0.
Poznamy podstawowe zmienne oraz metody...

Aktualizacja: 3 luty 2012 19:00


Gdy tworzymy grę "WindowsGame" naszym oczom ukazuje się solucja a w niej plik "Program.cs" oraz najważniejszy plik "Game1.cs". Kod w Program.cs sprawdza za pomocą dyrektywy pre procesora czy aplikacja jest uruchomiona na systemie Windows albo XBOX a jeśli tak wykonywana jest funkcja Main która załącza wykonywanie się pliku Game1.cs.

 Oczywiście na górze mamy już automatycznie dodane skróty do nowych bibliotek XNA:
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

jak i inne Systemowe rzeczy.

1.Metody
Niżej mamy przestrzeń nazwy naszej aplikacji w niej jeszcze przed inicjacją klasy "Game1" możemy utworzyć interesujące nas struktury które potem będziemy wykorzystywać. Pod klasą natomiast możemy dodawać zmienne które przydadzą się i będziemy wykorzystywać w dalszej części projektu. Np: Textury, długość i szerokość ekranu informacje o graczu jak i o liczbie graczy itd.

Dalej mamy metodę Game1() w której ustalamy interfejs graficzny i folder zawierający zasoby nasze aplikacji(tekstury,czcionki,dźwięk), są to rzeczy które powinny zostać utworzone wraz z utworzeniem klasy Game1.

Potem w metodzie Initialize() możemy dodawać rzeczy które będziemy potrzebowali zainicjować na początku działania aplikacji m.in: szerokość i wysokość ekranu, tryb pełnoekranowy, nazwę paska aplikacji itd. oczywiście wszystko umieszczamy pomiędzy nawiasem zaczynającym metodę a instrukcją base.Initialize();

Następnie w funkcji LoadContent() ładujemy odpowiednie pliki do naszej aplikacji jak dźwięk i tekstury,modele
i graczy

Po tej funkcji mamy funkcję UnloadContent() do niszczenia wczytanych obiektów. Jeśli używamy jakiś innych bibliotek zewnętrznych to tutaj należy wywołać metody je zamykające.

Powyższe funkcje inicjują się tylko raz na początku uruchomienia aplikacji, z wyjątkiem ostatniej, która uruchamia się wraz z końcem działania aplikacji

Dalej mamy funkcję Update jest to funkcja wykonywana co 1/60 s(dokładniej 1 / 58 według źródeł) a wszystkie wykonywane w niej metody odbywają się na CPU czyli procesorze naszej maszyny więc ta metoda służy do obliczeń. kod wstawiamy po początku metody i przed instrukcją  base.Update(gameTime);


natomiast metoda Draw służy do wyświetlania grafiki i tam umieszczamy elementy które mają być wyświetlane na planszy/aplikacji kod wpisujemy przed instrukjcą  base.Draw(gameTime);
a pomiędzy funkcje[którą musimy najpierw zainicjować na początku klasy naszej gry i wczytać w metodzie LoadContent()]:
            spriteBatch.Begin();
            ...
            spriteBatch.End();



2 Zmienne:
Teraz przydałoby się powiedzieć coś więcej na temat zmiennych jakich będziemy używać w Xna:
Vector2 Position;
zawira w sobie 2 zmienne w których przechowywane są pozycje
//np:

            players[0].Position = new Vector2(100, 193);


Color Color;
definiujemy w nich kolor
//np:
            player[0].Color = Color.Red;
            player[1].Color = Color.Green;



Texture2D backgroundTexture;
Są to nasze pojemniki na obrazy
//np:
        Texture2D backgroundTexture;
        Texture2D foregroundTexture;
        Texture2D carriageTexture;
        Texture2D cannonTexture;
//ładowanie tekstur:
            backgroundTexture = Content.Load<Texture2D>("background");
            foregroundTexture = Content.Load<Texture2D>("foreground");
            carriageTexture = Content.Load<Texture2D>("carriage");
            cannonTexture = Content.Load<Texture2D>("cannon");
SpriteFont font;
- Zmienna przechowywująca tekst
// inicjalizacja zmiennej z tekstem
font = Content.Load<SpriteFont> ("myFont");

SpriteBatch spriteBatch; //funkcja odpowiedzialna za rysowanie


3. Opis funkcji:
 spriteBatch.Draw(carriageTexture, player.Position, null, Color.White, 0, new Vector2(0, carriageTexture.Height), 1, SpriteEffects.None, 0);

Funkcja służy do rysowania 2D; oznaczenia kolejnych argumentów:
1.Jest to zmienna do której przypisaliśmy obraz do rysowania
2.Docelowa pozycja wyrażona w pikselach
3.Tutaj określamy jaka część obrazu ma zostać narysowana. Przydatne w Spritach czyli kilku obrazkach w jednym dużym
4. Kolor modulacji, jako podstawowy daje się biały ponieważ na niego składają się wszystkie inne w maksymalnej barwie RBG służy to do modyfikowania obrazu wynikowego
5.Określa obrót obrazu.
6.Określa o ile przesunąć obraz w pikselach względem początkowej pozycji 0,0 - służy do pozycjonowania obrazu tak by łatwiej było go ustawiać np. jeśli chciałbyś położyć klocek na podłożu o współrzędnych y = 0 a klocek byłby wysoki na 2 jedostki  to po narysowaniu klocka w pozycji (0,0) zawierałby się w przedziale y=(0,-2) czyli byłby pod ziemią!




Czerwona kropka – oś obrotu

 

my natomiast chcieliśmy by był na ziemi a na dodatek nie chcemy się zbytnio przemęczać i określać jego
przesunięcia do góry w zależności od jego wysokości. Wykorzystujemy tutaj więc zmienną: carriageTexture.Height  utworzoną dla naszego obrazka w której zawarta jest jego wysokość. Teraz nasz obraz będzie automatycznie podnoszony do góry o swoją wysokość(w tym wypadku o 2) i będzie poprawnie wyświetlany. Trzeba również dodać że tym sposobem zmieniamy również środek obrotu obrazka:
Czerwona kropka – oś obrotu

7. Skala naszego obrazu
8.Ustawienia efektów specjalnych
9.kanał Alpha czyli przeźroczystość

Oczywiście istnieje możliwość użycia tej funkcji z mniejszą ilością parametrów

4. Budowa widoku gry w XNA 4.0:
W XNA wykorzystuje się nieco inny układ współrzędnych do wyświetlania grafik niż ten znany nam z lekcji matematyki:

 Różnica polega na tym że w tym układzie oś Y rośnie ku dołowi zaś maleje ku górze, natomiast w Kartezjańskim o którym się uczymy w szkole Y rośnie ku górze i maleje ku dołowi. Początkowym problemem może być przestawienie się, jednak później nie będzie stanowiło to większego problemu dla nas.

Warto zauważyć tutaj również pewną ciekawą rzecz. Mianowicie jeśli metodzie SpriteBatch każemy namalować obraz 2 to funkcja namaluje go nam na ekranie, natomiast gdy każemy jej namalować obraz 1 to nasza funkcja również "namaluje" obraz 1 ale go nam nie wyświetli bo zawsze będzie się znajdować poza jego ramą.
Z malowaniem obrazu chodzi o to że funkcja SpriteBatch przetworzy obiekt(obraz) który każemy jej namalować tak samo nie ważne czy będzie przez nas widziany czy tez nie.
Dlatego ważnym aspektem gry będzie stworzenie odpowiedniej optymalizacji by takiej rzeczy uniknąć i malować tylko to co gracz będzie miał przed oczyma.


Po zapoznaniu się z tymi funkcjami i zmiennymi zapraszam do kolejnej części mojego tutka w której zaczniemy pisać kod:)