(tworznie gier) Kolizja z przedmiotem podczas spadania postaci

(tworznie gier) Kolizja z przedmiotem podczas spadania postaci
SP
  • Rejestracja:ponad 6 lat
  • Ostatnio:ponad 4 lata
  • Postów:27
0

Siema. Zrobiłem funkcja Kolizja():

Kopiuj
public static boolean Kolizja(Vector WektorPołożenia, Postać postać, Textury box) {
		return (WektorPołożenia.x < box.Xposition + box.Width && WektorPołożenia.x + postać.Width > box.Xposition
				&& WektorPołożenia.y + postać.Height > box.Yposition && WektorPołożenia.y < box.Yposition + box.Height);
	}

Wszystko działa, tzn zwraca wartosc true, gdy wjezdzam z kazdej strony na przeszkodę. Problem zaczyna się, gdy zaimplementowalem metodę skok(). Kiedy postac skacze na tyle wysoko, aby byc ponad przeszkodą to gdy probuje na nią wskoczyć, to przelatuje przez nią. Od spodu wszystko działa, a chce zeby postac zatrzymala się na przeszkodzie. Jakaś rada, pomysly ?

Funkcja skok():

Kopiuj
public void skok() {

		WektorPołożenia.y -= WektorPrędkości.y;
		WektorPrędkości.y -= 15;

		if (WektorPołożenia.y < TopMapBorder) {
			WektorPołożenia.y = TopMapBorder;
		}

		if (WektorPołożenia.y > BottomMapBorder - postać.Height) {
			WektorPołożenia.y = BottomMapBorder - postać.Height;
			jump = false;
			WektorPrędkości.y = 100;
		}

		if (Kolizja(WektorPołożenia, postać, box)) // OD DOŁU
		{
			WektorPołożenia.y = box.Yposition + box.Height;
		}
	}
Patryk27
Btw, lepszą nazwą dla Twojej funkcji mogłoby być czyKoliduja, jeśli chcesz się trzymać polskiego nazewnictwa.
Spine
  • Rejestracja:prawie 22 lata
  • Ostatnio:około godziny
  • Postów:6630
1
  1. Box.pozycja -> prawda, że też może być wektorem? Tak samo, jak gracz.pozycja. Jednolite nazwy...
  2. Taki sposób sprawdzania kolizji z otoczeniem jest dość wadliwy... Sama funkcja sprawdzająca kolizję też, bo sprawdzasz czy cały prostokąt postaci znajduje się w całym prostokącie platformy (a to jest możlwie tylko jeśli platforma jest większa od postaci i postać weszła w całą platformę a nie jest np. jedną nogą poza platformą). No i nawet jak przerobisz to, żeby sprawdzało wszystkie punkty, to i tak nie uwzględnisz sytuacji, kiedy prostokąty się krzyżują (a może się tak stać w skrajnych przypadkach, w zależności od wielkości przesunięcia/klatek na sekundę). Najprościej by było jakbyś zrobił obiekt "prostokąt", który będzie zawierał definicję wszystkich odcinków odpowiednio dla postaci i przeszkody. Kolizje byś badał sprawdzając, czy którekolwiek odcinki się przecinają. To podejście nie jest idealne, ale jest lepsze niż sprawdzanie punktów.

🕹️⌨️🖥️🖱️🎮
edytowany 4x, ostatnio: Spine
cerrato
Moderator Kariera
  • Rejestracja:około 7 lat
  • Ostatnio:minuta
  • Lokalizacja:Poznań
  • Postów:8768
1

@furious programming: przywołuję Cię :D
Wprawdzie język inny, ale zasada wykrywania kolizji podobna to Twojego platformersa. Może coś ciekawego dodasz :)

@Spwrtt - poczytaj wpisy Furoius'a na minibligu, opisywał tam różne aspekty tworzenia swoje gierki, był też odcinek o ruchu postaci i wykrywaniu kolizji.
https://4programmers.net/Profile/49548/Microblog


edytowany 1x, ostatnio: cerrato
piotrpo
  • Rejestracja:ponad 7 lat
  • Ostatnio:3 dni
  • Postów:3277
1

