W samym sercu koncepcji silnika Defold znajduje się kilka elementów, których zrozumienie ułatwia dalszą pracę z silnikiem. Instrukcja ta wyjaśnia czym są takie bloki służące do budowania aplikacji. Po zapoznaniu się z poniższą instrukcją, warto przejść do Instrukcji adresowania i przesyłania wiadomości. Na stronie Defold znajdziesz również tutoriale dla początkujących dostępne nawet z poziomu edytora, aby umożliwić Ci szybki start z silnikiem Defold.
Przy budowaniu gier na silniku Defold używa się trzech podstawowych elementów:
Kolekcje mają strukturę drzewa, która przechowuje obiekty i inne kolekcje. Kolekcje są zawsze przechowywane w formie pliku.
Kiedy Defold startuje, wczytuje pojedynczą, główną kolekcję bootrstrapową określoną w pliku game.project. Kolekcja bootstrapowa jest często nazywana “main.collection” (i tak jest też domyślnie nazwana po otwarciu każdego nowego projektu), ale oczywiście możesz używać dowolnej nazwy.
Kolekcja może zawierać obiekty i inne kolekcje (przez referencję do pliku sub-kolekcji) zagnieżdżone na dowolną “głębokość”. Poniżej jest przykład kolekcji “main.collection”. Zawiera ona jeden obiekt gry (z id “can”)i jedną sub-kolekcję (z id “bean”). Sub-kolekcja ta zawiera z kolei obiekty “bean” i “shield”.
Zauważ, że sub-kolekcja z id “bean” jest przechowywana w osobnym pliku nazwanym “/main/bean.collection”, a kolekcja nadrzędna “main.collection” zawiera do tego pliku jedynie referencję:
Nie można zaadresować kolekcji samej w sobie, ponieważ nie istnieją obiekty w czasie rzeczywistym, które reprezentują kolekcje “main” czy “bean” - nie można więc wysłać wiadomości do kolekcji samej w sobie, a tylko do obiektów i komponentów. Jednak czasem chcesz wysłać wiadomość do obiektu z innej kolekcji niż kolekcja, w której nadawca się znajduje, więc dlatego określą się ścieżkę (ang. path) do takiego obiektu z uwzględnieniem id kolekcji (Szczegóły znajdziesz w Instrukcji adresowania):
-- file: can.script
-- get position of the "bean" game object in the "bean" collection
local pos = go.get_position("bean/bean")
Kolekcja dodawana do innej kolekcji jest zawsze referencją do pliku kolekcji:
Naciśnij Prawy-przycisk-myszki na kolekcji w panelu Outline i wybierz Add Collection File.
Obiekty gry to bardzo proste obiekty posiadające indywidualny czas życia w trakcie wykonywania programu. Posiadają pozycję, orientację i skalę, a parametry te mogą być manipulowane i animowane osobno w czasie działania programu.
-- animate X position of "can" game object
go.animate("can", "position.x", go.PLAYBACK_LOOP_PINGPONG, 100, go.EASING_LINEAR, 1.0)
Obiekty gry mogą być używane jako puste obiekty (jako znacznik pozycji (ang. waypoint, startpoint, checkpoint etc.)), ale najczęściej zawierają komponenty, takie jak sprite’y, dźwięki, skrypty, modele, fabryki, efekty cząsteczkowe i inne. Obiekty te są tworzone albo z poziomu edytora i umieszczane bezpośrednio w plikach kolekcji (statycznie) albo dynamicznie, w kodzie, dzięki fabrykom (ang. factory).
Obiekty gry są więc dodawane jako nowe obiekty zdefiniowane w pliku kolekcji lub również w pliku kolekcji, ale jako referencja do osobnego pliku z definicją obiektu gry:
Naciśnij Prawy-przycisk-myszki na kolekcji w panelu Outline i wybierz Add Game Object (dodasz definicję do kolekcji) or Add Game Object File (dodasz do kolekcji referencję do pliku z definicją obiektu).
Jest to jeszcze dogłębniej wytłumaczone poniżej.
Komponenty są używane, żeby nadać obiektom gry konkretne właściwości i funkcjonalności, takie jak reprezentacja graficzna, dźwiękowa czy logika gry. Komponenty muszą należeć do obiektu gry i są afektowane przez zmiany jego pozycji, orientacji i skali:
Wiele komponentów ma specyficzne właściwości, które mogą być modyfikowane. Istnieją trzy specyficzne funkcje do interakcji z nimi w trakcie działania programu:
-- disable the can "body" sprite
msg.post("can#body", "disable")
-- play "hoohoo" sound on "bean" in 1 second
sound.play("bean#hoohoo", { delay = 1, gain = 0.5 } )
Komponenty są dodawane do obiektów gry z poziomu Edytora jako ich nowe komponenty lub referencje do istniejących plików komponentów:
Naciśnij prawym przyciskiem myszki na obiekcie gry w panelu Outline i wybierz Add Component (nowy komponent) lub Add Component File (jako referencja do pliku).
W większości przypadków sens ma tworzenie nowych komponentów specyficznych dla danego obiektu, ale często możesz też wykorzystywać wspólne komponenty dla wielu obiektów, a niektóre z nich nie mogą być utworzone inaczej niż przez stworzenie wcześniej pliku:
Odsyłamy do osobnej Instrukcji do komponentów, gdzie znajduje się lista wszystkich komponentów silnika Defold.
Kiedy tworzysz plik kolekcji, obiektu gry lub nawet komponentu (np. w panelu Assets), tak naprawdę tworzysz tylko szablon, prototyp (ang. blueprint, prototype). Tworzy to tylko i wyłącznie plik w strukturze Twojego projektu, natomiast nic nie jest dodawane do samej gry. Aby stworzyć instancję kolekcji, obiektu czy komponentu do gry, która bazuje na takim pliku-szablonie, dodać należy taką instancję w jednej z Twoich kolekcji.
W panelu Outline możesz zobaczyć na jakim pliku bazuje dana instancja, jeśli była ona stworzona z pliku, a nie bezpośrednio w panelu Outline właśnie. Przykładowo, kolekcja “main.collection” poniżej zawiera trzy instancje, które bazują na już utworzonych plikach:
Korzyścią z używania szablonów/plików jest zdecydowanie możliwość stworzenia wielu instancji obiektu gry lub kolekcji i zmiana ich wszystkich naraz w jednym pliku:
Przy zmianie pliku każda instancja utworzona z tego pliku zostaje natychmiastowo zaktualizowana:
W pliku kolekcji możesz tworzyć hierarchie obiektów gry (game objects) w ten sposób, że jeden z obiektów jest dzieckiem innego obiektu - rodzica. Po prostu przeciągnij jeden z obiektów gry i upuść nad innym obiektem - zostanie on umieszczony w drzewku pod tym obiektem i stanie się jego dzieckiem:
Relacja rodzic-dziecko jest dynamiczną relacją wpływającą na zmianę pozycji, orientacji i skali obu obiektów. Każda transformacja tych wartości zaaplikowana do obiektu rodzica zostanie następnie zaaplikowana do obiektu dziecka, aby ich wzajemna, względna pozycja/orientacja/skala pozostała taka sama, 1:1, zarówno w edytorze jak i w czasie działania programu:
Z kolei wszystkie transformacje na obiekcie dziecku są wykonywane w układzie odniesienia rodzica. W edytorze Defold możesz wybrać, czy operacje na obiekcie dziecku są wykonywane w układzie lokalnym rodzica (local space) czy w głównym układzie odniesienia (world space) klikając Edit ▸ World Space (domyślnie ustawione) lub Edit ▸ Local Space.
Jest też możliwe zmienienie rodzica danego obiektu przez wysłanie do niego wiadomości set_parent
.
local parent = go.get_id("bean")
msg.post("child_bean", "set_parent", { parent_id = parent })
Częstym błędem jest postrzeganie przypisania obiektu jako dziecka innego obiektu w kolekcji jako zmiana miejsca tego obiektu w hierarchii kolekcji. Są to jednak dwie osobne rzeczy. Relacje rodzic-dziecko dynamicznie zmieniają graf w panelu Outline, co pozwala wizualnie ją przedstawić. Jedyną rzeczą, która określa adres obiektu jest jej miejsce w hierarchii kolekcji. Adres jest statyczny podczas całego cyklu życia obiektu.
Did you spot an error or do you have a suggestion? Please let us know on GitHub!
GITHUB