Podstawy XNA - część druga 2278 0

O temacie

Autor Ezzam

Zaczęty 4.08.2012 roku

Wyświetleń 2278

Odpowiedzi 0

Ezzam

Ezzam

Użytkownicy
posty391
Propsy367
  • Użytkownicy

Ezzam

Podstawy XNA - część druga
2012-08-04, 14:44(Ostatnia zmiana: 2012-08-04, 19:38)
W tym tutorialu rozbudujemy stworzoną wcześniej przez nas grę. A więc do dzieła.

1. Rozbudowanie klasy Weight
Klasę Weight musimy wzbogacić o booleana:
       public Boolean IsFlying;Chcemy mieć do niego dostęp z pliku Game1.cs, więc musi być on publiczny. Upubliczniamy również teksturę, ponieważ będzie ona zmieniana w trakcie gry.
Dodajemy parametr do konstruktora i przypisujemy do niego pole:
       public Weight(Texture2D texture, Rectangle rectangle, Vector2 position, float gravity, Boolean isFlying)
        {
            Texture = texture;
            Rectangle = rectangle;
            Position = position;
            Gravity = gravity;
            IsFlying = isFlying;
        }
2. Nowe pola w Game1.cs
Stwórzmy teraz kolejne cztery pola:
       int score;
        Boolean isPlayerAlive;
        Random random;
        Texture2D weightTexture_2;
Int i boolean nie wymagają tłumaczenia, natomiast random jest generatorem liczb losowych. Do nowych pól przypiszmy teraz wartości w metodzie LoadContent()
           score = 0;
            isPlayerAlive = true;
            random = new Random();
            weightTexture_2 = Content.Load<Texture2D>("weight2");
Nowa tekstura:


3. Zmiany w metodzie Update()
Pierwszym, co rzuca się w oczy jest podkreślenie pod deklaracją nowego obiektu klasy Weight. Jest to spowodowane dodaniem nowego parametru do rzeczonej klasy. Żeby nie było błędów, do deklaracji trzeba dodać nowy parametr:
               Weight weight = new Weight(weightTexture, new Rectangle(mouseRectangle.X, mouseRectangle.Y, 64, 64), new Vector2(mouseRectangle.X, mouseRectangle.Y), 0f, true);Graczem chcemy ruszać tylko wtedy, kiedy jest żywy. By to osiągnąć, sterowanie postacią trzeba wsadzić w warunek if:
           if (isPlayerAlive == true)
            {
                if (Keyboard.GetState().IsKeyDown(Keys.Right))
                {
                    playerRectangle.X += 3;
                }
                if (Keyboard.GetState().IsKeyDown(Keys.Left))
                {
                    playerRectangle.X -= 3;
                }
            }
Dodajmy też warunek if do zrzucania odważników, by nie było to możliwe po śmierci postaci.
           if (Mouse.GetState().LeftButton == ButtonState.Pressed && canClick == true && isPlayerAlive == true)
            {
                Weight weight = new Weight(weightTexture, new Rectangle(mouseRectangle.X, mouseRectangle.Y, 64, 64), new Vector2(mouseRectangle.X, mouseRectangle.Y), 0f, true);

                weightList.Add(weight);
                canClick = false;
            }
Coś co zapomniałem wytłumaczyć w poprzednim tutorialu - && oznacza logiczne 'and', czyli by blok if był wykonany, wszystkie warunki muszą być spełnione.

W poprzednim tutorialu było małe niedopatrzenie - zrobiłem dwie pętle foreach w miejscu, gdzie można załatwić wszystko w jednej. Kopiujemy zawartość jednej pętli do drugiej, a niepotrzebną usuwamy.
           foreach (Weight weight in weightList)
            {
                weight.Position.Y += weight.Gravity;
                weight.Rectangle.Y = (int)weight.Position.Y;
                weight.Gravity += 0.1f;

                if (weight.Rectangle.Intersects(playerRectangle))
                {
                    playerRectangle.Y = -100;
                }
            }
Odważniki powinny spadać i uderzać w gracza tylko wtedy, kiedy są w powietrzu, a gracz żyje. W tym celu wstawiamy warunek do pętli foreach odpowiadającej za spadanie:
           foreach (Weight weight in weightList)
            {
                if (weight.IsFlying == true)
                {
                    weight.Position.Y += weight.Gravity;
                    weight.Rectangle.Y = (int)weight.Position.Y;
                    weight.Gravity += 0.1f;

                    if (weight.Rectangle.Intersects(playerRectangle) && isPlayerAlive == true)
                    {
                        playerRectangle.Y = -100;
                    }
                }
            }
Kiedy odważnik uderzy w ziemię, chcemy by się zatrzymał. W tym celu dodajemy kolejny warunek do pętli foreach:
if (weight.Rectangle.Intersects(groundRectangle))
                    {
                        weight.Rectangle.Y = 384;
                        weight.IsFlying = false;
                    }
Jeśli wykryta jest kolizja między odważnikiem a podłożem, odważnik jest ustawiany na wysokości 384 i zmieniana jest wartość pola odpowiadającego za jego latanie oraz zabijanie postaci.
Czas zaktualizować kolizje odważnika z graczem:
                   if (weight.Rectangle.Intersects(playerRectangle))
                    {
                        isPlayerAlive = false;
                        weight.Texture = weightTexture_2;
                    }
