Microsoft XNA, część 2

10.05.2010 - Marcin Oczeretko
TrudnośćTrudność

    Niestety nie przetestujemy teraz, czy wszystko dobrze działa, z dwóch banalnych powodów. Po pierwsze w klasie Game1 są błędy wynikające z tego, że zmodyfikowaliśmy konstruktor klasy Player. Z drugiej strony postać gracza i tak dość szybko spadłaby poza ekran, gdyż wciąż nie zamknęliśmy jej wewnątrz prostokąta bounds. Zacznijmy więc od tego, a klasę Game1 naprawimy za chwilę. Przed base.Update(gameTime) dopiszmy kilka linii kodu, które zatrzymają gracza wewnątrz określonego obszaru:

Pokaż/ukryj kod
1
2
3
4
5
6
7
8
9
10
11
if (position.X < bounds.Left)
    position.X = bounds.Left;
else if (position.X + texture.Width > bounds.Right)
    position.X = bounds.Right - texture.Width;
if (position.Y + texture.Height > bounds.Bottom)
{
    position.Y = bounds.Bottom - texture.Height;
    speed.Y = 0;
}
else if (position.Y < bounds.Top)
    position.Y = bounds.Top;

    Teraz naprawmy kod w klasie Game1. Usuńmy pole:

1
private Player player;

    Zamiast niego zadeklarujmy tablicę z obiektami reprezentujacymi różnych graczy:

1
private Player[] players = new Player[2];

    Pozostaje jeszcze tylko naprawić kod w konstruktorze:

Pokaż/ukryj kod konstruktora
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public Game1()
{
    graphics = new GraphicsDeviceManager(this);
    Content.RootDirectory = "Content";
 
    players[0] = new Player(new Rectangle(5, 120, 390, 480),
                            new Vector2(160, 220), false,
                            Keys.W, Keys.S, Keys.A, Keys.D, this);
 
    players[1] = new Player(new Rectangle(405, 120, 390, 480),
                            new Vector2(600, 220), true, Keys.Up,
                            Keys.Down, Keys.Left, Keys.Right, this);
 
    Components.Add(players[0]);
    Components.Add(players[1]);
 
    ball = new Ball(this);
    Components.Add(ball);
}

    Teraz możemy już uruchomić grę i pobawić się chwilę, poruszając postaciami graczy.

    Jeszcze tylko kilka drobnych udoskonaleń i klasa Player będzie już całkowicie skończona. Następnie zajmiemy się klasą Ball i właściwie ukończymy tym samym pisanie gry.

    Najpierw jednak zauważmy, że wszystkie obiekty reprezentujące gracza korzystają z takiego samego obrazka. Nie ma zatem żadnego sensu ładowanie go dla obu graczy osobno. Zróbmy więc z pola texture pole statyczne.

1
private static Texture2D texture;

    Metodę LoadContent() wystarczy teraz zmodyfikować tak, by jej kod wyglądał jak ten zamieszczony poniżej. Dzięki temu nie przechowujemy w pamięci więcej jak jednego obrazka postaci gracza.

1
2
3
4
5
6
protected override void LoadContent()
{
    if (texture == null)
        texture = Game.Content.Load<Texture2D>("player");
    base.LoadContent();
}

    Powinniśmy też w końcu obrócić gracza znajdującego się po prawej stronie boiska, gdyż niewielu jest siatkarzy, którzy podczas rozgrywki cały czas stoją plecami do siatki. W tym celu skorzystamy podczas rysowania z innej wersji metody Draw() obiektu spriteBatch, która w parametrach przyjmuje np. przesunięcie (my podajemy Vector2.Zero), skalę (dla nas $ 1 $), czy też pożądany obrót (nie interesuje nas, stąd $ 0 $). Wykorzystamy tak naprawdę jedynie możliwość podania rodzaju odbicia, jakie należy wykonać - SpriteEffects.FlipHorizontally jest dokładnie tym, czego potrzebujemy, aby odpowiednio wyświetlać postać z prawej. Kod metody Draw modyfikujemy tak, by uzyskać:

Pokaż/ukryj kod metody Draw()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public override void Draw(GameTime gameTime)
{
    SpriteBatch spriteBatch =
               (SpriteBatch) Game.Services.GetService(typeof (SpriteBatch));
 
    if (!flip)
        spriteBatch.Draw(texture, position, null, Color.White, 0,
                    Vector2.Zero, 1, SpriteEffects.None, 0.5f);
    else
        spriteBatch.Draw(texture, position, null, Color.White, 0,
                    Vector2.Zero, 1, SpriteEffects.FlipHorizontally, 0.5f);
 
    base.Draw(gameTime);
}

    Jeszcze tylko ostatnie, najdrobniejsze zmiany. Dodajmy dwie stałe - positionOffset, która określać będzie położenie środka głowy względem rogu obrazka i radius, która przechowywać będzie promień głowy gracza.

1
2
private static readonly Vector2 positionOffset = new Vector2(40, 40);
private const float radius = 35;

    Dodajmy też trzy właściwości, które umożliwią pobranie pozycji środka głowy, jej promienia i aktualnej prędkości gracza:

Pokaż/ukryj kod właściwości
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public Vector2 Center
{
    get{ return position + positionOffset; }
}
 
public float Radius
{
    get{ return radius; }
}
 
public Vector2 Speed
{
    get { return speed; }
}

    Z tą chwilą klasa Player jest już oficjalnie ukończona. Nasza gra jest już prawie gotowa, musimy jeszcze jedynie stworzyć w porządny sposób obiekt reprezentujący piłkę.

5
Twoja ocena: Brak Ocena: 5 (1 ocena)

Copyright © 2008-2010 Wrocławski Portal Informatyczny

design: rafalpolito.com