2012-04-29 12 views
5

Tworzę grę Java za pomocą kafelków. Mam problem z elementem kolizji. Definiuję prostokąty dla każdego pola na mapie i inny prostokąt dla gracza. Z czym mam problem, to wiedzieć, po której stronie gracz nadchodzi, kiedy trafi w prostokąt, a następnie odepchnąć gracza w kierunku, z którego przybył gracz. Zrobiłem już metodę, która sprawdza, jak bardzo postać znajduje się wewnątrz prostokąta, więc może wiedzieć, ile ją wypycha, ale nie potrafię określić, z której strony pochodzi postać.Gra w płytki Java - Wykrywanie kolizji

tutaj jest mój obecny kolizja methoe - uwaga rect1 jest charakter i rect2 jest dachówka

public void collision(Rectangle rect1, Rectangle rect2) { 
    float xAdd; 
    float xAdd2; 
    float yAdd; 
    float yAdd2; 

    boolean hitRight = false; 
    boolean hitLeft = false; 
    boolean hitTop = false; 
    boolean hitBot = false; 

    Vector2f rect1Origin = new Vector2f(rect1.x, rect1.y); 
    Vector2f rect2Origin = new Vector2f(rect2.x, rect2.y); 
    Vector2f rect1Mid = new Vector2f((rect1.x + rect1.width)/2,(rect1.y + rect1.height)/2); 
    Vector2f rect2Mid = new Vector2f((rect2.x + rect2.width)/2,(rect2.y + rect2.height)/2); 

    Vector2f rect1A = new Vector2f(rect1Origin.x + rect1.width, rect1.y); 
    Vector2f rect1B = new Vector2f(rect1Origin.x, rect1Origin.y+ rect1.height); 
    Vector2f rect1C = new Vector2f(rect1Origin.x + rect1.width,rect1Origin.y + rect1.height); 

    Vector2f rect2A = new Vector2f(rect2Origin.x + rect2.width, rect2.y); 
    Vector2f rect2B = new Vector2f(rect2Origin.x, rect2Origin.y 
      + rect2.height); 
    Vector2f rect2C = new Vector2f(rect2Origin.x + rect2.width, 
      rect2Origin.y + rect2.height); 

    xAdd = rect2C.x - rect1B.x; 
    xAdd2 = rect1C.x - rect2B.x; 

    yAdd = rect2A.y - rect1B.y; 
    yAdd2 = rect2C.y - rect1A.y; 


    if (rect1Mid.y < rect2Mid.y) { 
     if (rect1.intersects(rect2)) { 
      y_pos += yAdd; 
     } 
    } 
    if (rect1Mid.y > rect2Mid.y) { 
     if (rect1.intersects(rect2)) { 
      System.out.println(yAdd2); 
      y_pos += yAdd2; 
     } 

    } 
    if(rect1Mid.x > rect2Mid.x){ 
     if(rect1.intersects(rect2)){ 
      hitRight = true; x_pos += xAdd; 
     } 
    } 
    if(rect1Mid.x< rect2Mid.x){ 
      if(rect1.intersects(rect2)) { 
       x_pos += -xAdd2; 
      } 
    } 
} 

Każda pomoc będzie mile widziana

Dzięki

Odpowiedz

2

utrzymać dwie pozycje dla swojej postaci - gdzie to jest (jak w ostatnim kadrze, ruchu, itp.) i gdzie chcesz go przenieść. Następnie przenieś go tylko wtedy, gdy nie wykryjesz kolizji - jeśli nie zezwolisz na uszkodzony stan, nie musisz go naprawiać.

Edit: Sposób collision powinny być boolean - powinno się to odbywać przed faktycznie przesuwając charakteru, jak

if (!collision(character, tile)) 
{ 
    doMove(character); 
} 
else 
{ 
    //custom handling if required 
} 

Edit2: Poprzedniego będzie działać tylko dla małego kroku, jeśli potrzebujesz częściowego ruchu, musisz znać oryginalną pozycję postaci, np. move(originalPosition, desiredPosition, tile), gdzie możesz wywnioskować kierunek od originalPosition i tile.

Najważniejsze jest to, że właściwie nie poruszasz postacią, zanim nie uzyskasz dla niej prawidłowej pozycji.

+0

To doprowadzi do dziwnej sytuacji, w zależności od przedziału czasu. – Matzi

+0

@Matzi Niezupełnie rzecz biorąc, sprawdzanie poprawności przed wykonaniem polecenia użytkownika - jeśli nie zostanie zatwierdzone, można wykonać obsługę niestandardową. – jmruc

+0

@KirilRaychev Naprawdę nie rozumiem co próbujesz powiedzieć – grimrader22

1