Sprawdzenie kolizji 2 prostokątów z bokami równoległymi do osi układu współrzędnych to sprawdzenie czy:

  1. co najmniej jeden z wierzchołków prostokąta A znajduje się wewnątrz prostokąta B (intersekcje + A zawiera się w B)
  2. lub przynajmniej 1 wierzchołek B znajduje się wewnątrz A1. (przypadek kiedy cały B zawiera się w A)
  3. lub dowolnie wybrany odcinek pionowy A przecina się z dowolnie wybranym odcinkiem poziomym B.

Warto sobie wprowadzić pojęcie (i przy okazji klasę) MBR - minimum bounding rectangle, zaimplementować w niej metody do badania kolizji

Sprawdzanie czy odcinki się nie przecinają nie jest już takie banalne, a ze względów wydajnościowych poprzedza się takie sprawdzenie właśnie prostym badaniem kolizji 2 prostokątów

Problem jaki możesz spotkać, to prędkość i klatki ilość klatek fizyki - czasami obiekty mogą przeniknąć przez siebie a kolizja nie zdąży nastąpić - np. szybko poruszający się mały pocisk trafiający w cienką ścianę.

edytowany 1x, ostatnio: piotrpo
Spine
  • Rejestracja:prawie 22 lata
  • Ostatnio:około godziny
  • Postów:6630
1

Jest jeszcze taki fajny algorytm ;)

https://www.gamedev.net/articles/programming/general-and-gameplay-programming/2d-rotated-rectangle-collision-r2604/

Wiadomo, pewnie u Ciebie prostokąty się nie obracają, ale i tak zadziała ;)

Tylko przy takim wykrywaniu kolizji nie dowiesz się za bardzo, z której strony nastąpiła... Czyli Twoja postać skacząca stanie na platformie po uderzeniu w jej bok.
Dlatego zachęcam do badania kolizji z otoczeniem zanim ona nastąpiła przy użyciu raycastów. Kiedy idziesz w prawo to strzelasz w prawo raycastami o długości równej potencjalnemu przemieszczeniu, zanim w ogóle nastąpił ruch. Jeśli nastąpiła kolizja, to skracasz wektor przemieszczenia do takiej długości, przy której kolizja nie nastąpi.

Polecam opis tego gostka:


🕹️⌨️🖥️🖱️🎮
edytowany 2x, ostatnio: Spine
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 10 godzin
  • Lokalizacja:Tuchów
  • Postów:12165
0

Ja bym bardzo prosił, aby mojej platformówki nie dawać jako przykładu tworzenia gier, dlatego że jest ona jedynie eksperymentem (jest wysoce specyficzna), nie zawierająca czegokolwiek związanego z poprawnym dziś gamedevem. A że sam tworzeniem ”prawdziwych” gier się nie zajmuję, to każdy aspekt tego projektu po prostu wymyśliłem. Wiem co nieco na temat tworzenia gier na Famicoma, ale taka wiedza dziś nie jest zbyt przydatna. ;)

Tak więc mogę napisać o tym, w jaki sposób zaimplementowałem kolizje bohatera z platformami w mojej demówce, jednak głównie jako ciekawostkę, bo zapewne istnieją lepsze rozwiązania. Zresztą wszystko i tak zależy od konkretnych wymagań.


W mojej demówce, bohater jest prostokątnym klockiem. Rozmiar hitboksu klocka to zawsze 14x16 pikseli – bez względu na to czy ciało bohatera jest rozciągnięte, czy nie (rozciąga się głównie podczas opadania). Owe rozciągnięcie jest jedynie efektem wizualnym, bo może takim być – w końcu kolizja z platformą trwa tak krótko, że rozciągnięte ciało bohatera nachodzące na platformę jest niezauważalne.

Platformy zbudowane są z kafli o rozmiarach 16x16 pikseli. Hitboks bohatera mieści się ładnie wewnątrz kafli, dlatego też określiłem, że do sprawdzania kolizji używane będą wierzchołki. Hitboks bohatera opisuje struktura zawierająca współrzędne wszystkich czterech wierzchołków, natomiast hitboksy danej warstwy poziomu to po prostu dwuwymiarowa macierz wartości logicznych.

