Microsoft XNA, część 2

10.05.2010 - Marcin Oczeretko
TrudnośćTrudność

    Brakuje nam jeszcze tylko metody HandleNetCollision(). Wykorzystamy w niej zmienną netCollision, aby uniknąć przykrej sytuacji, kiedy lecąca szybko piłka przemieści się podczas jednej aktualizacji tak znacznie, że zablokuje się na siatce. Sprawimy więc, aby podczas jednej kolizji, piłka odbijała się dokładnie raz. Kolejne odbicie od siatki będzie możliwe, jeśli piłka oddali się od niej wpierw wystarczająco daleko (tzn. nie będzie przez jakiś czas kolidować z siatką). Kod omawianej metody wygląda następująco:

Pokaż/ukryj kod metody HandleNetCollision()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
private void HandleNetCollision()
{
    if (Center.X + Radius > net.Left && Center.X - Radius < net.Right)
    {
        if (Center.Y > net.Top + net.Width/2)
        {
            Bounce(Vector2.UnitX,0.5f,Vector2.Zero);
            if (Center.X < net.Left)
                position.X = net.Left - radius - positionOffset.X;
            else
                position.X = net.Right + radius - positionOffset.X;
 
            netCollision = false;
        }
        else
        {
            Vector2 diff = Center
                - new Vector2(net.Center.X, net.Top + net.Width/2);
                    
            if (diff.Length() < net.Width/2 + Radius)
            {
                if (!netCollision)
                    Bounce(diff, 0.3f, Vector2.Zero);
                netCollision = true;
            }
            else
                netCollision = false;
        }
    }
    else
        netCollision = false;
}

    Pomysł jest prosty - podzieliliśmy siatkę na dwie części. Przy jej "czubku" odbicie wyliczamy tak, jak dla koła, a dla dolnej części siatki tak, jak dla ściany. Piłka dzięki temu odbija się całkiem realistycznie. W linijkach $ 3-14 $ rozpatrujemy tę drugą opcję. Wektor diff łączy środek piłki i koła z górnej części siatki. Jeśli jego długość jest wystarczająco mała, to piłka odbija się ($ 23 $). W powyższym kodzie korzystamy kilka razy z nieistniejących jeszcze Center i Radius, które zwracają odpowiednio pozycję środka piłki i jej promień.

    Dodamy jeszcze brakujące dwie właściwości i klasa Ball jest również ukończona.

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

    To już prawie koniec. Musimy jeszcze jedynie sprawić, by piłka odbijała się od gracza i nieco zmodyfikować kod w klasie Game1. Zacznijmy od poprawienia w jej konstruktorze tworzenia instancji obiektu Ball. Musimy przecież podawać w nim odpowiednie parametry.

1
2
3
ball = new Ball(new Rectangle(20, 20, 760, 580),
                new Vector2(400, 300),
                new Rectangle(395,340,10,250), this);

    Kolizje z graczem będziemy traktować bardzo podobnie do kolizji z siatką. Aby uniknąć blokowania się piłki wewnątrz głowy postaci, zagwarantujemy, że przy jednej kolizji dojdzie do dokładnie jednego odbicia. Dodajmy zatem pole:

1
private bool[] playerCollided = new[]{false,false};

    Teraz w metodzie Update() dopiszmy wywołanie metody HandleCollisions(), której stworzeniem zajmiemy się za moment.

1
2
3
4
5
protected override void Update(GameTime gameTime)
{
    HandleCollisions();
    base.Update(gameTime);
}
5
Twoja ocena: Brak Ocena: 5 (1 ocena)

Copyright © 2008-2010 Wrocławski Portal Informatyczny

design: rafalpolito.com