Przede wszystkim każdy Sprite (znak i kafelek tutaj) powinien mieć czterech członków: xPos, yPos, xVec, yVec. Mając to na uwadze, wiesz, gdzie postać była i będzie w następnej ramce.

sprite.xPos += sprite.xVec; 
sprite.yPos += sprite.yVec; 

wziąć również spojrzeć na kod, należy poprawić propozycji (na przykład, jeśli sprawdzeniu (rect1.intersects (rect2)) w cztery jeżeli sprawozdania). Zamiast tego sprawdź tylko jeden raz, aby przecinał(), a wewnątrz sprawdzał każdy możliwy przypadek (lewy, prawy, górny, dolny traf).

Wreszcie, sposób kolizją otrzymać 2 ikonek przedmiotów (na przykład, Sprite1 i sprite2), a następnie sprawdzić na przecina() sposobu, biorąc pod uwagę pozycji wyjściowych obu ikonek oraz jego wektory. Jeśli sprite przecinają się w nowej pozycji, to odpowiednio odwracasz wektor obiektu.

+0

Co oznaczają zmienne xVec i yVec? – grimrader22

+0

Przepraszam, nie byłam tak jasna, to są kierunkowe wektory sprite'a (można też użyć Vector2f lub Point2D). Wartość można interpretować jako prędkość duszka w każdym kierunku. Więc jeśli postać trafi na kafelek dokładnie od lewej, xVec jest wartością dodatnią, a yVec jest równe 0; a po trafieniu xVec powinien mieć tę samą wartość, ale teraz ujemną. Daj mi znać, jeśli potrzebujesz dodatkowej pomocy. –

+0

Nie bardzo rozumiem, co mówisz, przepraszam, jeśli jestem głupi. Czy xand y Vecs byłyby prędkością? – grimrader22

1

Zakładając, że można wykryć kolizję z kodem. Oto sposób na określenie pozycji twojej postaci względem obiektu prostokąta.

  1. Znajdź środkowy punkt prostokąta. (Rx, Ry).

  2. Znajdź środkowy punkt sprite'a twojej postaci. (Sx, Sy).

  3. Teraz można porównać Rx, Ry, Sx, Sy, aby określić, w którym strona jest Sx i Sy z Rx i Ry

  4. dla ex:

    if Sx < Rx then 
        Sx = left side of Rx 
    
1

zmagała się z to sam, ale po pewnym zastanowieniu to sprawdzenie można zrobić, mając wszystkie swoje jednostki na liście, w moim kodzie musiałem zablokować graczowi przejście przez bloki. Wszystkie bloki znajdują się na liście. Teraz, podczas sprawdzania pozycji graczy, tworzę nowy prostokąt i umieszczam graczy w jednej klatce do przodu w kierunku, w którym aktualizacja nastąpi w następnej klatce, jeśli prostokąt przecina aktualizację dla tego kierunku, nie nastąpi. Herezje mój kod to:

if (isKeyPressed(KeyEvent.VK_LEFT)) { 
     if(!collisionWithBlocks(1)){ 
      pl.x = pl.x - updatePlayerPosition; 
     } 
    } 
    if (isKeyPressed(KeyEvent.VK_RIGHT)) { 
     if(!collisionWithBlocks(0)){ 
      pl.x = pl.x + updatePlayerPosition; 
     } 
    } 
    if (isKeyPressed(KeyEvent.VK_UP)) { 
     if(!collisionWithBlocks(3)){ 
      pl.y = pl.y - updatePlayerPosition; 
     } 
    } 
    if (isKeyPressed(KeyEvent.VK_DOWN)) { 
     if(!collisionWithBlocks(2)){ 
      pl.y = pl.y + updatePlayerPosition; 
     } 
    } 

collisionWithBlocks():

public boolean collisionWithBlocks(int side){ 
    for(Block b : main.blocks){ 
     Rectangle block = b.getBounds(); 
     Rectangle player = null; 
     if(side == 0){ 
      player = new Rectangle(pl.x + updatePlayerPosition, pl.y, pl.getWidth(), pl.getHeight()); 
     } else if(side == 1){ 
      player = new Rectangle(pl.x - updatePlayerPosition, pl.y, pl.getWidth(), pl.getHeight()); 
     } else if(side == 2){ 
      player = new Rectangle(pl.x, pl.y + updatePlayerPosition, pl.getWidth(), pl.getHeight()); 
     } else if(side == 3){ 
      player = new Rectangle(pl.x, pl.y - updatePlayerPosition, pl.getWidth(), pl.getHeight()); 
     } 

     if(player.intersects(block)){ 
      return true; 
     } 
    } 

    return false; 
} 

updatePlayerPosition wynosi 2, a zmiany w kodzie, ale dość o tym. W twoim przypadku polecam umieszczenie obiektów na liście, a następnie sprawdzanie, jak to zrobiłem.

Powiązane problemy