Komentarze

# The Lost and Damned Tips: Chopper vs. Chopper
  1. gra wygląda ciekawie, chciałem w nia pograć, ale nikt nie dołącza do mojego serwera...

Gdzie się podział śnieg tej zimy? Razem z ekipą QA zadawaliśmy sobie to samo pytanie. Dlatego jbeta pomógł nam w napisaniu kolejnego tutoriala, prezentującego… śnieg!

Głównie jest to skrypt, który tworzy, a właściwie symuluje, śnieg wokół gracza, kiedy ktoś wpisze zwykłą komendę. Skrypt pozwala zmieniać obszar „opadu”, oraz jego intensywność, prędkość i wielkość samych płatków.

MTA snow tutorial

Przygotowania

Na samym początku stwórzmy tabelę:

Kod
snowflake = {} –wprowadzamy tabelę, która będzie zawierała ID poszczególnych płatków

Oraz kilka zmiennych globalnych (dostępnych w całym skrypcie):

Kod
flakeID = 1 –Ustawia ID pierwszego płatku na 1updaterate = 27 –jak często skrypt ma sprawdzać pozycję każdego płatka

height = 4 –Jak wysoko ma zaczynać się “opad”

snowing = false –Pada, czy nie pada? Oto jest pytanie ;)

Programowanie komendy

Nauczyliśmy się tydzień temu, że możemy użyć funkcji addEventHandler aby przypisać nasz własne funkcje do wydarzeń globalnych (tego, co się dzieje w grze). Ten skrypt jednak używa komendy pisanej w konsoli, aby uruchomić daną funkcję. Dlatego powstała funkcja addCommandHandler:

Kod
addCommandHandler ( ‘snow’, ‘snow_SnowCommand’ ) –Przypisujemy funkcję snow_SnowCommand do komendy /snow

Teraz zaprogramujemy samo zdarzenie tak, aby można było określić w komendzie wszystkie (wypisane na początku) parametry.

Kod
Function snow_SnowCommand ( player, commandname, radius, density, speed, size ) –możesz określić wszystkie parametry za pomocą jednej komendy

Funkcja addCommandHandler domyślnie przekazuje dwie wartości funkcji, do której jest przypisana. Są to ‘player’ (gracz) i ‘commandname’ (nazwa komendy, tutaj snow). Wszystkie dodatkowe argumenty muszą zostać oddzielnie zaprogramowane jako zmienne.

