Komentarze

# 10 naprawdę denerwujących rzeczy
  1. do momentu aż mu ktoś heada nie sprzeda :D...

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.

Video instruktażowe: scriptvideo2.avi – XviD codec (640×480, 30fps)

Kompletny skrypt: script2.lua


Przygotowania

Na samym początku stwórzmy tabelę,
snowflake = {} –wprowadzamy tabelę, która będzie zawierała ID poszczególnych płatków

(Po więcej informacji na temat table w języku LUA, zapraszam na oficjalną stronę http://lua-users.org/wiki/TablesTutorial)

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

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ń flobalnych (tego, co się dzieje w grze). Ten skrypt jednak używa komendy pisanej w konsoli, aby uruchomić daną funkcję (nie przycisku – przyp. Globi). Dlatego powstała funkcja addCommandHandler:
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.

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.
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”:

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ć:

function 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.
–jeżeli gracz nie istnieje, rozłączył się, lub go w ogóle nie było (anty hack ;d –dop. Globi) 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.

–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 – dop. Globi) używamy funkcji lua – tonumber.
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.
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.

(po więcej informacji o funkcjach math.abs i math.ceil zapraszam na oficjalną dokumentację. http://lua-users.org/wiki/MathLibraryTutorial

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 – dop. Globi). Warunkiem będzie intensywność, ustawiona wcześniej.

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. Majpierw 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

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) tworzyc taki matker. 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

–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 by napisać funkcję snow_moveFlake.

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.

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.
Od tłumacza – Ekipa MTA pracuje nad dosłownie każdym elementem gry. Mamy teleportację, śnieg… Co teraz? Zapraszam za tydzień!

Sprawdźcie też, czy do tłumaczenia kodu nie wkradły się błędy…