Ruch i kolizje
Stworzy Pan/Pani grywalną scenę.
Ruch i kolizje to bezpłatna lekcja Lua Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Lua Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Lua Academy zawiera 4 lekcji w sumie.
Pozycja i prędkość
Ruch w LÖVE polega na zmienianiu pozycji obiektu w czasie. Należy przechowywać wartości x i y, a następnie dodawać prędkość w love.update, skalując ją za pomocą dt.
Przechowywanie prędkości jako dx i dy na sekundę ułatwia obsługę ruchu po przekątnej i fizyki oraz uniezależnia je od liczby klatek.
function love.update(dt)
player.x = player.x + player.dx * dt
player.y = player.y + player.dy * dt
endRuch sterowany danymi wejściowymi
Odpytywanie należy połączyć z prędkością, aby sterować obiektem. W love.update trzeba odczytywać klawisze kierunkowe i stosować iloczyn prędkości oraz dt.
Ponieważ love.keyboard.isDown jest sprawdzane w każdej klatce, gracz porusza się płynnie tak długo, jak długo klawisz jest wciśnięty.
function love.update(dt)
if love.keyboard.isDown('left') then player.x = player.x - player.speed*dt end
if love.keyboard.isDown('right') then player.x = player.x + player.speed*dt end
endNormalizacja prędkości ruchu po przekątnej
Naciśnięcie jednocześnie dwóch klawiszy kierunkowych powoduje szybszy ruch po przekątnej, ponieważ obie osie dodają pełną prędkość. Aby temu zapobiec, należy znormalizować wektor ruchu.
Należy podzielić kierunek przez jego długość, aby jego długość wynosiła 1, a następnie pomnożyć go przez prędkość. Dzięki temu ruch po przekątnej ma taką samą prędkość jak ruch w linii prostej.
local dx, dy = ix, iy
local len = math.sqrt(dx*dx + dy*dy)
if len > 0 then
player.x = player.x + (dx/len) * player.speed * dt
endUtrzymywanie obiektów na ekranie
Należy ograniczyć pozycję, aby obiekty pozostawały na ekranie. Rozmiar okna można odczytać za pomocą love.graphics.getWidth i getHeight, a następnie ograniczyć współrzędne do odpowiedniego zakresu.
Połączenie funkcji math.max i math.min pozwala w prosty sposób ograniczyć wartość do zakresu między minimum a maksimum.
local w = love.graphics.getWidth()
player.x = math.max(0, math.min(player.x, w - player.size))Prostokąty ograniczające wyrównane do osi
Najprostsze kolizje wykorzystują prostokąty, nazywane AABB (axis-aligned bounding boxes). Każdy obiekt ma wartości x, y, szerokość i wysokość.
Dwa prostokąty nakładają się, gdy przecinają się jednocześnie na osi poziomej i pionowej. To sprawdzenie jest szybkie i wystarczające dla większości gier 2D.
-- box: { x, y, w, h }Test nakładania się AABB
Dwa prostokąty nakładają się, gdy na żadnej z osi jeden z nich nie znajduje się całkowicie za drugim. Klasyczny test łączy cztery porównania.
Jeśli wszystkie cztery warunki są spełnione, prostokąty się przecinają. Ten pojedynczy warunek stanowi podstawę wykrywania kolizji w grach 2D.
function overlaps(a, b)
return a.x < b.x + b.w and
b.x < a.x + a.w and
a.y < b.y + b.h and
b.y < a.y + a.h
endReagowanie na kolizję
Gdy overlaps zwróci wartość true, należy zdecydować, co ma się wydarzyć: podnieść monetę, otrzymać obrażenia lub zatrzymać ruch. Kolizje należy sprawdzać w love.update po wykonaniu ruchu.
W przypadku przedmiotów do zebrania wystarczy usunąć przedmiot lub zwiększyć wynik. W przypadku litych ścian należy wypchnąć gracza z powrotem na zewnątrz.
function love.update(dt)
movePlayer(dt)
if overlaps(player, coin) then
score = score + 1
coin.dead = true
end
endKolizje okręgów
W przypadku okrągłych obiektów dokładniejsze jest wykrywanie kolizji na podstawie odległości. Dwa okręgi kolidują, gdy odległość między ich środkami jest mniejsza niż suma ich promieni.
Porównywanie kwadratów odległości pozwala uniknąć kosztownego obliczania pierwiastka kwadratowego. Jest to często stosowana optymalizacja podczas sprawdzania wielu obiektów.
function circlesHit(a, b)
local dx, dy = a.x - b.x, a.y - b.y
local rsum = a.r + b.r
return dx*dx + dy*dy < rsum*rsum
endRozwiązywanie kolizji ze ścianami
Aby zatrzymać gracza przy ścianie, można poruszać nim osobno wzdłuż każdej osi i cofać krok powodujący nakładanie się obiektów.
Należy przesunąć obiekt w osi x i sprawdzić kolizję; jeśli wystąpi, cofnąć zmianę x. Następnie należy powtórzyć to samo dla osi y. Rozwiązywanie kolizji osobno dla każdej osi zapobiega blokowaniu się na rogach.
player.x = player.x + vx * dt
if overlaps(player, wall) then player.x = player.x - vx * dt end
player.y = player.y + vy * dt
if overlaps(player, wall) then player.y = player.y - vy * dt endStosowanie grawitacji
Gry platformowe dodają stałe przyspieszenie w dół. W każdej klatce należy zwiększyć prędkość pionową o iloczyn grawitacji i dt, a następnie zastosować prędkość do pozycji.
Gdy gracz wyląduje na ziemi, należy wyzerować jego prędkość pionową, aby zatrzymać spadanie. Skok nadaje prędkości pionowej wartość ujemną.
function love.update(dt)
player.dy = player.dy + GRAVITY * dt
player.y = player.y + player.dy * dt
endUsuwanie nieaktywnych obiektów
Po kolizjach często trzeba usuwać obiekty. Należy iterować po liście od końca i wywoływać table.remove, aby indeksy pozostały prawidłowe podczas usuwania.
Iterowanie od końca to bezpieczny idiom Lua służący do usuwania elementów w środku pętli. Zapobiega pomijaniu elementów, do którego doszłoby podczas iterowania od początku.
for i = #coins, 1, -1 do
if coins[i].dead then
table.remove(coins, i)
end
endSzybki test
Sprawdź swoje zrozumienie ruchu i kolizji w LÖVE.
Podsumowanie
Ruch łączy pozycję, prędkość i dt, a normalizacja zapewnia równą prędkość ruchu po przekątnej, zaś ograniczanie utrzymuje obiekty na ekranie. Wykrywanie kolizji zaczyna się od testów nakładania AABB, a w przypadku okrągłych obiektów stosuje się sprawdzanie odległości.
Kolizje ze ścianami należy rozwiązywać przez cofanie ruchu osobno dla każdej osi, w grach platformowych dodać grawitację, a nieaktywne obiekty usuwać, iterując od końca za pomocą table.remove.
Ucz się Lua dzięki korepetycjom AI — za darmo
Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.
- Kursy
- 40
- Lekcje
- 159
Często zadawane pytania
Czy lekcja „Ruch i kolizje” jest bezpłatna?
Tak — pełny tekst „Ruch i kolizje” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Lua Academy, przejdź na CoddyKit PRO. Kurs Lua Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Ruch i kolizje”?
Stworzy Pan/Pani grywalną scenę. Ćwiczysz Lua Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć Lua Academy?
Nie wymagamy żadnego doświadczenia. Lua Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.
Ile czasu zajmuje lekcja „Ruch i kolizje”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji Lua Academy?
Tak. Każda lekcja Lua Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.