Strzelanie 2D - wykrywanie kolizji.

0

W jaki sposób mogę napisać kolizję strzałów na mapie składającej się z pół każde 32x32 pixeli?

Podrzucam rysunek obrazujący sprawę:

Untitled.png

Czerwona gwiazdka - miejsce gdzie powinna nastąpić kolizja.
Rozwazam dwa przypadki - koniec czerwonej linii / brązowej to położenie kursora, kolizja powinna nastąpić w obu przypadkach w tym samym miejscu.

W zasadzie to trzeba tylko wyznaczyć ten punkt na podstawie koordynatów myszki oraz gracza, ale nie mam pojęcia jak to zrobić. Kombinuje już któryś dzień z rzędu, ale wszystkie rozwiązania które przychodzą mi do głowy są strasznie kosztowne i mimo wszystko mam problem z ich implementacją.
Każde pole ma przypisane w tablicy dwuwymiarowej 1 bądź 0, gdzie 0 to pola na których nie powinno być kolizji (na rysunku białe) zaś na 1 powinna zajść (na rysunku szare).
Mógłby ktoś podpowiedzieć jak się za to zabrać?

2

Podziel składowe x, y przez wielkość kratki i przyrównaj do swojej 2-wymiarowej mapy

Wyjdzie Ci coś w stylu
bool collides = map.testCollision(translatedPos);

Jak spróbujesz dokładniej przedstawić co potrzebujesz to strzelę Ci przykład w rubim

0

Właśnie podobnie chciałem to zrobić, ale nie mam pojęcia jak wyznaczyć ten punkt kolizji za pomocą koordynatów myszki i gracza.

1

Zrób to co powiedziałem i przesuń sobie to według położenia kamery, przetłumaczonego uprzednio w ten sam sposób :P

0

Tylko, że nie ma żadnej kamery. Gra jest na widoku z góry i docelowo ma to być coś w stylu areny.

1

To jaki właściwie masz problem? Nie ma kamery, to wracamy do gołego pierwszego postu.

Wytłumacz dokładnie to jutro zrobie Ci przykład

0

Podstawowe pytanie: na jakim etapie edukacyjnym jesteś?
Funkcje trygonometryczne przerabia się w liceum, a do tego właśnie są one potrzebne (i wydaje mi się, że zauważyłbyś to, gdybyś znał zastosowanie tangensa) :P

0

W sumie to na studiach.
Próbowałem użyć tangensa, z współczynnika kierunkowego prostej ale nie mogłem wpaść na nic co dalej.. Potem próbowałem wyznaczyć wszystkie pola z którymi przecina się prosta a potem wyznaczyć który z nich jest najbliżej ale wydaje się to zbyt obciążające obliczeniowo i jednocześnie niewygodne.

Problem jest taki, że nie mam zielonego pojęcia jak wyznaczyć ten punkt zaznaczony gwiazdką - nawet jeżeli go nie potrzeba to chciałbym go wyznaczyć aby potem narysowac dziurę po kuli w ścianie. A jak istnieje jakiś sposób w którym nie trzeba go wyznaczać to go nie rozumiem. Kiedy policze tak jak mówisz x/32 i y/32 to dostanę to pole na które została kliknięta myszka a wcale nie musi byc kliknięta na ścianę i co dalej?

1

Musisz wyznaczyć półprostą zaczynającą się od gracza i przechodzącą przez celownik (mysz).
Następnie musisz sprawdzić czy ta półprosta koliduje z którymkolwiek z bloczków (sprawdzając każdy bloczek*), i jeśli tak - to gdzie koliduje (to Ci już wyjdzie z przekształcenia wzorów).

* tak naprawdę nie trzeba sprawdzać absolutnie każdego bloczku - można by wykorzystać na przykład kd-drzewo czy tez BSP, aby zmniejszyć złożoność, lecz na początek pomińmy to.

0

Dalej na tym stoję.. Spróbujmy krok po kroku.

Tak wygląda moja klasa z pociskami:

public class Bullet extends GameObject{
	
	class Point2d{
		int x,y;
		public Point2d(int x, int y)
		{
			this.x=x;
			this.y=y;
		}
	}

	private int targetX,targetY; //Współrzędne kursora myszki
	private double a,b; // Współczynniki prostej
	public Bullet(int x, int y, ID id, Game game, int targetX, int targetY, double accuracy) {   //x,y współrzędne lufy broni, accuracy to ma być maksymalna wartość kąta rozrzutu broni.
		super(x, y, id, game);
		this.targetX=targetX;
		this.targetY=targetY;
		LinearFunction();
	}

	public void tick(Game g) {
			g.handler.removeBullet(this); // handler przechowuje obiekty gry i je wszystkie updatuje, strzal ma zniknac po narysowaniu wiec jest odrazu usuwany

	}

	public void LinearFunction() // wyznaczenie wspolczynnikow prostej
	{
		this.a = (double)(targetY-y)/(targetX-x);
		this.b =(double)(y - (this.a * x));
        }
}

Mapa jest zapisana w pliku tekstowym, obecnie mamy tylko 2 pola - albo ściany albo podłogę.
Przykładowy plik z mapą:

1;1;1;1;1
1;2;2;2;1
1;2;2;2;1
1;2;2;2;1
1;1;1;1;1

1 - ściany
2 - pola po których można chodzić
Każde pole jest kwadratem o wielkości 32x32.

Po wczytaniu takiego pliku rysuję go w następujący sposób:

	public void Draw(Graphics g)
	{
		for(int i=0; i<VerticalTiles; ++i)
		{
			{
				for(int j=0; j<HorizontalTiles; ++j)
				{
				current = mapTiles.grabImage(map[j][i], 1, 32, 32); // Wycinam odpowiedni obrazek z BufferedImage i go rysuje. map[j][i] to tablica dwuwymiarowa przechowująca wyżej wypisaną mapę, tylko bez ";".
				g.drawImage(current, j*32, i*32, null);
				}
			}
		}
	}

Sporo tego kodu jest, ale chyba tyle wystarczy do tego problemu.

Czyli jak już wyznaczyłem równanie prostej, jak dalej mogę sprawdzić czy koliduje ze ścianą, mam przelecieć pętlą przez wszystkie ściany i sprawdzać, czy wartość tej funkcji liniowej się w niej zawiera dla wszystkich trzydziestu dwóch x? Nie widzę tego.

0

Najprościej będzie potraktować kwadrat jak cztery odcinki i sprawdzać kolizję półprosta-odcinek.
Jeśli się zgubisz w pewnym momencie podczas przekształcania wzorów, to podpowiem, że kilka takich wątków na StackOverflow już istnieje ;-)

Btw, dlaczego masz tę nibyklasę Point2d, a i tak robisz osobne targetX i targetY?

0

Zapomniałem usunąć z wcześniejszego kombinowania.
Czyli powinienem określić w którą stronę leci strzał, na tego postawie sprawdzam konkretne trzy odcinki, ale może dojść do takiej sytuacji:
Untitled.png
Czy dobrze rozumiem, że jak określę strone strzału, (np. prawo + dół) to w zasadzie mogę zbadać lewy, po nim górny i na koniec dolny odcinek i stąd dostać odpowiedni punkt w którym pocisk powinien się zatrzymać?

2

Yup, w teorii wygląda dobrze.

1 użytkowników online, w tym zalogowanych: 0, gości: 1