Teraz zamiast przemieszczać gracza w niewidoczne miejsce, zmieniamy wartość booleana. Zmieniamy również teksturę odważnika, który uderzył w gracza.

4. Zmiany w metodzie Draw()
Jeśli uruchomiliście grę po przeprowadzeniu zmian w Update(), zobaczyliście, że po uderzeniu odważnika w gracza, gracz nadal jest wyświetlany. Pora uzależnić jego wyświetlanie od booleana isPlayerAlive.
           if (isPlayerAlive == true)
            {
                spriteBatch.Draw(playerTexture, playerRectangle, Color.White);
            }
Mogliście zauważyć również, że gracz jest wyświetlany za odważnikami. Spowodowane jest to kolejnością rysowania - każda kolejna rzecz jest rysowana na poprzedniej. Żeby zmienić kolejność rysowania, wystarczy zmienić kolejność kodu - blok kodu stworzony przed chwilą należy przenieść pod pętlę foreach, która odpowiada za rysowanie odważników:
           foreach (Weight weight in weightList)
            {
                weight.Draw(spriteBatch);
            }
            if (isPlayerAlive == true)
            {
                spriteBatch.Draw(playerTexture, playerRectangle, Color.White);
            }
5. Pisanie tekstu i wyniki
Żeby mieć możliwość napisania czegokolwiek, trzeba stworzyć nowy SpriteFont. W tym celu zadeklarujmy:
       SpriteFont font;Teraz trzeba utworzyć plik czcionki. Żeby to zrobić, prawoklik na [Nazwa projektu]Content (Content)Add...New Item...Sprite Font. Wybieramy nazwę fonta (w moim przypadku score) i klikamy OK.
Teraz chwila o pliku XML stworzonego fonta. Omówię tu trzy najważniejsze rzeczy:
   <FontName>Segoe UI Mono</FontName>To oczywiście nazwa czcionki.

   <Size>14</Size>Kolejna oczywistość - rozmiar czcionki.

   <CharacterRegions>
      <CharacterRegion>
        <Start>& #32;</Start>
        <End>& #126;</End>
      </CharacterRegion>
    </CharacterRegions>
Ten kawałek kodu odpowiada za to, jakie znaki wpakować do czcionki. Domyślnie nie ma w niej polskich znaków. Żeby były one dostępne, trzeba rozszerzyć CharacterRegion - między znacznikami <End> i </End> wpisać & #399;Dzięki temu czcionka będzie zawierała cały pakiet znaków Łaciński Rozszerzony - B. Ważne - Kody symboli nie mają spacji między & i #.

Wracamy do Game1.cs. W LoadContent() przypisujemy polu font naszego spritefonta:
           font = Content.Load<SpriteFont>("score");Teraz możemy zająć się aktualizacją wyniku. Za każdy odważnik którego uniknęliśmy zostanie dodany punkt. Należy zaktualizować kod kolizji odważnika z podłożem.
                   if (weight.Rectangle.Intersects(groundRectangle))
                    {
                        weight.Rectangle.Y = 384;
                        weight.IsFlying = false;

                        if (isPlayerAlive == true)
                        {
                            score += 1;
                        }
                    }
Punkt jest dodawany, jeśli odważnik uderza w ziemię, a gracz żyje. Wynik trzeba jeszcze narysować.
W metodzie Draw() dopisujemy:
           spriteBatch.DrawString(font, "Wynik: " + score.ToString(), new Vector2(10, 10), Color.Black);DrawString przyjmuje cztery parametry: czcionkę, tekst, wektor i kolor. Przed napisaniem wyniku (pole score) trzeba go skonwertować do stringa, czym zajmuje się metoda ToString.

6. Liczby losowe
Chcemy, by odważniki były zrzucane w losowych miejscach. Najpierw zmieńmy trochę kod aktualizacji pozycji odważników:
weight.Position.Y += weight.Gravity;
                    weight.Rectangle.Y = (int)weight.Position.Y;
                    weight.Rectangle.X = (int)weight.Position.X;
                    weight.Gravity += 0.1f;
Dzięki temu pozycja pozioma prostokątów jest równa pozycji poziomej wektora.
Teraz zmieńmy kod odpowiadający za zrzut odważników:
Weight weight = new Weight(weightTexture, new Rectangle(0, 0, 64, 64), new Vector2(random.Next(0,737), -64), 0f, true);Prostokąt ustawiamy w pozycji 0,0 ponieważ aktualizuje się on względem wektora. Do wektora z kolei przypisujemy wartość X losowaną spomiędzy 0 a 736 (736, nie 737) i wartość Y równą -64.

7. Posłowie
Kolejny tutorial ukończony. Oczywiście czekam na komentarze, krytykę, pytania etc.

Źródło projektu: https://dl.dropbox.com/u/67704253/Xna%20Tutorial/2/source2.zip
 


0 użytkowników i 1 Gość przegląda ten wątek.
0 użytkowników
Do góry