Aby przeprowadzić ruchu bohatera, wykonuje się przesunięcie współrzędnych wierzchołków o zadane wartości. Dla ruchu poziomego jest to stała wartość równa 2, a dla pionowego, zależna od prędkości wznoszenia/opadania (od 1 do 16). Aby wykryć kolizję, najpierw określa się kierunek ruchu – lewo lub prawo oraz góra lub dół – i wybiera dwie pary wierzchołków, jedna para dla ruchu poziomego i jedna dla pionowego. Jeśli bohater ma być przesunięty np. w prawo, to bierze się dwa prawe wierzchołki, jeśli w dół, to dwa dolne. Następnie dodaje się offsety do tych współrzędnych i dzieli się je przez rozmiar kafli – w ten sposób uzyskujemy relatywne indeksy komórek w macierzy hitboksów warstwy poziomu.

Ostatnim krokiem jest sprawdzenie, czy komórki w macierzy hitboksów spod obliczonych relatywnych indeksów zawierają True (blok platformy) lub False (pusta przestrzeń). Jeśli False, to bohater może się przesunąć (brak kolizji), więc aktualizuje się jego pozycję, a jeśli True, to należy wyrównać pozycję do danego kafla (nastąpiła kolizja). Gra oprócz statycznych platform nie posiada żadnych innych obiektów, z którymi bohater może się zderzyć, więc kolizje z platformami to jedyne co należało oprogramować.

Oczywiście zabezpieczeń jest więcej. Należy też sprawdzać kolizje ze ścianami ekranu (dla ruchu poziomego), tak aby bohater nie mógł wyjść poza planszę, a także z granicami planszy (dla ruchu pionowego), aby bohater z niej nie wypadł (wtedy podczas testowania kolizji wykroczonoby poza zakres macierzy hitboksów). Dlatego każdy poziom określają dwa obszary:

  • widoczna przestrzeń (Area) – do której wyrównywana jest kamera oraz ciało bohatera w ruchu poziomym,
  • granice planszy (Bounds) – do których wyrównywane jest ciało bohatera w ruchu pionowym (tylko po wpadnięciu w przepaść).

Różnica tych obszarów to tzw. margines, gdyby to kogokolwiek obchodziło. Bohater może się poruszać po marginesie jedynie w ruchu pionowym. Śmierć bohatera następuje w momencie dotknięcia granicy planszy (Bounds), co zostało wykorzystane do stworzenia efektu niewielkiej przerwy, trwającej od zniknięcia bohatera pod/nad ekranem do jego zabicia, a tym samym do zaciemnienia ekranu i resetu. Owa przerwa to ruch pionowy właśnie po marginesie, a jej długość jest uzależniona od prędkości opadania (im wyższa prędkość, tym szybciej bohater dotknie granicy, więc i krótsza przerwa).

Rozmiar kafli warstw poziomów oraz rozmiar bohatera są dobrane w taki sposób, aby powyższe obliczenia nigdy się nie myliły. Maksymalna prędkość opadania określona jest jako 16 pikseli na klatkę i jest równa rozmiarowi pojedynczego kafla. Jest ona konieczna, bo gdyby nie była określona, to podczas opadania np. 30 pikseli na klatkę, bohater mógłby przelecieć przez kafel poziomu (przesunięcie współrzędnych wierzchołków byłoby większe niż rozmiar kafla). To tak gwoli ścisłości.


Ok, w dużym skrócie byłoby tyle.

Jeśli kogoś potrzebuje szczegółów to z chęcią je podam, choć tak jak wspomniałem – ten projekt jest jedynie eksperymentem. Jednym z jego założeń był opis ruchu na podstawie liczb całkowitych**1** oraz liczenie klatek zamiast czasu na podstawie delty, czyli podobnie jak miało to miejsce w grach na Famicoma. O ile było to fajne wyzwanie, to taka technika nie jest używana we współczesnych grach, więc nie polecam jej stosować.


[1] Wyjątkiem jest ruch świetlików po okręgu, do czego użyłem liczb zmiennoprzecinkowych. Co prawda floaty nie są konieczne (bo mamy np. odmianę Midpoint circle algorithm bazującą na intach), jednak użycie floatów było po prostu krótsze w implementacji.


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 8x, ostatnio: flowCRANE
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)