Na przykład, jeżeli gracz wpisał „snow 4 3 2 1″ w konsoli, to komenda powinna przekazał funkcji takie dane (w oddzielnych wartościach: „snow”, 4, 3, 2, 1

Dobrze więc. Mamy zaprojektowanć komendę. Czas stworzyć sam śnieg po wpisaniu komendy.

Kod
if not snowing then –sprawdzamy, czy zmienna “snowing” jest ustawiona na “false” (nieprawda). Wtedy zaczynamy opad
snowing = true –najpierw jednak ustawiamy wartość na „true”
snow_CreateSnow ( player, radius, density, speed, size ) –Tworzymy śnieg za pomocą funkcji snow_CreateSnow!
outputChatBox ( ‘Snow started by ‘ .. getClientName ( player ) ) –Wysyłamy powiadomienie, że zaczął się opad

Jeżeli nie pada śnieg, tworzymy go za pomocą snow_CreateSnow. Należy również zauważyć, że funkcja getClientName zwraca nick gracza ją wywołującego

Czas pozwolić graczom na zatrzymanie “opadu”:

Kod
else
snowing = false
–ustawiamy zmiennć na “nieprawda”
outputChatBox ( ‘Snow stopped.’ ) powiadamiamy gracza, że śnieg przestał padać (co za odkrycie ;d – dop. Globi)
end
end

Tworzymy śnieg

Skrypt używa funkcji snow_CreateSnow. Nie jest to jedna z podstawowych funkcji MTA, jest raczej dodatkowa, warto ją zadeklarować:

Kod
ifunction snow_CreateSnow ( player, radius, density, speed, size )
Skrypt tworzy śnieg wokół gracza, który go wywołał. Musimy więc pobrać jego aktualną pozycję:
local px, py, pz = getElementPosition ( player )

Tydzień temu nauczyliśmy się korzystać z funkcji setElementPosition. Najczęściej jednak używa się jej do pobrania samej pozycji gracza – dlatego zdefiniowano ją wraz ze zmiennymi px, py, pz.

Kod
–jeżeli gracz nie istnieje, rozłączył się, lub go w ogóle nie było ustawiamy wszystko domyślnie:
if not px or not py or not pz then
snowing = false
return
end

Ta część skryptu sprawdzi, czy gracz czasem się nie rozłączył (po co ma padać, gdy już go nie ma). Wystarczy sprawdzić, czy wartości px, py albo pz są nieprawidłowe. Jeżeli są – gracza nie ma w grze.

Następna część skryptu rozpoznaje, czy podano wszystkie parametry. Na przykład, jeżeli gracz po prostu napisze „snow” bez dokładniejszych wytycznych, wtedy zostaną one ustawione domyślnie.

Kod
–wartości domyślne
if not radius then radius = 20 else radius = tonumber ( radius ) end

Jeżeli pole “opadu” nie istnieje, to zostanie ustawione automatycznie na 20. Jeżeli istnieje, konwertujemy go na numer (dane z konsoli są pobierane jako łańcuchy znakowe) używamy funkcji lua – tonumber.

Kod
if not density then density = 3 else density = math.ceil ( tonumber ( density ) ) end –intensywność również powinna być numerem (płatki/sekundę)

Analogicznie, jeżeli w ogóle jej nie ustawiliśmy, to wartością domyślną będzie 3. Jeżeli jednak istnieje, konwertujemy ją na numer, oraz zaokrąglamy za pomocą funkcji lua math.ceil.

Kod
if not speed then speed = 1.5 else speed = math.abs ( tonumber ( speed ) ) end –prędkość powinna być dodatnia (jednostki/sekundę)

Dlatego używamy funkcji lua math.abs, żeby zwrócić dodatni, zaokrąglony numer.

Kod
if not size then size = 0.15 else size = tonumber ( size ) end

Jeżeli nie zostanie określona, zostawiamy domyślną.

Następnie zastosujemy pętlę while, aby stworzyć tyle płatków, ile nam potrzeba (pętla będzie tworzyć dopóty, dopóki nie spełni się dany warunek). Warunkiem będzie intensywność, ustawiona wcześniej.

Kod
local counter = 0 –Powtarzamy process tworzenia dla każdego z płatków
while counter = density do
–Dla x i y, nadal obliczana jest przypadkowa pozycja wokół gracza (z uwzględnieniem podanych parametrów ograniczających)
local angle = randInt ( 0, 359 )local fx = px + math.cos ( angle ) * radius * randFloat ()local fy = py + math.sin ( angle ) * radius * randFloat ()
local fz = pz + height

Użyjemy trygonometrii, aby umieścić płatek w przestrzeni. Najpierw zastosujemy funkcję lua randInt aby wygenerować przypadkowy numer między 0 a 359. Następnie stosujemy trygonometrię, pobieramy pozycję x i y, oraz mnożymy przez radius (obszar opadu: „jego promień”). Teraz mnożymy to przez dowolną liczbę dziesiętną między 0, a 1 (randFloat).

Mamy pozycję, stwórzmy więc sam płatek

Kod
snowflake[flakeID] = createMarker ( fx, fy, fz, ‘corona’, size, 255, 255, 255, 150 )

Zastosowano funkcję createMarker. Tydzień temu używaliśmy jej, aby określić wygląd „cylindryczny” (owalny) tworząc marker. Tworzymy teraz obiekt „corona”, który czymś w rodzaju świecącej piłki. Dodajemy go również do tabeli, więc będziemy mogli się do niego odwołać później.

Ustawiamy liczniki

Kod
–Obliczamy czas, który minie, zanim płatek spadnie na ziemię, w milisekundach
local time = 1000 * ( height + 1 ) / speed
–każemy skryptowi, aby zaktualizować obecną pozycję płatka, tyle razy, ile trzeba oraz zapisać ID licznika do tabeli
setTimer ( ‘snow_moveFlake’, updaterate, math.floor ( time / updaterate ), flakeID, speed )
–Niszczymy płatek, gdy minie czas
setTimer ( ‘snow_destroyFlake’, time, 1, flakeID )

Wreszcie przywołujemy funkcję, którą rozpoczniemy opad.

Ruch oraz niszczenie płatków

Teraz warto napisać funkcję snow_moveFlake.

Kod
function snow_moveFlake ( flakeID, speed )
local fx, fy, fz = getElementPosition ( snowflake[flakeID] )
setElementPosition ( snowflake[flakeID], fx, fy, fz – ( updaterate / 1000 * speed ) )
end

Pobiera ona pozycję płatku, sprawdzając w poprzednio stworzonej tabeli. Następnie go porusza w dół, odwołując się do prędkości i częstotliwości opadu. Jako, że będzie to wykonywane wielokrotnie (zmienna updaterate), będzie sprawiał wrażenie ruchu.

Wreszcie napiszmy ostatnią funkcją snow_destroyFlake, odpowiedzialną za niszczenie płatków, gdy skończy się ustawiony czas opadu.

Kod
function snow_destroyFlake ( flakeID )
destroyElement ( snowflake[flakeID] )
snowflake[flakeID] = nil

end

Jak widać, użyto tej samej funkcji, co w zeszłym tygodniu, destroyElement, (używanej wtedy, aby zniszczyć pole teleportacyjne). Nie inaczej jest ze śniegiem. Na sam koniec następuje czyszczenie tabeli i zwolnienie pamięci.