From 8dc511e909f3b144b6d39758eae9de4a869f4347 Mon Sep 17 00:00:00 2001 From: AGulev Date: Fri, 13 Mar 2026 12:43:57 +0100 Subject: [PATCH 1/3] bunch two --- docs/pl/manuals/collection-factory.md | 119 ++++++----- docs/pl/manuals/editor-preferences.md | 96 +++++---- docs/pl/manuals/factory.md | 156 +++++++-------- docs/pl/manuals/lua.md | 68 +++---- docs/pl/manuals/mesh.md | 65 +++--- docs/pl/manuals/physics-joints.md | 46 +++-- docs/pl/manuals/property-animation.md | 138 ++++++------- docs/pl/manuals/resource.md | 70 ++++--- docs/pl/manuals/texture-profiles.md | 276 +++++++++++++++----------- docs/pl/manuals/writing-code.md | 69 ++++--- 10 files changed, 606 insertions(+), 497 deletions(-) diff --git a/docs/pl/manuals/collection-factory.md b/docs/pl/manuals/collection-factory.md index 259443cd..bc1f9cbd 100644 --- a/docs/pl/manuals/collection-factory.md +++ b/docs/pl/manuals/collection-factory.md @@ -1,57 +1,57 @@ --- -title: Instrukcja do Fabryk kolekcji -brief: Instrukcja ta wyjaśnia jak używać Fabryk kolekcji, żeby tworzyć hierarchię obiektów gry. +title: Fabryki kolekcji +brief: Ta instrukcja wyjaśnia, jak używać komponentów Collection factory do tworzenia hierarchii obiektów gry. --- -# Fabryka kolekcji (Collection factory) +# Fabryki kolekcji -Fabryki kolekcji to komponenty używane do tworzenia grup i hierarchi obiektów gry przechowywanych w pliku danej kolekcji w trakcie działania programu. +Komponent Collection factory służy do tworzenia grup i hierarchii obiektów gry zapisanych w plikach kolekcji w działającej grze. -Kolekcje są potężnym narzędziem do tworzenia szablonów, które można utylizować wielokrotnie (podobnie jak prefaby). Więcej szczegółów na temat kolekcji znajdziesz w [dokumentacji podstawowych elementów Defold](/manuals/building-blocks#collections). Kolekcje mogą być umieszczane bezpośrednio w Edytorze lub tworzone dynamicznie. +Kolekcje są w Defold wygodnym mechanizmem tworzenia szablonów wielokrotnego użytku, czyli odpowiednika prefabów. Przegląd kolekcji znajdziesz w [dokumentacji o blokach budujących](/manuals/building-blocks#collections). Kolekcje można umieszczać w edytorze albo dynamicznie wstawiać do gry. -Używając fabryki kolekcji możesz tworzyć w świecie gry zawartość pliku kolekcji. Jest to uproszczonie analogicznego procesu tworzenia wszystkich obiektów gry opisanych w danym pliku kolekcji i przypisywanie im relacji rodzic-dziecko również opisanych w takim pliku. Typowym przykładem jest tworzenie postaci wrogów składających się z wielu różnych obiektów (np. jedno z wariantów ciał + jedna z broni). +Za pomocą komponentu Collection factory możesz tworzyć w świecie gry zawartość pliku kolekcji. To odpowiednik utworzenia przez Factory wszystkich obiektów gry zapisanych w kolekcji, a następnie odtworzenia relacji rodzic-dziecko pomiędzy nimi. Typowym zastosowaniem jest tworzenie przeciwników złożonych z wielu obiektów gry, na przykład wroga i jego broni. ## Tworzenie kolekcji -Załóżmy, że chcesz, żeby obiekt reprezentujący Twojego bohatera miał również obiekt-dziecko reprezentujący tarczę. Zbudujemy taką hierarchię w pliku kolekcji i zapiszemy jako "bean.collection". +Załóżmy, że chcemy mieć obiekt gry postaci oraz osobny obiekt gry tarczy będący dzieckiem tej postaci. Budujemy taką hierarchię w pliku kolekcji i zapisujemy ją jako `bean.collection`. ::: sidenote -Komponent typu pełnomocnik kolekcji (*collection proxy*) różni się od fabryki i jest używany do stworzenia nowego świata gry, a co za tym idzie również osobnego świata fizyki z obiektami bazującymi na hierarchi w pliku danej kolekcji. Nowy świat ma swoje nowe gniazdo (socket), więc i nową przestrzeń adresową. Wszystkie zasoby z danej kolekcji są wczytywane przez pełnomocnika, kiedy wyślesz do niego wiadomość o rozpoczęciu wczytywania. Jest więc to przydatne przykładowo przy tworzeniu nowych poziomów w grze. Nowy świat gry wiąże się jednak z zajęciem sporej ilości nowych zasobów w pamięci, więc lepiej nie używać ich do dynamicznego wczytywania. Więcej szczegółów znajdziesz w [dokumentacji pełnomocników kolekcji](/manuals/collection-proxy). +Komponent *collection proxy* służy do tworzenia nowego świata gry, w tym osobnego świata fizyki, na podstawie kolekcji. Nowy świat jest dostępny przez nowe gniazdo adresowe. Wszystkie zasoby zawarte w kolekcji są ładowane przez pełnomocnika po wysłaniu do niego wiadomości rozpoczynającej ładowanie. To bardzo przydatne na przykład przy zmianie poziomów w grze. Nowe światy gry mają jednak spory narzut, więc nie należy ich używać do dynamicznego ładowania małych elementów. Więcej informacji znajdziesz w [dokumentacji Collection proxy](/manuals/collection-proxy). ::: ![Collection to spawn](images/collection_factory/collection.png) -Dodajemy następnie komponent typu *Collection factory* (Fabryka kolekcji) do obiektu gry, który będzie odpowiedzialny za stworzenie obiektów i hierarchi z pliku kolekcji "bean.collection" podanego jako właściwość *Prototype*: +Następnie dodajemy *Collection factory* do obiektu gry, który ma odpowiadać za tworzenie instancji, i ustawiamy `bean.collection` jako *Prototype* komponentu: ![Collection factory](images/collection_factory/factory.png) -Tworzenie bohatera i tarczy jest teraz tylko kwestią wywołania funckji `collectionfactory.create()`: +Utworzenie postaci i tarczy sprowadza się teraz do wywołania `collectionfactory.create()`: ```lua local bean_ids = collectionfactory.create("#bean_factory") ``` -Funkcja przyjmuje 5 parameterów: +Funkcja przyjmuje 5 parametrów: `url` -: Identyfikator fabryki kolekcji, która ma być użyta do tworzenia nowego zestawu obiektów. +: Id komponentu Collection factory, który ma utworzyć nowy zestaw obiektów gry. `[position]` -: (opcjonalnie) Pozycja w świecie (bezwzględna) nowych obiektów. Typu `vector3`. Jeśli nie określisz pozycji, obiekty będą tworzone w miejscu komponentu fabryki kolekcji. +: Opcjonalna pozycja tworzonych obiektów gry w przestrzeni świata. Powinna mieć typ `vector3`. Jeśli jej nie podasz, obiekty zostaną utworzone w pozycji komponentu Collection factory. `[rotation]` -: (opcjonalnie) Orientacja w świecie (bezwzględna) nowych obiektów. Typu `quat`. Jeśli nie określisz orientacji, obiekty będą tworzone z orientacją komponentu fabryki kolekcji. +: Opcjonalny obrót tworzonych obiektów gry w przestrzeni świata. Powinien mieć typ `quat`. `[properties]` -: (opcjonalnie) Właściwości - tabela Lua o strukturze par `id`-`table` używana przy tworzeniu obiektów gry. Poniżej opisano jak skonstruować taką tabelę. +: Opcjonalna tabela Lua zawierająca pary `id`-`table`, używana do inicjalizowania tworzonych obiektów gry. Poniżej opisano, jak ją zbudować. `[scale]` -: (opcjonalnie) Skala tworzonych obiektów, określona jako liczba (`number`) (większa od 0), która określa jednolitą skalę wzdłuż wszystkich osi. Możesz też podać wektor (`vector3`), gdzie każdy komponent będzie odpowiadał skali wzdłuż danej osi. +: Opcjonalna skala tworzonych obiektów gry. Może być podana jako `number` większy od 0, co oznacza jednolite skalowanie we wszystkich osiach. Możesz też przekazać `vector3`, gdzie każdy komponent określa skalę na odpowiedniej osi. -Funkcja `collectionfactory.create()` zwraca tabelę z identyfikatorami utworzonych obiektów gry. Klucze tabeli mapują hashe kolekcji do lokalnych identyfikatorów każdego z obiektów: +`collectionfactory.create()` zwraca tabelę z identyfikatorami utworzonych obiektów gry. Klucze tabeli mapują hash lokalnego id obiektu w kolekcji na runtime id danego obiektu: ::: sidenote -Relacja rodzic-dziecko między "bean" a "shield" *NIE* jest odzwierciedlona w zwracanej tabeli. Ta relacja istnieje jedynie w grafie sceny w trakcie działania programu, co określa jak obiekty są ustawione w stosunku do siebie. Przypisywanie rodzica nigdy nie zmienia identyfikatora obiektu. +Relacja rodzic-dziecko między `bean` i `shield` *nie* jest odzwierciedlona w zwracanej tabeli. Ta relacja istnieje tylko w runtime scene-graph, czyli w sposobie, w jaki obiekty są razem transformowane. Zmiana rodzica nigdy nie zmienia id obiektu. ::: ```lua @@ -64,12 +64,11 @@ pprint(bean_ids) -- hash: [/bean] = hash: [/collection0/bean], -- } ``` - -1. Prefix `/collection[N]/`, gdzie `[N]` jest licznikiem dodanym do ID, żeby zidentyfikować obiekt w sposób unikalny dla każdej instancji: +1. Do id dodawany jest prefiks `/collection[N]/`, gdzie `[N]` to licznik, aby każdą instancję jednoznacznie rozróżnić. ## Właściwości -Podczas tworzenia kolekcji, możesz przekazać właściwości do każdego obiektu gry konstruując tabelę, gdzie klucze odpowiadają identyfikatorom obiektów, a wartości są tabelami z właściwościami (scrip properties) dla danych obiektów. +Podczas tworzenia kolekcji możesz przekazać właściwości do poszczególnych obiektów gry, budując tabelę, w której kluczami są id obiektów, a wartościami tabele z właściwościami skryptu do ustawienia. ```lua local props = {} @@ -77,76 +76,94 @@ props[hash("/bean")] = { shield = false } local ids = collectionfactory.create("#bean_factory", nil, nil, props) ``` -Załóżmy, że obiekt "bean" w kolekcji "bean.collection" ma właściwość "shield". [Instrukcja do właściwości skryptów](/manuals/script-properties) zawiera więcej szczegółów na ten temat. +Załóżmy, że obiekt gry `bean` w `bean.collection` definiuje właściwość `shield`. [Instrukcja o właściwościach skryptu](/manuals/script-properties) zawiera więcej informacji o takich właściwościach. ```lua --- bean/controller.script +-- plik bean/controller.script go.property("shield", true) function init(self) if not self.shield then go.delete("shield") - end + end end ``` -## Wczytywanie dynamiczne zasobów +## Dynamiczne ładowanie zasobów fabryki -Zaznaczając właściwość *Load Dynamically* fabryki kolekcji, silnik odłoży wczytywanie zasobów danej kolekcji aż do momentu rozpoczęcia tworzenia. +Po zaznaczeniu pola *Load Dynamically* we właściwościach Collection factory silnik opóźni ładowanie zasobów powiązanych z fabryką. ![Load dynamically](images/collection_factory/load_dynamically.png) -Z odznaczoną opcją, silnik wczyta prototypy zasobów kolekcji w momencie wczytywania komponentu fabryki kolekcji, więc będzie można je utworzyć w świecie gry natychmiastowo. +Gdy pole nie jest zaznaczone, silnik ładuje zasoby prototypu podczas ładowania komponentu Collection factory, dzięki czemu są one od razu gotowe do tworzenia instancji. -Z zaznaczoną opcją, możesz użyć fabryki na dwa sposoby: +Gdy pole jest zaznaczone, masz dwa sposoby użycia: -Wczytywanie synchroniczne: -: Wywołaj [`collectionfactory.create()`](/ref/collectionfactory/#collectionfactory.create:url-[position]-[rotation]-[properties]-[scale]) kiedy chcesz utworzyć obiekty kolekcji. Funkcja wczyta wszystkie zasoby potrzebe do utworzenia obiektów synchronicznie (co może spowodować zwieszenie programu w zależności od wielkości zasobów), a następnie utworzy obiekty z danymi zasobami. +Wczytywanie synchroniczne +: Wywołaj [`collectionfactory.create()`](/ref/collectionfactory/#collectionfactory.create:url-[position]-[rotation]-[properties]-[scale]) wtedy, gdy chcesz tworzyć obiekty. Spowoduje to synchroniczne załadowanie zasobów, co może wywołać chwilowe przycięcie, a następnie utworzenie nowych instancji. ```lua function init(self) - -- Żadne zasoby fabryki nie są załadowane kiedy kolekcja rodzic - -- zawierająca daną fabrykę kolekcji jest utworzona. - -- Wywołanie create spowoduje wczytanie zasobów synchronicznie. - self.go_ids = collecionfactory.create("#collectionfactory") + -- Zasoby fabryki nie są ładowane, gdy ładowana jest kolekcja + -- nadrzędna komponentu Collection factory. Wywołanie create + -- bez wcześniejszego load wczyta zasoby synchronicznie. + self.go_ids = collectionfactory.create("#collectionfactory") end - function final(self) - -- Usuwanie obiektów gry. Zwolni to zasoby. - -- W tym przypadku obiekty są usuwane, ponieważ - -- fabryka kolekcji nie ma żadnych referencji. + function final(self) + -- Usuń obiekty gry. To zmniejszy licznik referencji zasobów. + -- W tym przypadku zasoby zostaną usunięte, ponieważ komponent + -- Collection factory nie trzyma już do nich referencji. go.delete(self.go_ids) - -- Wywołanie unload nie zrobi nic, ponieważ - -- fabryka kolekcji nie ma żadnych referencji. + -- Wywołanie unload nic nie zrobi, ponieważ fabryka + -- nie ma żadnych referencji. collectionfactory.unload("#factory") end ``` -Wczytywanie asynchroniczne: -: Wywołaj [`collectionfactory.load()`](/ref/collectionfactory/#collectionfactory.load:[url]-[complete_function]), żeby jawnie załadować zasoby asynchronicznie. Kiedy zasoby będą gotowe, skrypt, w którym wywołano load() otrzyma callback. +Wczytywanie asynchroniczne +: Wywołaj [`collectionfactory.load()`](/ref/collectionfactory/#collectionfactory.load:[url]-[complete_function]), aby jawnie załadować zasoby asynchronicznie. Gdy zasoby będą gotowe do tworzenia obiektów, otrzymasz callback. ```lua - --callback, który zostanie wywołany po wczytaniu zasobów: function load_complete(self, url, result) - -- Wczytywanie zakończone, zasoby są gotowe do utworzenia + -- Ładowanie zakończone, zasoby są gotowe do tworzenia instancji. self.go_ids = collectionfactory.create(url) end function init(self) - -- Żadne zasoby nie są wczytywane przy utworzeniu kolekcji - -- która jest rodzicem komponentu fabryki kolekcji. - -- Zasoby są wczytywane po wywołaniu load(): + -- Zasoby fabryki nie są ładowane, gdy ładowana jest kolekcja + -- nadrzędna komponentu Collection factory. Wywołanie load + -- spowoduje ich załadowanie. collectionfactory.load("#factory", load_complete) end function final(self) - -- Usuwanie obiektu gry. Zasoby są zwalniane. - -- W tym przypadku zasoby nie są usuwane, ponieważ - -- fabryka kolekcji nadal posiada do nich referencję. + -- Usuń obiekty gry. To zmniejszy licznik referencji zasobów. + -- W tym przypadku zasoby nie zostaną usunięte, ponieważ komponent + -- Collection factory nadal trzyma do nich referencję. go.delete(self.go_ids) - -- Wywołanie unload zwolni zasoby utrzymywane przez farbykę i usunie je + -- Wywołanie unload zmniejszy licznik referencji zasobów + -- trzymanych przez komponent fabryki, co doprowadzi do ich usunięcia. collectionfactory.unload("#factory") end ``` + +## Dynamiczny prototyp + +Możesz zmienić to, jaki *Prototype* potrafi tworzyć Collection factory, zaznaczając pole *Dynamic Prototype* we właściwościach komponentu. + +![Dynamic prototype](images/collection_factory/dynamic_prototype.png) + +Gdy opcja *Dynamic Prototype* jest włączona, komponent Collection factory może zmieniać prototyp za pomocą `collectionfactory.set_prototype()`. Przykład: + +```lua +collectionfactory.unload("#factory") -- zwolnij poprzednie zasoby +collectionfactory.set_prototype("#factory", "/main/levels/level1.collectionc") +local ids = collectionfactory.create("#factory") +``` + +::: important +Gdy opcja *Dynamic Prototype* jest włączona, liczba komponentów w kolekcji nie może zostać zoptymalizowana i kolekcja właściciela będzie używać domyślnych limitów komponentów z pliku *game.project*. +::: diff --git a/docs/pl/manuals/editor-preferences.md b/docs/pl/manuals/editor-preferences.md index ff3bf4d9..20996d3f 100644 --- a/docs/pl/manuals/editor-preferences.md +++ b/docs/pl/manuals/editor-preferences.md @@ -1,83 +1,111 @@ --- -title: Preferencje Edytora -brief: Ta instrukcja przedstawia co oznaczają i jak zmodyfikować Preferencje Edytora. +title: Preferencje edytora +brief: Ustawienia edytora możesz zmieniać w oknie Preferences. --- -# Preferencje Edytora +# Preferencje edytora -Możesz dostosować ustawienia Edytora z poziomu okna Preferencji. Okno Preferencji otwiera się z menu File -> Preferences. +Ustawienia edytora możesz zmieniać w oknie Preferences. Okno otwiera się z menu File -> Preferences. ## General (Ogólne) ![](images/editor/preferences_general.png) Load External Changes on App Focus (Wczytaj zewnętrzne zmiany po aktywowaniu aplikacji) -: Umożliwia skanowanie zewnętrznych zmian, gdy Edytor zostaje aktywnie wybrany w systemie. +: Włącza skanowanie zmian zewnętrznych, gdy edytor odzyskuje fokus. Open Bundle Target Folder (Otwórz folder docelowy pakietu) -: Umożliwia otwarcie folderu docelowego pakietu po zakończeniu procesu pakowania. +: Włącza otwieranie folderu docelowego bundla po zakończeniu procesu bundlowania. Enable Texture Compression (Włącz kompresję tekstur) -: Umożliwia kompresję tekstur dla wszystkich kompilacji utworzonych z Edytora. +: Włącza [kompresję tekstur](/manuals/texture-profiles) dla wszystkich buildów wykonywanych z poziomu edytora. Escape Quits Game (Klawisz Escape zamyka grę) -: Zatrzymuje działającą kompilację twojej gry za pomocą klawisza Esc. +: Zamyka uruchomiony build gry po naciśnięciu Esc. Track Active Tab in Asset Browser (Śledź aktywną kartę w przeglądarce zasobów) -: Plik edytowany na wybranej karcie w panelu Edytor zostanie zaznaczony w Przeglądarce Zasobów (znanej również jako panel *Assets*). +: Plik edytowany na aktualnie wybranej karcie w panelu *Editor* zostanie zaznaczony w Asset Browser, nazywanym też panelem *Asset*. -Path to custom keymap (Ścieżka do niestandardowej mapy klawiszy) -: Absolutna ścieżka do pliku zawierającego niestandardowe skróty klawiaturowe. +Lint Code on Build +: Włącza [linting kodu](/manuals/writing-code/#konfiguracja-lintingu) podczas budowania projektu. Ta opcja jest domyślnie włączona, ale można ją wyłączyć, jeśli linting w dużym projekcie trwa zbyt długo. -## Code (Kod) +Engine Arguments +: Argumenty przekazywane do pliku wykonywalnego `dmengine`, gdy edytor buduje i uruchamia projekt. + Używaj jednego argumentu na linię. Na przykład: + ``` +--config=bootstrap.main_collection=/my dir/1.collectionc +--verbose +--graphics-adapter=vulkan +``` + +## Code ![](images/editor/preferences_code.png) Custom Editor (Niestandardowy Edytor) -: Absolutna ścieżka do zewnętrznego Edytora. Na macOS powinna to być ścieżka do pliku wykonywalnego wewnątrz .app (np. `/Applications/Atom.app/Contents/MacOS/Atom`). +: Bezwzględna ścieżka do zewnętrznego edytora. W macOS powinna to być ścieżka do pliku wykonywalnego wewnątrz `.app`, na przykład `/Applications/Atom.app/Contents/MacOS/Atom`. + +Open File +: Wzorzec używany przez zewnętrzny edytor do wskazania pliku, który ma zostać otwarty. Wzorzec `{file}` zostanie zastąpiony nazwą pliku. -Open File (Otwórz plik) -: Wzorzec używany przez niestandardowy Edytor do określenia, który plik ma być otwarty. Wzorzec `{file}` zostanie zastąpiony nazwą pliku do otwarcia. +Open File at Line +: Wzorzec używany przez zewnętrzny edytor do wskazania pliku i numeru linii. `{file}` zostanie zastąpione nazwą pliku, a `{line}` numerem linii. -Open File at Line (Otwórz plik w linii) -: Wzorzec używany przez niestandardowy edytor do określenia, który plik ma być otwarty i na której linii. Wzorzec `{file}` zostanie zastąpiony nazwą pliku do otwarcia, a `{line}` numerem linii. +Code editor font +: Nazwa czcionki zainstalowanej w systemie, używanej w edytorze kodu. -Code editor font (Czcionka edytora kodu) -: Nazwa zainstalowanej systemowej czcionki do użycia w edytorze kodu. +Zoom on Scroll +: Określa, czy podczas przewijania w edytorze kodu z wciśniętym Cmd/Ctrl ma się zmieniać rozmiar czcionki. -### Otwieranie plików skryptów w programie Visual Studio Code +### Otwieranie plików skryptów w Visual Studio Code ![](images/editor/preferences_vscode.png) -Aby otworzyć pliki skryptów bezpośrednio z Edytora Defold w programie Microsoft Visual Studio Code, musisz ustawić następujące ustawienia, określając ścieżkę do pliku wykonywalnego: +Aby otwierać pliki skryptów z edytora Defold bezpośrednio w Visual Studio Code, ustaw poniższe wartości, podając ścieżkę do pliku wykonywalnego: -- macOS: /Applications/Visual Studio Code.app/Contents/MacOS/Electron -- Linux: /usr/bin/code -- Windows: C:\Program Files\Microsoft VS Code\Code.exe +- macOS: `/Applications/Visual Studio Code.app/Contents/MacOS/Electron` +- Linux: `/usr/bin/code` +- Windows: `C:\Program Files\Microsoft VS Code\Code.exe` Ustaw te parametry, aby otwierać konkretne pliki i linie: - Open File: `. {file}` - Open File at Line: `. -g {file}:{line}` -Znak . jest wymagany, aby otworzyć cały workspace, a nie pojedynczy plik. +Znak `.` jest tutaj wymagany, aby otworzyć cały obszar roboczy, a nie pojedynczy plik. -## Rozszerzenia +## Extensions ![](images/editor/preferences_extensions.png) Serwer budowania (Build Server) -: URL serwera budowania używanego podczas kompilacji projektu zawierającego rozszerzenia natywne (native extensions). Możliwe jest dodanie nazwy użytkownika i tokena dostępowego do URL w celu autoryzowanego dostępu do serwera budowania. Aby określić nazwę użytkownika (username) i token dostępowy, użyj następującej notacji: `username:token@build.defold.com`. Autoryzowany dostęp jest wymagany dla kompilacji na platformę Nintendo Switch oraz w przypadku uruchamiania własnej instancji serwera kompilacji z włączoną autoryzacją (dokładne informacje znajdziesz w [dokumentacji serwera budowania](https://github.com/defold/extender/blob/dev/README_SECURITY.md). Nazwę użytkownika i hasło można także ustawić jako zmienne środowiskowe systemu `DM_EXTENDER_USERNAME` i `DM_EXTENDER_PASSWORD`. +: URL serwera buildów używanego podczas budowania projektu zawierającego [native extensions](/manuals/extensions). Do URL można dodać nazwę użytkownika i token dostępu, aby uwierzytelnić się przy dostępie do serwera buildów. Użyj notacji `username:token@build.defold.com`. Uwierzytelniony dostęp jest wymagany przy buildach na Nintendo Switch oraz przy korzystaniu z własnej instancji serwera buildów z włączonym uwierzytelnianiem ([zobacz dokumentację serwera buildów](https://github.com/defold/extender/blob/dev/README_SECURITY.md)). Nazwę użytkownika i hasło można też ustawić w zmiennych środowiskowych `DM_EXTENDER_USERNAME` i `DM_EXTENDER_PASSWORD`. + +Build Server Username +: Nazwa użytkownika do uwierzytelniania. + +Build Server Password +: Hasło do uwierzytelniania. Zostanie zapisane w pliku preferencji w postaci zaszyfrowanej. -Nagłówki serwera budowania -: dodatkowe nagłówki serwera budowania przy budowaniu rozszerzeń natywnych. Jest to ważne, jeśli korzystasz z usługi CloudFlare lub podobnych usług z extenderem. +Build Server Headers +: Dodatkowe nagłówki wysyłane do serwera buildów podczas budowania rozszerzeń natywnych. Jest to ważne przy korzystaniu z CloudFlare lub podobnych usług razem z extenderem. -## Narzędzia +## Tools ![](images/editor/preferences_tools.png) -Ścieżka ADB -: Ścieżka do narzędzia linii komend [ADB](https://developer.android.com/tools/adb) zainstalowanego na tym systemie. Jeśli masz zainstalowane ADB na swoim systemie, edytor Defold użyje go do instalacji i uruchamiania spakowanych plików APK na połączonym urządzeniu z systemem Android. Domyślnie edytor sprawdza, czy ADB jest zainstalowane w znanych lokalizacjach, więc musisz podać ścieżkę tylko wtedy, gdy masz zainstalowane ADB w niestandardowym miejscu. +ADB path (Ścieżka ADB) +: Ścieżka do narzędzia wiersza poleceń [ADB](https://developer.android.com/tools/adb) zainstalowanego w systemie. Jeśli ADB jest dostępne, edytor Defold użyje go do instalowania i uruchamiania zbudowanych plików APK na podłączonym urządzeniu z Androidem. Domyślnie edytor sprawdza kilka znanych lokalizacji, więc ścieżkę trzeba podawać tylko wtedy, gdy ADB jest zainstalowane niestandardowo. + +ios-deploy path (Ścieżka ios-deploy) +: Ścieżka do narzędzia wiersza poleceń [ios-deploy](https://github.com/ios-control/ios-deploy) zainstalowanego w systemie. Dotyczy to tylko macOS. Podobnie jak przy `ADB path`, edytor Defold użyje tego narzędzia do instalowania i uruchamiania zbundlowanych aplikacji iOS na podłączonym iPhonie. Domyślnie edytor sprawdza kilka znanych lokalizacji, więc ścieżkę trzeba podać tylko wtedy, gdy korzystasz z niestandardowej instalacji `ios-deploy`. + +## Keymap + +![](images/editor/preferences_keymap.png) + +Możesz konfigurować skróty klawiszowe edytora, zarówno dodając własne, jak i usuwając wbudowane. Aby edytować skrót, użyj menu kontekstowego dla wybranego polecenia w tabeli skrótów albo kliknij dwukrotnie lub naciśnij Enter, aby otworzyć okno dodawania nowego skrótu. -Ścieżka ios-deploy -: Ścieżka do narzędzi linii komend ios-deploy zainstalowanych na tym systemie (dotyczy tylko macOS). Podobnie jak w przypadku ścieżki ADB, edytor Defold będzie używać tego narzędzia do instalacji i uruchamiania spakowanych aplikacji iOS na połączonym iPhone. Domyślnie edytor sprawdza, czy ios-deploy jest zainstalowane w znanych lokalizacjach, więc musisz podać ścieżkę tylko wtedy, gdy korzystasz z niestandardowej lokalizacji własnej instalacji ios-deploy. +Przy niektórych skrótach mogą pojawić się ostrzeżenia, wyświetlane na pomarańczowo. Najedź kursorem na skrót, aby zobaczyć szczegóły. Typowe ostrzeżenia to: +- typeable shortcuts: wybrany skrót można wpisać w polach tekstowych. Upewnij się, że polecenie jest wyłączone w kontekstach edycji kodu i wprowadzania tekstu. +- conflicts: ten sam skrót jest przypisany do wielu różnych poleceń. Upewnij się, że w chwili wywołania skrótu aktywne jest najwyżej jedno z nich, w przeciwnym razie edytor wykona jedno z przypisanych poleceń w nieokreślony sposób. diff --git a/docs/pl/manuals/factory.md b/docs/pl/manuals/factory.md index 1a40dbf9..37e76e5e 100644 --- a/docs/pl/manuals/factory.md +++ b/docs/pl/manuals/factory.md @@ -1,22 +1,22 @@ --- -title: Fabryka -brief: Ta instrukcja opisuje komponent fabryki służący do tworzenia obiektów gry z komponentami w czasie działania programu. +title: Instrukcja komponentu Factory +brief: Ta instrukcja wyjaśnia, jak używać komponentów Factory do dynamicznego tworzenia obiektów gry w runtime. --- -# Fabryka +# Komponenty Factory -Komponenty fabryki w Defoldzie służą do dynamicznego generowania obiektów gry z puli obiektów podczas działania gry. +Komponenty Factory służą do dynamicznego tworzenia obiektów gry z puli obiektów w działającej grze. -Gdy dodajesz komponent fabryki do obiektu gry, w właściwości *Prototype* określasz, jaki plik obiektu gry fabryka powinna używać jako prototyp (nazywany również "prefabem", "szablonem" czy "blueprintem" w innych silnikach) dla wszystkich nowych obiektów gry, które tworzy. +Gdy dodajesz komponent Factory do obiektu gry, we właściwości *Prototype* określasz, którego pliku obiektu gry fabryka ma używać jako prototypu. W innych silnikach taki prototyp bywa nazywany również prefabem albo blueprintem. Na tej podstawie tworzone są wszystkie nowe obiekty gry. -![Fabryka](images/factory/factory_collection.png) +![Factory component](images/factory/factory_collection.png) -![Fabryka](images/factory/factory_component.png) +![Factory component](images/factory/factory_component.png) -Aby wywołać utworzenie obiektu gry, należy wywołać funkcję `factory.create()`: +Aby utworzyć obiekt gry, wywołaj `factory.create()`: ```lua --- factory.script +-- plik factory.script local p = go.get_position() p.y = vmath.lerp(math.random(), min_y, max_y) local component = "#star_factory" @@ -25,39 +25,38 @@ factory.create(component, p) ![Spawned game object](images/factory/factory_spawned.png) -`factory.create()` przyjmuje 5 parameterów: +`factory.create()` przyjmuje 5 parametrów: `url` -: Identyfikator komponentu fabryki, który ma utworzyć nowy obiekt gry. +: Id komponentu Factory, który ma utworzyć nowy obiekt gry. `[position]` -: (opcjonalne) pozycja w przestrzeni świata (world position) nowego obiektu gry. Powinien to być `vector3`. Jeśli nie określisz pozycji, obiekt gry zostanie utworzony w pozycji komponentu fabryki. +: (opcjonalnie) Pozycja nowego obiektu gry w przestrzeni świata. Powinien to być `vector3`. Jeśli nie podasz pozycji, obiekt zostanie utworzony w pozycji komponentu Factory. `[rotation]` -: (opcjonalne) obrót w przestrzeni świata (world rotation) nowego obiektu gry. Powinien to być kwaternion - `quat`. +: (opcjonalnie) Obrót nowego obiektu gry w przestrzeni świata. Powinien to być `quat`. `[properties]` -: (opcjonalne) tabela Lua z wartościami właściwości skryptu do zainicjowania obiektu gry. Zobacz szczegóły w [instrukcji o właściwościach skryptu](/manuals/script-properties). +: (opcjonalnie) Tabela Lua z wartościami właściwości skryptu, którymi ma zostać zainicjowany obiekt gry. Informacje o właściwościach skryptu znajdziesz w [instrukcji Script property](/manuals/script-properties). `[scale]` -: (opcjonalne) skala utworzonego obiektu gry. Skalę można wyrazić jako liczbę - `number` (większą niż 0), która określa jednolitą skalę we wszystkich osiach. Możesz też podać `vector3`, gdzie każdy komponent określa skalę w odpowiedniej osi. +: (opcjonalnie) Skala utworzonego obiektu gry. Skalę można podać jako `number` większy od 0, co oznacza jednakowe skalowanie we wszystkich osiach. Możesz też przekazać `vector3`, gdzie każdy składnik określa skalowanie w odpowiadającej osi. Na przykład: ```lua --- factory.script +-- plik factory.script local p = go.get_position() p.y = vmath.lerp(math.random(), min_y, max_y) local component = "#star_factory" --- Utwórz obiekt z obrotem 0, ale podwójną skalą. --- Ustaw wartość punktową "score" na 10. +-- Utwórz bez obrotu, ale z podwójną skalą. +-- Ustaw wartość właściwości score gwiazdy na 10. factory.create(component, p, nil, { score = 10 }, 2.0) -- <1> ``` - -1. Ustala wartość punktową obiektu gry gwiazdy. +1. Ustawia właściwość `"score"` obiektu gry gwiazdy. ```lua --- star.script +-- plik star.script go.property("score", 1) -- <1> local speed = -240 @@ -78,20 +77,18 @@ function on_message(self, message_id, message, sender) end end ``` +1. Właściwość skryptu `"score"` jest zdefiniowana z wartością domyślną. +2. Odwołuje się do właściwości skryptu `"score"` jako do wartości przechowywanej w `self`. -1. Właściwość skryptu "score" jest zdefiniowana z wartością domyślną. -2. Odwołuje się do właściwości skryptu "score" jako przechowywanej wartości w "self". - -![utworzone obiekty](images/factory/factory_spawned2.png) +![Spawned game object with property and scaling](images/factory/factory_spawned2.png) ::: sidenote -Defold obecnie nie obsługuje nieliniowego skalowania kształtów kolizji. Jeśli podasz wartość nieliniowego skalowania, na przykład `vmath.vector3(1.0, 2.0, 1.0)` to sprite zostanie odpowiednio przeskalowany, ale kształty kolizji nie. +Defold nie obsługuje obecnie niejednorodnego skalowania kształtów kolizji. Jeśli podasz wartość niejednorodnego skalowania, na przykład `vmath.vector3(1.0, 2.0, 1.0)`, sprite zostanie przeskalowany poprawnie, ale kształty kolizji już nie. ::: +## Adresowanie obiektów utworzonych przez Factory -## Adresowanie obiektów utworzonych z fabryki - -Mechanizm adresowania Defolda umożliwia dostęp do każdego obiektu i komponentu w trakcie działania gry. [Instrukcja adresowania](/manuals/addressing/) zawiera szczegółowe informacje na temat działania tego systemu. Ten mechanizm można również wykorzystać do dostępu do utworzonych obiektów gry i ich komponentów. Najczęściej wystarcza użycie identyfikatora utworzonego obiektu, na przykład w celu wysłania wiadomości: +Mechanizm adresowania Defold pozwala uzyskać dostęp do każdego obiektu i komponentu w działającej grze. [Instrukcja Addressing](/manuals/addressing/) szczegółowo wyjaśnia, jak ten system działa. Tego samego mechanizmu można używać również dla utworzonych obiektów gry i ich komponentów. Często wystarczy użycie id utworzonego obiektu, na przykład przy wysyłaniu wiadomości: ```lua local function create_hunter(target_id) @@ -102,10 +99,10 @@ end ``` ::: sidenote -Przesłanie wiadomości bezpośrednio do obiektu gry, a nie do określonego komponentu, w rzeczywistości wysyła wiadomość do wszystkich komponentów tego obiektu. Zazwyczaj nie stanowi to problemu, ale warto pamiętać, jeśli obiekt ma wiele komponentów. +Wysłanie wiadomości do samego obiektu gry zamiast do konkretnego komponentu w praktyce rozsyła ją do wszystkich komponentów tego obiektu. Zwykle nie stanowi to problemu, ale warto o tym pamiętać, jeśli obiekt ma dużo komponentów. ::: -Ale co, jeśli musisz uzyskać dostęp do konkretnego komponentu na utworzonym obiekcie gry, na przykład, aby wyłączyć obiekt kolizji lub zmienić obraz sprite'a? Rozwiązaniem jest skonstruowanie adresu URL na podstawie identyfikatora obiektu gry i identyfikatora komponentu: +Co jednak zrobić, gdy chcesz uzyskać dostęp do konkretnego komponentu utworzonego obiektu gry, na przykład aby wyłączyć obiekt kolizji albo zmienić obraz sprite'a? Rozwiązaniem jest zbudowanie adresu URL z id obiektu gry i id komponentu. ```lua local function create_guard(unarmed) @@ -120,149 +117,150 @@ local function create_guard(unarmed) end ``` -## Śledzenie utworzonych obiektów i rodziców +## Śledzenie utworzonych obiektów i obiektów nadrzędnych -Wywołując `factory.create()` otrzymujesz identyfikator nowego obiektu gry, co pozwala na przechowywanie go do użycia później. Jednym z powszechnych zastosowań jest generowanie obiektów i dodawanie ich identyfikatorów do tabeli, dzięki czemu można je usunąć w późniejszym momencie, na przykład podczas resetowania układu poziomu: +Gdy wywołasz `factory.create()`, otrzymasz z powrotem id nowego obiektu gry, dzięki czemu możesz zachować je do późniejszego użycia. Często wykorzystuje się to do tworzenia obiektów i dodawania ich id do tabeli, aby później usunąć je wszystkie, na przykład przy resetowaniu układu poziomu: ```lua --- spawner.script +-- plik spawner.script self.spawned_coins = {} ... --- Spawn a coin and store it in the "coins" table. +-- Utwórz monetę i zapisz ją w tabeli "coins". local id = factory.create("#coinfactory", coin_position) table.insert(self.spawned_coins, id) ``` -I później: +A później: ```lua --- spawner.script --- Usuń utworzone monety +-- plik spawner.script +-- Usuń wszystkie utworzone monety. for _, coin_id in ipairs(self.spawned_coins) do go.delete(coin_id) end --- lub alternatywnie: +-- albo alternatywnie go.delete(self.spawned_coins) ``` -Warto też wiedzieć jakie obiekty się utworzyło w świecie gry. Przykładem może być obiekt, którego instancję chcemy mieć tylko jedną w jednym czasie. Utworzony obiekt musi wtedy poinformować swojego twórcę (spawner) kiedy jest usunięty lub nieaktywny, dzięki czemu spawner będzie mógł utworzyć następną instancję: +Często chcesz też, aby utworzony obiekt wiedział, który obiekt gry go utworzył. Jednym z przykładów jest autonomiczny obiekt, który może istnieć tylko w jednej instancji naraz. Taki obiekt musi poinformować spawner, że został usunięty lub zdezaktywowany, aby można było utworzyć kolejny: ```lua --- spawner.script --- Utwórz drona i ustaw jego rodzica na url tego skryptu +-- plik spawner.script +-- Utwórz drona i ustaw jego rodzica na URL tego komponentu skryptu self.spawned_drone = factory.create("#dronefactory", drone_position, nil, { parent = msg.url() }) ... function on_message(self, message_id, message, sender) if message_id == hash("drone_dead") then - self.spawed_drone = nil + self.spawned_drone = nil end end ``` -A to logika utworzonego obiektu: +A logika utworzonego obiektu wygląda tak: + ```lua --- drone.script +-- plik drone.script go.property("parent", msg.url()) ... function final(self) - -- I'm dead. + -- Koniec działania obiektu. msg.post(self.parent, "drone_dead") end ``` -## Dynamiczne ładowanie zasobów fabryki +## Dynamiczne ładowanie zasobów Factory -Zaznaczając opcję *Load Dynamically* (Ładuj dynamicznie) we właściwościach fabryki, silnik Defold odkłada w czasie ładowanie zasobów związanych z fabryką. +Po zaznaczeniu pola *Load Dynamically* we właściwościach Factory silnik odracza ładowanie zasobów powiązanych z fabryką. ![Load dynamically](images/factory/load_dynamically.png) -Gdy opcja jest niezaznaczona, silnik ładuje zasoby prototypu, gdy komponent fabryki jest ładowany, więc są one od razu gotowe do generowania. +Gdy pole nie jest zaznaczone, silnik ładuje zasoby prototypu podczas ładowania komponentu Factory, więc są one od razu gotowe do użycia. -Z opcją zaznaczoną, masz dwie możliwości użycia fabryki: +Gdy pole jest zaznaczone, masz dwa sposoby użycia: -Synchroniczne wczytywanie -: Wywołaj [`factory.create()`](/ref/factory/#factory.create), gdy chcesz generować obiekty. Spowoduje to synchroniczne ładowanie zasobów, co może powodować przycięcia w zależności od wielkości zasobu, a następnie tworzenie nowych instancji. +Ładowanie synchroniczne +: Wywołaj [`factory.create()`](/ref/factory/#factory.create), gdy chcesz utworzyć obiekty. Spowoduje to synchroniczne załadowanie zasobów, co może wywołać przycięcie, a następnie utworzenie nowych instancji. ```lua function init(self) - -- Gdy komponent fabryki jest ładowany, nie są jeszcze dostępne zasoby fabryki. - -- Wywołanie create bez wcześniejszego wywołania load spowoduje synchroniczne - -- ładowanie zasobów. + -- Gdy zostanie wczytana kolekcja nadrzędna fabryki, + -- zasoby fabryki nie są jeszcze załadowane. Wywołanie create + -- bez wcześniejszego load utworzy zasoby synchronicznie. self.go_id = factory.create("#factory") end function final(self) - -- Usuwa obiekty gry. Zasoby zostaną zwolnione. - -- W tym przypadku zasoby zostaną usunięte, ponieważ komponent fabryki - -- nie trzyma referencji. + -- Usuń obiekty gry. Zmniejszy to licznik referencji zasobów. + -- W tym przypadku zasoby zostaną usunięte, ponieważ komponent + -- fabryki nie trzyma już do nich referencji. go.delete(self.go_id) - -- Wywołanie unload nie spowoduje żadnych działań, - -- ponieważ komponent fabryki nie trzyma referencji. + -- Wywołanie unload nic nie zrobi, bo fabryka nie ma referencji. factory.unload("#factory") end ``` -Asynchroniczne wczytywanie -: Wywołaj [`factory.load()`](/ref/factory/#factory.load), aby jawnie załadować zasoby asynchronicznie. Po zakończeniu ładowania zasobów, są one gotowe do generowania - wywołane wtedy zostanie wywołanie zwrotne (callback). +Ładowanie asynchroniczne +: Wywołaj [`factory.load()`](/ref/factory/#factory.load), aby jawnie załadować zasoby asynchronicznie. Gdy zasoby będą gotowe do tworzenia obiektów, otrzymasz callback. ```lua function load_complete(self, url, result) - -- Ładowanie jest zakończone, zasoby są gotowe do generowania. + -- Ładowanie zakończone, zasoby są gotowe do tworzenia instancji. self.go_id = factory.create(url) end function init(self) - -- Gdy komponent fabryki jest ładowany, nie są jeszcze dostępne zasoby fabryki. - -- Wywołanie load spowoduje ładowanie zasobów. + -- Gdy zostanie wczytana kolekcja nadrzędna fabryki, + -- zasoby fabryki nie są jeszcze załadowane. Wywołanie load + -- spowoduje ich wczytanie. factory.load("#factory", load_complete) end function final(self) - -- Usuwa obiekt gry. Zasoby nie zostaną zwolnione, - -- ponieważ komponent fabryki nadal trzyma referencję. + -- Usuń obiekt gry. Zmniejszy to licznik referencji zasobów. + -- W tym przypadku zasoby nie zostaną usunięte, ponieważ komponent + -- fabryki nadal trzyma do nich referencję. go.delete(self.go_id) - -- Wywołanie unload spowoduje zwolnienie zasobów trzymanych przez komponent fabryki, - -- co spowoduje zniszczenie zasobów. + -- Wywołanie unload zmniejszy licznik referencji zasobów + -- trzymanych przez komponent fabryki, co doprowadzi do ich usunięcia. factory.unload("#factory") end ``` ## Dynamiczny prototyp -Możliwa jest zmiana prototypu *Prototype*, który ma utworzyć fabryka, zaznaczając opcję *Dynamic Prototype* we właściwościach fabryki. +Można zmienić prototyp tworzony przez Factory przez zaznaczenie pola *Dynamic Prototype* we właściwościach komponentu. ![Dynamic prototype](images/factory/dynamic_prototype.png) -Gdy opcja *Dynamic Prototype* jest zaznaczona, komponent fabryki może zmieniać prototyp, używając funkcji `factory.set_prototype()`. Przykład: +Gdy opcja *Dynamic Prototype* jest włączona, komponent Factory może zmieniać prototyp przy użyciu funkcji `factory.set_prototype()`. Przykład: ```lua factory.unload("#factory") -- zwolnij poprzednie zasoby -factory.set_prototype("#factory", "/main/levels/enemyA.goc") -local enemy_id = factory.create("#factory") +factory.set_prototype("#factory", "/main/levels/enemy.go") +local id = factory.create("#factory") ``` ::: important -Gdy opcja *Dynamic Prototype* jest ustawiona, ilość komponentów w kolekcji nie może być optymalizowana, a zawierająca kolekcja będzie korzystać z domyślnych liczby komponentów z pliku *game.project*. +Gdy opcja *Dynamic Prototype* jest włączona, liczba komponentów w kolekcji nie może zostać zoptymalizowana, a kolekcja właściciela będzie używać domyślnych limitów komponentów z pliku *game.project*. ::: +## Limity instancji -## Limit instancji - -Ustawienie *max_instances* w ustawieniach związanych z kolekcją (*Collection related settings*) ogranicza łączną liczbę instancji obiektów gry, które mogą istnieć w świecie (główna kolekcja "main.collection" wczytana podczas uruchamiania lub dowolny świat wczytany za pośrednictwem pełnomocnika kolekcji). Wszystkie obiekty gry, które istnieją w świecie, są wliczane do tego limitu, niezależnie od tego, czy są umieszczone ręcznie w edytorze, czy generowane dynamicznie za pomocą skryptu. +Ustawienie projektu *max_instances* w sekcji *Collection related settings* ogranicza łączną liczbę instancji obiektów gry, które mogą istnieć w jednym świecie. Dotyczy to zarówno `main.collection` wczytywanej przy starcie, jak i dowolnego świata załadowanego przez Collection proxy. Do tego limitu wliczają się wszystkie obiekty gry istniejące w świecie, niezależnie od tego, czy zostały ręcznie umieszczone w edytorze, czy utworzone w czasie działania przez skrypt. ![Limit instancji](images/factory/factory_max_instances.png) -Jeśli ustawisz *max_instances* na 1024 i masz 24 ręcznie umieszczone obiekty gry w swojej głównej kolekcji, możesz utworzyć dodatkowe 1000 obiektów gry. Gdy tylko usuniesz obiekt gry, będziesz mógł utworzyć nową instancję. +Jeśli ustawisz *max_instances* na `1024` i masz 24 obiekty gry ręcznie umieszczone w głównej kolekcji, możesz dodatkowo utworzyć 1000 obiektów gry. Gdy tylko usuniesz jakiś obiekt gry, możesz utworzyć kolejną instancję. ## Pula obiektów gry -Może się wydawać, że dobrym pomysłem jest zapisywanie utworzonych obiektów gry w puli i ponowne ich użycie. Jednak silnik Defold wykonuje już pulowanie obiektów pod spodem, więc dodatkowe obciążenie spowolni działanie. Szybsze i bardziej przejrzyste jest usuwanie obiektów gry i tworzenie nowych. +Może się wydawać, że dobrym pomysłem jest przechowywanie utworzonych obiektów gry w puli i ponowne ich wykorzystywanie. Silnik i tak stosuje jednak pooling obiektów wewnętrznie, więc dodatkowa warstwa narzutu tylko spowolni działanie. Szybciej i czyściej jest usuwać obiekty gry i tworzyć nowe. diff --git a/docs/pl/manuals/lua.md b/docs/pl/manuals/lua.md index e91affa9..951e2b92 100644 --- a/docs/pl/manuals/lua.md +++ b/docs/pl/manuals/lua.md @@ -1,42 +1,33 @@ --- -title: Programowanie Lua w Defoldzie -brief: Ta instrukcja przedstawi krótkie wprowadzenie do podstaw programowania w języku Lua ogólnie oraz to, na co należy zwrócić uwagę podczas pracy z Lua w Defoldzie. +title: Programowanie w Lua w silniku Defold +brief: Ta instrukcja krótko wprowadza w podstawy programowania w języku Lua i wyjaśnia, na co zwracać uwagę podczas pracy z Lua w silniku Defold. --- -# Lua w Defoldzie +# Lua w silniku Defold -Silnik Defold ma wbudowany język Lua do skryptowania. Lua to lekki język dynamiczny, który jest potężny, szybki i łatwy do osadzenia. Jest powszechnie używany jako język skryptowy w grach wideo. Programy w Lua są napisane w prostym składni proceduralnym. Język jest dynamicznie typowany i uruchamiany przez interpreter kodu bajtowego. Posiada automatyczne zarządzanie pamięcią z inkrementalnym zbieraniem śmieci. +Silnik Defold ma wbudowany język Lua do skryptowania. Lua to lekki język dynamiczny, który jest wydajny, szybki i łatwy do osadzenia. Jest powszechnie używany jako język skryptowy w grach wideo. Programy w Lua zapisuje się prostą składnią proceduralną. Język jest dynamicznie typowany i wykonywany przez interpreter kodu bajtowego. Oferuje automatyczne zarządzanie pamięcią z inkrementalnym odśmiecaniem. -Ta instrukcja przedstawi krótkie wprowadzenie do podstaw programowania w Lua ogólnie oraz to, na co należy zwrócić uwagę podczas pracy z Lua w Defoldzie. Jeśli masz pewne doświadczenie z Pythonem, Perlem, Rubym, Javascriptem lub podobnym językiem dynamicznym, szybko się dostosujesz. Jeśli jesteś zupełnie nowy w programowaniu, możesz rozpocząć od książki o Lua skierowanej dla początkujących. Jest ich wiele do wyboru. +Ta instrukcja krótko wprowadza w podstawy programowania w Lua i wyjaśnia, na co zwracać uwagę podczas pracy z Lua w silniku Defold. Jeśli masz już doświadczenie z Pythonem, Perlem, Rubym, JavaScriptem lub podobnym językiem dynamicznym, szybko się odnajdziesz. Jeśli dopiero zaczynasz programować, warto sięgnąć po książkę o Lua dla początkujących. Do wyboru jest ich wiele. ## Wersje Lua -Staramy się, aby Defold był taki sam na wszystkich platformach, ale obecnie mamy kilka drobnych rozbieżności w wersji języka Lua między platformami: +[LuaJIT](https://luajit.org/) to mocno zoptymalizowana wersja Lua, dobrze nadająca się do gier i innego oprogramowania krytycznego pod względem wydajności. Jest w pełni kompatybilna w górę z Lua 5.1 i obsługuje wszystkie standardowe funkcje bibliotek Lua oraz pełny zestaw funkcji Lua/C API. -| Platforma | Wersja Lua | JIT Włączony | -|------------------|---------------------|--------------| -| Windows | LuaJIT 2.1.0-beta3 | Tak | -| macOS | LuaJIT 2.1.0-beta3 | Tak | -| Linux | LuaJIT 2.1.0-beta3 | Tak | -| Android | LuaJIT 2.1.0-beta3 | Tak | -| iOS | LuaJIT 2.1.0-beta3 | Nie* | -| Nintendo Switch | LuaJIT 2.1.0-beta3 | Nie* | -| HTML5 | Lua 5.1.4 | N/A | +LuaJIT dodaje też kilka [rozszerzeń języka](https://luajit.org/extensions.html) oraz część funkcji z Lua 5.2 i 5.3. -*=Kod kompilowany JIT nie jest dozwolony - -[LuaJIT](https://luajit.org/) to bardzo zoptymalizowana wersja Lua, odpowiednia do użycia w grach i innych krytycznych pod względem wydajności oprogramowaniu. LuaJIT jest w pełni kompatybilny w górę z Lua 5.1. Obsługuje wszystkie standardowe funkcje biblioteki Lua oraz pełen zestaw funkcji Lua/C API. - -LuaJIT dodaje również kilka [rozszerzeń języka](https://luajit.org/extensions.html) i niektóre funkcje z Lua 5.2. +Chcemy, aby Defold zachowywał się tak samo na wszystkich platformach, ale obecnie istnieje kilka drobnych różnic dotyczących wersji Lua: +* iOS nie pozwala na kompilację JIT. +* Nintendo Switch nie pozwala na kompilację JIT. +* HTML5 używa Lua 5.1.4 zamiast LuaJIT. ::: important Aby zagwarantować, że Twoja gra działa na wszystkich obsługiwanych platformach, gorąco zalecamy korzystanie TYLKO z funkcji języka z wersji Lua 5.1. ::: ### Biblioteki standardowe i rozszerzenia -Defold zawiera wszystkie [standardowe biblioteki Lua 5.1](http://www.lua.org/manual/5.1/manual.html#5), a także bibliotekę do operacji na gniazdach i operacji bitowych: +Defold zawiera wszystkie [standardowe biblioteki Lua 5.1](http://www.lua.org/manual/5.1/manual.html#5), a także bibliotekę socket i bibliotekę operacji bitowych: - - base (`assert()`, `error()`, `print()`, `ipairs()`, `require()`, itp.) + - base (`assert()`, `error()`, `print()`, `ipairs()`, `require()` itd.) - coroutine - package - string @@ -53,22 +44,23 @@ Wszystkie biblioteki są udokumentowane w [dokumentacji API](/ref/go). ## Książki i zasoby Lua ### Zasoby online -* [Programowanie w Lua (pierwsza edycja)](http://www.lua.org/pil/contents.html) Dostępne są późniejsze edycje w wersji drukowanej. -* [Podręcznik referencyjny Lua 5.1](http://www.lua.org/manual/5.1/) -* [Naucz się Lua w 15 minut](http://tylerneylon.com/a/learn-lua/) -* [Niesamowita Lua - sekcja z tutorialami](https://github.com/LewisJEllis/awesome-lua#tutorials) +* [Programming in Lua (first edition)](http://www.lua.org/pil/contents.html) Późniejsze wydania są dostępne w druku. +* [Lua 5.1 reference manual](http://www.lua.org/manual/5.1/) +* [Learn Lua in 15 Minutes](http://tylerneylon.com/a/learn-lua/) +* [Awesome Lua - tutorial section](https://github.com/LewisJEllis/awesome-lua#tutorials) ### Książki -* [Programowanie w Lua](https://www.amazon.com/gp/product/8590379868/ref=dbs_a_def_rwt_hsch_vapi_taft_p1_i0) - Programowanie w Lua to oficjalna książka o języku, stanowiąca solidną podstawę dla każdego programisty, który chce używać Lua. Autorstwa Roberto Ierusalimschy, głównego architekta języka. -* [Lua programming gems](https://www.amazon.com/gp/product/8590379868/ref=dbs_a_def_rwt_hsch_vapi_taft_p1_i0) - Lua Programming Gems to zbiór krótkich i zrozumiałych przepisów, stworzonych przez różnych doświadczonych programistów Lua. Książka ta oferuje wiele przydatnych porad i trików dotyczących programowania w Lua. -* [Beginning Lua Programming](https://www.amazon.com/gp/product/1484219602/ref=dbs_a_def_rwt_hsch_vapi_taft_p1_i0) - Ta książka zawiera wiele praktycznych przykładów i projektów, które pomogą Ci opanować język Lua. Jest odpowiednia dla początkujących programistów, ale oferuje także bardziej zaawansowane tematy dla tych, którzy chcą pogłębić swoją wiedzę. -* [Programming in Lua](https://www.amazon.com/gp/product/8590379868/ref=dbs_a_def_rwt_hsch_vapi_taft_p1_i0) - Kolejna dobra książka na temat Lua, napisana przez Roberto Ierusalimschy, jednego z autorów języka Lua. Obejmuje wiele aspektów języka Lua i dostarcza praktyczne wskazówki oraz porady dotyczące programowania w nim. +* [Programming in Lua](https://www.amazon.com/gp/product/8590379868/ref=dbs_a_def_rwt_hsch_vapi_taft_p1_i0) - To oficjalna książka o języku, dająca solidne podstawy każdemu programiście chcącemu używać Lua. Jej autorem jest Roberto Ierusalimschy, główny architekt języka. +* [Lua programming gems](https://www.amazon.com/Programming-Gems-Luiz-Henrique-Figueiredo/dp/8590379841) - Zbiór artykułów dokumentujących dobre praktyki i sprawdzone podejścia do programowania w Lua. +* [Lua 5.1 reference manual](https://www.amazon.com/gp/product/8590379833/ref=dbs_a_def_rwt_hsch_vapi_taft_p1_i4) - Ta pozycja jest dostępna również online. +* [Beginning Lua Programming](https://www.amazon.com/Beginning-Lua-Programming-Kurt-Jung/dp/0470069171) -Oczywiście, istnieje wiele innych dostępnych materiałów i samouczków do nauki Lua, więc możesz wybrać te, które najlepiej odpowiadają Twoim potrzebom i poziomowi umiejętności. +### Wideo +* [Learn Lua in one video](https://www.youtube.com/watch?v=iMacxZQMPXs) ## Składnia języka Lua -Programy w Lua mają prostą, czytelną składnię. Instrukcje zapisywane są jedna na każdej linii, i nie ma potrzeby oznaczania końca instrukcji. Opcjonalnie można używać średników `;` do oddzielania instrukcji. Bloki kodu są ograniczane słowem kluczowym `end`. Komentarze mogą być blokowe lub do końca linii: +Programy w Lua mają prostą, czytelną składnię. Instrukcje zapisuje się po jednej w każdej linii i nie ma potrzeby oznaczania końca instrukcji. Opcjonalnie można używać średników `;` do oddzielania instrukcji. Bloki kodu są ograniczane słowem kluczowym `end`. Komentarze mogą być blokowe lub jednolinijkowe: ```lua --[[ @@ -91,7 +83,7 @@ end Lua jest językiem dynamicznym, co oznacza, że zmienne nie mają określonych typów, ale wartości już mają. W odróżnieniu od języków o typach statycznych, możesz przypisać dowolną wartość do dowolnej zmiennej. W Lua istnieje osiem podstawowych typów wartości: `nil` -: Ten typ ma tylko jedna wartość, `nil`. Zazwyczaj reprezentuje brak przydatnej wartości, na przykład nieprzypisane zmienne. +: Ten typ ma tylko jedną wartość: `nil`. Zazwyczaj reprezentuje brak przydatnej wartości, na przykład nieprzypisane zmienne. ```lua print(my_var) -- wyświetli 'nil', ponieważ 'moja_zmienna' nie ma jeszcze przypisanej wartości @@ -251,7 +243,7 @@ function ``` `userdata` -: Userdata (dane użytkownika) pozwala na przechowywanie dowolnych danych C w zmiennych Lua. W Defoldzie, userdata Lua służy do przechowywania wartości Hash (`hash`), obiektów URL (`url`), obiektów Math (`vector3`, `vector4`, `matrix4`, `quaternion`), obiektów gry, węzłów GUI (`GUI node`), predykatów renderowania (`predicate`), celów renderowania (`render_target`) oraz buforów stałych renderowania (`constant_buffer`). +: Userdata (dane użytkownika) pozwala przechowywać dowolne dane C w zmiennych Lua. W silniku Defold userdata Lua służy do przechowywania wartości Hash (`hash`), obiektów URL (`url`), obiektów Math (`vector3`, `vector4`, `matrix4`, `quaternion`), obiektów gry, węzłów GUI (`GUI node`), predykatów renderowania (`predicate`), celów renderowania (`render_target`) oraz buforów stałych renderowania (`constant_buffer`). `thread` : Wątki reprezentują niezależne wątki wykonywania i są używane do implementacji korygujących. Zobacz poniżej dla szczegółów. @@ -360,7 +352,7 @@ while weekdays = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"} - -- Print each weekday + -- Wypisz każdy dzień tygodnia i = 1 while weekdays[i] do print(weekdays[i]) @@ -375,7 +367,7 @@ repeat---until weekdays = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"} - -- Print each weekday + -- Wypisz każdy dzień tygodnia i = 0 repeat i = i + 1 @@ -546,9 +538,9 @@ end ``` -## Konteksty Lua w Defoldzie +## Konteksty Lua w silniku Defold -Wszystkie zmienne, które deklarujesz, są domyślnie globalne, co oznacza, że są dostępne we wszystkich częściach kontekstu uruchomienia Lua (ang. Lua runtime context). W Defoldzie istnieje opcja *shared_state* w pliku *game.project*, która kontroluje ten kontekst. Jeśli opcja jest ustawiona, wszystkie skrypty, skrypty GUI i skrypt renderowania są oceniane w tym samym kontekście Lua, a zmienne globalne są widoczne wszędzie. Jeśli opcja nie jest ustawiona, silnik wykonuje skrypty, skrypty GUI i skrypt renderowania w osobnych kontekstach. +Wszystkie deklarowane zmienne są domyślnie globalne, co oznacza, że są dostępne we wszystkich częściach kontekstu uruchomieniowego Lua (ang. Lua runtime context). W pliku *game.project* znajduje się opcja *shared_state*, która steruje tym zachowaniem. Jeśli jest włączona, wszystkie skrypty, skrypty GUI i skrypt renderowania są wykonywane w tym samym kontekście Lua, a zmienne globalne są widoczne wszędzie. Jeśli jest wyłączona, silnik wykonuje skrypty, skrypty GUI i skrypt renderowania w osobnych kontekstach. ![Contexts](images/lua/lua_contexts.png) diff --git a/docs/pl/manuals/mesh.md b/docs/pl/manuals/mesh.md index 307205e1..33fa3f8f 100644 --- a/docs/pl/manuals/mesh.md +++ b/docs/pl/manuals/mesh.md @@ -1,56 +1,56 @@ --- -title: Komponent Mesh w Defoldzie -brief: Ta instrukcja opisuje jak działają komponenty typu Mesh służące do wyśweitlania obiektów 3D. +title: Siatki 3D w Defold +brief: Ta instrukcja opisuje, jak tworzyć siatki 3D w czasie działania gry. --- -# Komponent Mesh (Siatka) +# Komponent Mesh -Defold to od podstaw silnik 3D. Nawet w przypadku pracy tylko z materiałem 2D, całe renderowanie jest wykonywane w 3D, ale rzutowane ortograficznie na ekran. Defold pozwala na korzystanie z pełnej zawartości 3D poprzez dodawanie i tworzenie komponentów 3D w czasie wykonywania w kolekcjach. Możesz tworzyć gry w czystym 3D, korzystając tylko z aktywów 3D, lub mieszać zawartość 3D i 2D według własnych preferencji. Komponent typu Mesh - Siatka jest jednym z komponentów do obsługi elementów trójwymiarowych. +Defold jest w swojej istocie silnikiem 3D. Nawet gdy pracujesz wyłącznie z materiałami 2D, całe renderowanie odbywa się w 3D, a następnie jest rzutowane ortograficznie na ekran. Defold pozwala korzystać z pełnej zawartości 3D przez dodawanie i tworzenie siatek 3D w czasie działania w kolekcjach. Możesz tworzyć gry całkowicie trójwymiarowe albo dowolnie łączyć zawartość 3D i 2D. -## Tworzenie komponentu Siatki +## Tworzenie komponentu Mesh -Komponenty Siatki - mesh są tworzone tak samo jak każdy inny komponent obiektu gry. Możesz to zrobić na dwa sposoby: +Komponenty Mesh tworzy się tak samo jak inne komponenty obiektów gry. Można to zrobić na dwa sposoby: -- Utwórz plik Mesh klikając prawym przyciskiem myszy w lokalizacji w panelu *Assets* i wybierając New... ▸ Mesh. -- Utwórz komponent osadzony bezpośrednio w obiekcie gry klikając prawym przyciskiem myszy na obiekcie gry w panelu *Outline* i wybierając Add Component ▸ Mesh. +- Utwórz plik *Mesh* przez kliknięcie prawym przyciskiem myszy w wybranym miejscu panelu *Assets* i wybranie New... ▸ Mesh. +- Utwórz komponent osadzony bezpośrednio w obiekcie gry przez kliknięcie prawym przyciskiem myszy obiektu gry w widoku *Outline* i wybranie Add Component ▸ Mesh. -![Mesh w obiekcie gry](images/mesh/mesh.png) +![Mesh in game object](images/mesh/mesh.png) -Po utworzeniu Siatki musisz określić szereg właściwości (properties): +Po utworzeniu siatki musisz ustawić kilka właściwości: -### Właściwości Siatki +### Właściwości komponentu Mesh -Oprócz właściwości *Id*, *Position* i *Rotation* istnieją następujące właściwości specyficzne dla komponentu typu Mesh: +Poza właściwościami *Id*, *Position* i *Rotation* dostępne są następujące właściwości specyficzne dla tego komponentu: *Material* -: Materiał do użycia podczas renderowania Siatki trójwymiarowej. +: Materiał używany do renderowania siatki. *Vertices* -: Plik bufora opisujący dane Siatki dla strumienia. +: Plik bufora opisujący dane siatki dla poszczególnych strumieni. *Primitive Type* -: Typ prymitywu: Linie, Trójkąty lub Trójkąty Strip (Lines, Triangles or Triangle Strip). +: Linie, Triangles albo Triangle Strip. *Position Stream* -: Strumień pozycji - ta właściwość powinna zawierać nazwę strumienia *position*. Strumień jest automatycznie dostarczany jako wejście do vertex shadera (shadera wierzchołków). +: Nazwa strumienia *position*. Ten strumień jest automatycznie przekazywany do vertex shadera. *Normal Stream* -: Strumień normalnych - ta właściwość powinna zawierać nazwę strumienia *normal*. Strumień jest automatycznie dostarczany jako wejście do vertex shadera. +: Nazwa strumienia *normal*. Ten strumień jest automatycznie przekazywany do vertex shadera. *tex0* -: Ustaw to na teksturę do użycia na siatce. +: Tekstura używana przez siatkę. -## Manipulacja w Edytorze +## Edycja w edytorze -Dzięki komponentowi typu Mesh możesz swobodnie edytować i manipulować komponentem i/lub otaczającym obiektem gry za pomocą standardowych narzędzi Edytora sceny (*Scene Editor*), aby dostosować pozycję, obrót i skalowanie Siatki według swojego uznania. +Po dodaniu komponentu Mesh możesz edytować i przekształcać zarówno sam komponent, jak i obiekt gry, który go zawiera, za pomocą standardowych narzędzi *Scene Editor*, aby przesuwać, obracać i skalować siatkę według potrzeb. -## Manipulacja w czasie rzeczywistym +## Modyfikacja w czasie działania -Możesz manipulować meshami w czasie wykonania programu, korzystając z buforów Defolda. Oto przykład tworzenia sześcianu z pasów trójkątów: +Siatki można modyfikować w czasie działania przy użyciu buforów Defold. Przykład utworzenia sześcianu z pasów trójkątów: ```Lua --- definicja wierzchołków sześcianu +-- sześcian local vertices = { 0, 0, 0, 0, 1, 0, @@ -68,7 +68,7 @@ local vertices = { 0, 1, 0 } --- utwórz bufor z danymi pozycji +-- utwórz bufor ze strumieniem pozycji local buf = buffer.create(#vertices / 3, { { name = hash("position"), type=buffer.VALUE_TYPE_FLOAT32, count = 3 } }) @@ -79,29 +79,30 @@ for i, value in ipairs(vertices) do positions[i] = vertices[i] end --- ustaw bufor z wierzchołkami w siatce +-- ustaw bufor z wierzchołkami w komponencie Mesh local res = go.get("#mesh", "vertices") resource.set_buffer(res, buf) ``` -Aby uzyskać więcej informacji na temat korzystania z komponentu Mesh, w tym projektów przykładowych i fragmentów kodu, zapoznaj się z [postem ogłoszeniowym na forum](https://forum.defold.com/t/mesh-component-in-defold-1-2-169-beta/65137. +Więcej informacji o korzystaniu z komponentu Mesh, wraz z przykładowymi projektami i fragmentami kodu, znajdziesz w [poście ogłoszeniowym na forum](https://forum.defold.com/t/mesh-component-in-defold-1-2-169-beta/65137). ## Frustum culling -Frustum culling, czyli odrzucanie widoku spoza bryły widoku to funkcjonalność pozwalająca usuwać powierzchnie spoza widoku określonego przez specjalną bryłę (frustum) w celu zyskiwaniu na szybkości renderowania. Komponenty typu Mesh nie są automatycznie odrzucane ze względu na ich dynamiczną naturę i fakt, że niemożliwe jest dokładne ustalenie, w jaki sposób dane pozycyjne są kodowane. Aby odrzucić mesh, należy ustawić prostopadłościenne obramowanie otaczające mesh jako metadane w buforze za pomocą 6 liczb zmiennoprzecinkowych (AABB min/max): +Komponenty Mesh nie są automatycznie odrzucane, ponieważ mają dynamiczny charakter i nie da się jednoznacznie określić, jak zakodowano dane pozycyjne. Aby włączyć odrzucanie siatki, trzeba zapisać w metadanych bufora ograniczający ją axis-aligned bounding box za pomocą 6 liczb zmiennoprzecinkowych (AABB min/max): ```lua buffer.set_metadata(buf, hash("AABB"), { 0, 0, 0, 1, 1, 1 }, buffer.VALUE_TYPE_FLOAT32) ``` -## Stałe materiałowe +## Stałe materiału {% include shared/material-constants.md component='mesh' variable='tint' %} `tint` -: odcień/barwa Siatki (typu `vector4`). Wektor 4-składnikowy jest używany do reprezentowania odcienia z X, Y, Z i W odpowiadającymi kolorami czerwonym, zielonym, niebieskim i alfa (przezroczystości). +: Odcień koloru siatki (`vector4`). Wektor `vector4` reprezentuje odcień, gdzie `x`, `y`, `z` i `w` odpowiadają odpowiednio kanałom czerwieni, zieleni, błękitu i alfa. -## Przestrzeń wierzchołkowa lokalna a przestrzeń świata -Jeśli ustawienia Przestrzeni wierzchołka (Vertex Space setting) materiału Siatki są ustawione na Przestrzeń lokalną (vertex local space), dane zostaną dostarczone do shadera w postaci, w jakiej są, i będziesz musiał przekształcać wierzchołki/normalne na GPU, tak jak zwykle. +## Lokalna przestrzeń wierzchołków a przestrzeń świata -Jeśli ustawienia Przestrzeni wierzchołka materiału meshu są ustawione na Przestrzeń świata (world space), musisz albo dostarczyć domyślny strumień "position" i "normal", albo wybrać go z listy rozwijanej podczas edycji Siatki. Ma to na celu przekształcenie danych do przestrzeni świata w celu ich grupowania z innymi obiektami. +Jeśli ustawienie *Vertex Space* materiału siatki ma wartość *Local Space*, dane zostaną przekazane do shadera bez zmian i musisz samodzielnie przekształcać wierzchołki oraz normalne na GPU, tak jak zwykle. + +Jeśli ustawienie *Vertex Space* materiału siatki ma wartość *World Space*, musisz albo dostarczyć domyślny strumień `position` i `normal`, albo wybrać go z listy rozwijanej podczas edycji siatki. Dzięki temu silnik może przekształcić dane do przestrzeni świata i batchować je razem z innymi obiektami. diff --git a/docs/pl/manuals/physics-joints.md b/docs/pl/manuals/physics-joints.md index a5e81f46..ab1c5804 100644 --- a/docs/pl/manuals/physics-joints.md +++ b/docs/pl/manuals/physics-joints.md @@ -1,55 +1,57 @@ --- -title: Łączenia fizyczne w Defoldzie -brief: Defold supports joints for 2D physics. This manual explains how to create and work with joints. +title: Łączenia fizyczne w Defold +brief: Defold obsługuje łączenia dla fizyki 2D. Ta instrukcja wyjaśnia, jak je tworzyć i jak z nimi pracować. --- -# Łączenia fizyczne (Joints) +# Łączenia -Defold obsługuje łączenia (ang. joints) w fizyce 2D. Łączenie łączy ze sobą dwa obiekty kolizji za pomocą wybranego rodzaju ograniczenia. Obsługiwane rodzaje połączeń to: +Defold obsługuje łączenia w fizyce 2D. Łączenie łączy dwa obiekty kolizji za pomocą określonego ograniczenia. Obsługiwane typy łączeń to: -* **Fixed (physics.JOINT_TYPE_FIXED)** - łączenie stałe, które ogranicza maksymalną odległość między dwoma punktami. W Box2D jest to znane jako połączenie "lina" (ang. rope joint). -* **Hinge (physics.JOINT_TYPE_HINGE)** - łączenie zawiasowe/osi określa punkt kotwiczenia na dwóch obiektach kolizji i przesuwa je tak, aby obiekty były zawsze w tym samym miejscu, a względna rotacja obiektów kolizyjnych nie była ograniczona. Łączenie zawiasowe można łączyć ze specjalnym silnikiem (ang. motor) zdefiniowanym z maksymalnym momentem obrotowym i prędkością, co umożliwia przykładowo stworzenie koła pojazdu. W Box2D jest to znane jako połączenie obrotowe (ang. revolute joint). -* **Weld (physics.JOINT_TYPE_WELD)** - łączenie spawane stara się ograniczyć wszelkie względne ruchy między dwoma obiektami kolizyji. Łączenie spawane można zrobić miękkie jak sprężyna z częstotliwością i współczynnikiem tłumienia. W Box2D jest to znane również jako połączenie spawane (ang. weld joint). -* **Spring (physics.JOINT_TYPE_SPRING)** - łączenie sprężynowe utrzymuje dwa obiekty kolizyjne w stałej odległości od siebie. Połączenie sprężyny można zrobić miękkie jak sprężyna z częstotliwością i współczynnikiem tłumienia. W Box2D jest znane jako połączenie dystansowe (ang. distance joint). -* **Slider (physics.JOINT_TYPE_SLIDER)** - łączenie przesuwne/suwaka umożliwia względną translację dwóch obiektów kolizji wzdłuż określonej osi i zapobiega względnej rotacji. W Box2D jest znane jako połączenie pryzmatyczne (ang. prismatic joint). +* **Fixed (physics.JOINT_TYPE_FIXED)** - Łączenie linowe ograniczające maksymalną odległość między dwoma punktami. W Box2D nazywa się Rope joint. +* **Hinge (physics.JOINT_TYPE_HINGE)** - Łączenie zawiasowe określa punkt zakotwiczenia na dwóch obiektach kolizji i przesuwa je tak, aby oba obiekty zawsze znajdowały się w tym samym miejscu, przy czym ich względny obrót nie jest ograniczony. Łączenie zawiasowe może włączyć motor o określonym maksymalnym momencie obrotowym i prędkości. W Box2D odpowiada [Revolute joint](https://box2d.org/documentation/group__revolute__joint.html#details). +* **Weld (physics.JOINT_TYPE_WELD)** - Łączenie spawane próbuje ograniczyć cały względny ruch między dwoma obiektami kolizji. Może być zmiękczone jak sprężyna dzięki częstotliwości i współczynnikowi tłumienia. W Box2D odpowiada [Weld joint](https://box2d.org/documentation/group__weld__joint.html#details). +* **Spring (physics.JOINT_TYPE_SPRING)** - Łączenie sprężynowe utrzymuje dwa obiekty kolizji w stałej odległości od siebie. Także może być zmiękczone jak sprężyna dzięki częstotliwości i współczynnikowi tłumienia. W Box2D odpowiada [Distance joint](https://box2d.org/documentation/group__distance__joint.html#details). +* **Slider (physics.JOINT_TYPE_SLIDER)** - Łączenie przesuwne pozwala na względne przesunięcie dwóch obiektów kolizji wzdłuż wskazanej osi i zapobiega ich względnemu obrotowi. W Box2D odpowiada [Prismatic joint](https://box2d.org/documentation/group__prismatic__joint.html#details). +* **Wheel (physics.JOINT_TYPE_WHEEL)** - Łączenie koła ogranicza punkt na `bodyB` do linii na `bodyA`. Zapewnia też sprężynę zawieszenia. W Box2D odpowiada [Wheel joint](https://box2d.org/documentation/group__wheel__joint.html#details). -## Tworzenie połączeń +## Tworzenie łączeń -Obecnie połączenia można tworzyć tylko programowo za pomocą funkcji [`physics.create_joint()`](/ref/physics/#physics.create_joint:joint_type-collisionobject_a-joint_id-position_a-collisionobject_b-position_b-[properties]): +Łączenia można obecnie tworzyć tylko programowo za pomocą [`physics.create_joint()`](/ref/physics/#physics.create_joint:joint_type-collisionobject_a-joint_id-position_a-collisionobject_b-position_b-[properties]): ::: sidenote -Wsparcie Edytora do tworzenia połączeń jest planowane, ale nie ustalono jeszcze daty wydania. +Obsługa tworzenia łączeń w edytorze jest planowana, ale nie ustalono jeszcze daty wydania. ::: ```lua --- połącz dwa obiekty kolizyjne za pomocą połączenia liny (fixed joint) +-- połącz dwa obiekty kolizji za pomocą stałego ograniczenia łączenia (rope) physics.create_joint(physics.JOINT_TYPE_FIXED, "obj_a#collisionobject", "my_test_joint", vmath.vector3(10, 0, 0), "obj_b#collisionobject", vmath.vector3(0, 20, 0), { max_length = 20 }) ``` -Powyższy kod utworzy stałe połączenie o identyfikatorze `my_test_joint`, połączone między dwoma obiektami kolizyjnymi `obj_a#collisionobject` i `obj_b#collisionobject`. Połączenie jest ustanowione 10 pikseli na lewo od środka obiektu kolizyjnego `obj_a#collisionobject` i 20 pikseli nad środkiem obiektu kolizyjnego `obj_b#collisionobject`. Maksymalna długość połączenia wynosi 20 pikseli. +Powyższy przykład tworzy łączenie typu Fixed o id `my_test_joint` pomiędzy obiektami kolizji `obj_a#collisionobject` i `obj_b#collisionobject`. Łączenie jest umieszczone 10 pikseli na lewo od środka `obj_a#collisionobject` i 20 pikseli nad środkiem `obj_b#collisionobject`. Maksymalna długość łączenia wynosi 20 pikseli. -## Niszczenie połączeń +## Niszczenie łączeń -Połączenie można zniszczyć za pomocą funkcji [`physics.destroy_joint()`](/ref/physics/#physics.destroy_joint:collisionobject-joint_id): +Łączenie można zniszczyć za pomocą [`physics.destroy_joint()`](/ref/physics/#physics.destroy_joint:collisionobject-joint_id): ```lua --- zniszcz połączenie, które było wcześniej podłączone do pierwszego obiektu kolizyjnego +-- zniszcz łączenie wcześniej podłączone do pierwszego obiektu kolizji physics.destroy_joint("obj_a#collisionobject", "my_test_joint") ``` -## Odczytywanie i aktualizowanie połączeń +## Odczyt i aktualizacja łączeń -Właściwości połączenia można odczytać za pomocą funkcji [`physics.get_joint_properties()`](/ref/physics/#physics.get_joint_properties:collisionobject-joint_id) i ustawić za pomocą funkcji [`physics.set_joint_properties()`](/ref/physics/#physics.set_joint_properties:collisionobject-joint_id-properties): +Właściwości łączenia można odczytać przez [`physics.get_joint_properties()`](/ref/physics/#physics.get_joint_properties:collisionobject-joint_id), a ustawić przez [`physics.set_joint_properties()`](/ref/physics/#physics.set_joint_properties:collisionobject-joint_id-properties): ```lua function update(self, dt) if self.accelerating then local hinge_props = physics.get_joint_properties("obj_a#collisionobject", "my_hinge") - -- zwiększ prędkość silnika o 100 obrotów na sekundę + -- zwiększ prędkość motoru o 100 obrotów na sekundę hinge_props.motor_speed = hinge_props.motor_speed + 100 * 2 * math.pi * dt physics.set_joint_properties("obj_a#collisionobject", "my_hinge", hinge_props) end end ``` -## Odczytywanie siły i momentu reakcji połączenia -Siłę reakcji i moment reakcji, które zostały zastosowane do połączenia, można odczytać za pomocą funkcji odpowiednio [`physics.get_joint_reaction_force()`](/ref/physics/#physics.get_joint_reaction_force:collisionobject-joint_id) i [`physics.get_joint_reaction_torque()`](/ref/physics/#physics.get_joint_reaction_torque:collisionobject-joint_id). +## Odczyt siły i momentu reakcji łączenia + +Siłę reakcji i moment reakcji działające na łączenie można odczytać funkcjami [`physics.get_joint_reaction_force()`](/ref/physics/#physics.get_joint_reaction_force:collisionobject-joint_id) oraz [`physics.get_joint_reaction_torque()`](/ref/physics/#physics.get_joint_reaction_torque:collisionobject-joint_id). diff --git a/docs/pl/manuals/property-animation.md b/docs/pl/manuals/property-animation.md index 3978923a..8a29d886 100644 --- a/docs/pl/manuals/property-animation.md +++ b/docs/pl/manuals/property-animation.md @@ -1,109 +1,109 @@ --- title: Animacja właściwości -brief: Ta instrukcja opisuje wsparcie dla animacji właściwości w silniku Defold. +brief: Ta instrukcja opisuje, jak używać animacji właściwości w silniku Defold. --- # Animacja właściwości -Wszystkie właściwości (ang. properties) będące zmiennymi numerycznymi (typy Lua: numbers, vector3, vector4 i quaterions (kwaterniony)) oraz stałe shaderów mogą być animowane w Defoldzie wykorzystując wbudowany system animacji, używając funkcji `go.animate()`. Silnik będzie automatycznie dopasowywał wartość (ang. tween) uwzględniając wybrany tryb odtwarzania (playback mode) i funkcję wygładzania (easing function). Można również definiować własne funkcje wygładzania. +Wszystkie właściwości liczbowe, czyli `number`, `vector3`, `vector4` i kwaterniony, a także stałe shaderów, można animować za pomocą wbudowanego systemu animacji i funkcji `go.animate()`. Silnik automatycznie interpoluje wartości zgodnie z wybranym trybem odtwarzania i funkcją easing. Możesz też definiować własne funkcje easing. ![Property animation](images/animation/property_animation.png) ![Bounce loop](images/animation/bounce.gif) -## Animowanie właściwości +## Animacja właściwości -Aby animować właściwości (ang. properties) obiektu lub komponentu użyj funkcji `go.animate()`. Dla właściwości węzłów GUI, analogiczną funkcją jest `gui.animate()`. +Aby animować właściwość obiektu gry albo komponentu, użyj `go.animate()`. W przypadku właściwości węzłów GUI odpowiednikiem jest `gui.animate()`. ```lua --- Ustaw pozycję w osi Y - właściwość komponentu na 200 +-- Ustaw składową y właściwości position na 200 go.set(".", "position.y", 200) --- Następnie przeprowadź animację właściwości do 100 i z powrotem +-- Następnie ją animuj go.animate(".", "position.y", go.PLAYBACK_LOOP_PINGPONG, 100, go.EASING_OUTBOUNCE, 2) ``` -Aby zatrzymać wszystkie animacje danej właściwości, wywołaj `go.cancel_animations()`, a dla węzłów GUI, analogicznie: `gui.cancel_animation()` lub dookreśl, które właściwości chcesz zatrzymać: +Aby zatrzymać wszystkie animacje danej właściwości, wywołaj `go.cancel_animations()`, a dla węzłów GUI `gui.cancel_animation()`: ```lua --- Zatrzymaj rotację eulera na osi Z obecnego obiektu gry +-- Zatrzymaj animację obrotu euler.z bieżącego obiektu gry go.cancel_animations(".", "euler.z") ``` -Jeśli zatrzymasz animacje właściwości, która jest właściwością "kompozytową" (składającą się z kilku osobnych wartości, jak np. `vector3 position`), osobne animacje każdego z elementów składowych danej właściwości (`position.x`, `position.y` i `position.z`) zostaną zatrzymane. +Jeśli anulujesz animację właściwości złożonej, takiej jak `position`, anulowane zostaną również animacje jej składowych, czyli `position.x`, `position.y` i `position.z`. -[Instrukcja do właściwości](/manuals/properties) zawiera wszystkie informacje na temat dostępnych właściwości obiektów, komponentów i węzłów GUI. +[Instrukcja o właściwościach](/manuals/properties) zawiera listę wszystkich dostępnych właściwości obiektów gry, komponentów i węzłów GUI. -## Animowanie właściwości węzłów GUI +## Animacja właściwości węzłów GUI -Prawie każdą właściwość węzła GUI można animować. Możesz, przykładowo, ukryć węzeł poprzez ustawienie jego koloru (`color`) na całkowicie przezroczysty, a następnie pokazać go przez płynne pojawianie się animując kolor do wartości koloru białego (nieprzezroczystego): +Prawie wszystkie właściwości węzłów GUI można animować. Możesz na przykład ukryć węzeł, ustawiając jego właściwość `color` na pełną przezroczystość, a następnie płynnie go wyświetlić, animując kolor do bieli, czyli bez dodatkowego zabarwienia. ```lua local node = gui.get_node("button") local color = gui.get_color(node) --- Animuj kolor do białego +-- Animuj kolor do bieli gui.animate(node, gui.PROP_COLOR, vmath.vector4(1, 1, 1, 1), gui.EASING_INOUTQUAD, 0.5) --- Animuj kolor obrzeży do czerwonego +-- Animuj czerwony składnik koloru obramowania gui.animate(node, "outline.x", 1, gui.EASING_INOUTQUAD, 0.5) --- I animuj pozycję wzdłuż osi X do 100 +-- I przesuń do pozycji x równej 100 gui.animate(node, hash("position.x"), 100, gui.EASING_INOUTQUAD, 0.5) ``` -## Funkcje po zakończeniu animacji +## Callbacki zakończenia -Funkcje do animacji właściwości `go.animate()` i `gui.animate()` wspierają opcjonalną funkcję tzw. callback jako ostatni argument. Funkcja ta zostanie wywołana po zakończeniu animacji. Funkcja nigdy nie jest wywoływana dla animacji w pętli, więc takich, których tryby odtwarzania zaczynają się od: `PLAYBACK_LOOP_*`, ani w przypadku ręcznego anulowania animacji za pomocą `go.cancel_animations()`. Funkcję zwrotną można wykorzystać do wyzwalania zdarzeń po zakończeniu animacji lub do połączenia różnych animacji w serie, jedna za drugą. +Funkcje animacji właściwości `go.animate()` i `gui.animate()` obsługują opcjonalną funkcję callback jako ostatni argument. Zostanie ona wywołana po zakończeniu animacji. Callback nigdy nie jest wywoływany dla animacji zapętlonych ani wtedy, gdy animacja została ręcznie anulowana przez `go.cancel_animations()` lub `gui.cancel_animation()`. Można go używać do wyzwalania zdarzeń po zakończeniu animacji albo do łączenia kilku animacji w sekwencję. -## Wygładzanie +## Easing -Wygładzanie (ang. easing) określa w jaki sposób animowana będzie wartość w czasie. Poniżej zaprezentowano wykresy funkcji wygładzania przedstawiające wartość w czasie. +Easing określa, jak animowana wartość zmienia się w czasie. Poniższe obrazy pokazują funkcje używane do tworzenia poszczególnych krzywych easing. -Tutaj przedstawione są funkcje wygładzania dostępne dla funkcji `go.animate()`: +Poniżej znajdują się poprawne wartości easing dla `go.animate()`: |---|---| -| go.EASING_LINEAR | | -| go.EASING_INBACK | go.EASING_OUTBACK | -| go.EASING_INOUTBACK | go.EASING_OUTINBACK | -| go.EASING_INBOUNCE | go.EASING_OUTBOUNCE | -| go.EASING_INOUTBOUNCE | go.EASING_OUTINBOUNCE | -| go.EASING_INELASTIC | go.EASING_OUTELASTIC | -| go.EASING_INOUTELASTIC | go.EASING_OUTINELASTIC | -| go.EASING_INSINE | go.EASING_OUTSINE | -| go.EASING_INOUTSINE | go.EASING_OUTINSINE | -| go.EASING_INEXPO | go.EASING_OUTEXPO | -| go.EASING_INOUTEXPO | go.EASING_OUTINEXPO | -| go.EASING_INCIRC | go.EASING_OUTCIRC | -| go.EASING_INOUTCIRC | go.EASING_OUTINCIRC | -| go.EASING_INQUAD | go.EASING_OUTQUAD | -| go.EASING_INOUTQUAD | go.EASING_OUTINQUAD | -| go.EASING_INCUBIC | go.EASING_OUTCUBIC | -| go.EASING_INOUTCUBIC | go.EASING_OUTINCUBIC | -| go.EASING_INQUART | go.EASING_OUTQUART | -| go.EASING_INOUTQUART | go.EASING_OUTINQUART | -| go.EASING_INQUINT | go.EASING_OUTQUINT | -| go.EASING_INOUTQUINT | go.EASING_OUTINQUINT | - -Tutaj przedstawione są funkcje wygładzania dostępne dla funkcji `gui.animate()`: +| `go.EASING_LINEAR` | | +| `go.EASING_INBACK` | `go.EASING_OUTBACK` | +| `go.EASING_INOUTBACK` | `go.EASING_OUTINBACK` | +| `go.EASING_INBOUNCE` | `go.EASING_OUTBOUNCE` | +| `go.EASING_INOUTBOUNCE` | `go.EASING_OUTINBOUNCE` | +| `go.EASING_INELASTIC` | `go.EASING_OUTELASTIC` | +| `go.EASING_INOUTELASTIC` | `go.EASING_OUTINELASTIC` | +| `go.EASING_INSINE` | `go.EASING_OUTSINE` | +| `go.EASING_INOUTSINE` | `go.EASING_OUTINSINE` | +| `go.EASING_INEXPO` | `go.EASING_OUTEXPO` | +| `go.EASING_INOUTEXPO` | `go.EASING_OUTINEXPO` | +| `go.EASING_INCIRC` | `go.EASING_OUTCIRC` | +| `go.EASING_INOUTCIRC` | `go.EASING_OUTINCIRC` | +| `go.EASING_INQUAD` | `go.EASING_OUTQUAD` | +| `go.EASING_INOUTQUAD` | `go.EASING_OUTINQUAD` | +| `go.EASING_INCUBIC` | `go.EASING_OUTCUBIC` | +| `go.EASING_INOUTCUBIC` | `go.EASING_OUTINCUBIC` | +| `go.EASING_INQUART` | `go.EASING_OUTQUART` | +| `go.EASING_INOUTQUART` | `go.EASING_OUTINQUART` | +| `go.EASING_INQUINT` | `go.EASING_OUTQUINT` | +| `go.EASING_INOUTQUINT` | `go.EASING_OUTINQUINT` | + +Poniżej znajdują się poprawne wartości easing dla `gui.animate()`: |---|---| -| gui.EASING_LINEAR | | -| gui.EASING_INBACK | gui.EASING_OUTBACK | -| gui.EASING_INOUTBACK | gui.EASING_OUTINBACK | -| gui.EASING_INBOUNCE | gui.EASING_OUTBOUNCE | -| gui.EASING_INOUTBOUNCE | gui.EASING_OUTINBOUNCE | -| gui.EASING_INELASTIC | gui.EASING_OUTELASTIC | -| gui.EASING_INOUTELASTIC | gui.EASING_OUTINELASTIC | -| gui.EASING_INSINE | gui.EASING_OUTSINE | -| gui.EASING_INOUTSINE | gui.EASING_OUTINSINE | -| gui.EASING_INEXPO | gui.EASING_OUTEXPO | -| gui.EASING_INOUTEXPO | gui.EASING_OUTINEXPO | -| gui.EASING_INCIRC | gui.EASING_OUTCIRC | -| gui.EASING_INOUTCIRC | gui.EASING_OUTINCIRC | -| gui.EASING_INQUAD | gui.EASING_OUTQUAD | -| gui.EASING_INOUTQUAD | gui.EASING_OUTINQUAD | -| gui.EASING_INCUBIC | gui.EASING_OUTCUBIC | -| gui.EASING_INOUTCUBIC | gui.EASING_OUTINCUBIC | -| gui.EASING_INQUART | gui.EASING_OUTQUART | -| gui.EASING_INOUTQUART | gui.EASING_OUTINQUART | -| gui.EASING_INQUINT | gui.EASING_OUTQUINT | -| gui.EASING_INOUTQUINT | gui.EASING_OUTINQUINT | +| `gui.EASING_LINEAR` | | +| `gui.EASING_INBACK` | `gui.EASING_OUTBACK` | +| `gui.EASING_INOUTBACK` | `gui.EASING_OUTINBACK` | +| `gui.EASING_INBOUNCE` | `gui.EASING_OUTBOUNCE` | +| `gui.EASING_INOUTBOUNCE` | `gui.EASING_OUTINBOUNCE` | +| `gui.EASING_INELASTIC` | `gui.EASING_OUTELASTIC` | +| `gui.EASING_INOUTELASTIC` | `gui.EASING_OUTINELASTIC` | +| `gui.EASING_INSINE` | `gui.EASING_OUTSINE` | +| `gui.EASING_INOUTSINE` | `gui.EASING_OUTINSINE` | +| `gui.EASING_INEXPO` | `gui.EASING_OUTEXPO` | +| `gui.EASING_INOUTEXPO` | `gui.EASING_OUTINEXPO` | +| `gui.EASING_INCIRC` | `gui.EASING_OUTCIRC` | +| `gui.EASING_INOUTCIRC` | `gui.EASING_OUTINCIRC` | +| `gui.EASING_INQUAD` | `gui.EASING_OUTQUAD` | +| `gui.EASING_INOUTQUAD` | `gui.EASING_OUTINQUAD` | +| `gui.EASING_INCUBIC` | `gui.EASING_OUTCUBIC` | +| `gui.EASING_INOUTCUBIC` | `gui.EASING_OUTINCUBIC` | +| `gui.EASING_INQUART` | `gui.EASING_OUTQUART` | +| `gui.EASING_INOUTQUART` | `gui.EASING_OUTINQUART` | +| `gui.EASING_INQUINT` | `gui.EASING_OUTQUINT` | +| `gui.EASING_INOUTQUINT` | `gui.EASING_OUTINQUINT` | ![Linear interpolation](images/properties/easing_linear.png) ![In back](images/properties/easing_inback.png) @@ -147,22 +147,22 @@ Tutaj przedstawione są funkcje wygładzania dostępne dla funkcji `gui.animate( ![In-out quintic](images/properties/easing_inoutquint.png) ![Out-in quintic](images/properties/easing_outinquint.png) -## Własne funkcje wygładzania +## Własne funkcje easing -Możesz tworzyć własne funkcje wygładzania zdefiniowane jako specjalny `vector` ze zbiorem odpowiednich, kolejnych wartości i użyć go zamiast predefiniowanych stałych przedstawionych powyżej. Wektor ten reprezentuje krzywą zmiany wartości numerycznej od wartości startowej (`0`) do wartości końcowej (`1`). Silnik interpoluje w czasie działania programu te wartości liniowo. +Możesz tworzyć własne krzywe easing, definiując `vector` z zestawem wartości i przekazując go zamiast jednej z predefiniowanych stałych easing opisanych wyżej. Wartości wektora opisują krzywą od wartości początkowej (`0`) do wartości docelowej (`1`). W czasie działania silnik próbuje próbki z wektora i liniowo interpoluje wartości pomiędzy punktami opisanymi w tym wektorze. -For example, the vector: +Na przykład taki wektor: ```lua local values = { 0, 0.4, 0.2, 0.2, 0.5, 1 } local my_easing = vmath.vector(values) ``` -stworzy następującą krzywą: +da następującą krzywą: ![Custom curve](images/animation/custom_curve.png) -W poniższym przykładzie wartość y pozycji obiektu skacze między aktualną pozycją startową, a pozycją docelową 200: +W kolejnym przykładzie pozycja `y` obiektu gry będzie przeskakiwać między bieżącą pozycją a wartością `200` zgodnie z przebiegiem przypominającym falę prostokątną: ```lua local values = { 0, 0, 0, 0, 0, 0, 0, 0, diff --git a/docs/pl/manuals/resource.md b/docs/pl/manuals/resource.md index 77863c8c..2804221e 100644 --- a/docs/pl/manuals/resource.md +++ b/docs/pl/manuals/resource.md @@ -1,63 +1,67 @@ --- -title: Zarządzanie zasobami w Defoldzie -brief: Ta instrukcja wyjaśnia jak Defold automatycznie zarządza zasobami i jak można rędzie to robić. +title: Zarządzanie zasobami w Defold +brief: Ta instrukcja wyjaśnia, jak Defold automatycznie zarządza zasobami i jak ręcznie sterować ich ładowaniem, by pilnować zużycia pamięci oraz rozmiaru bundla. --- # Zarządzanie zasobami -Jeśli tworzysz bardzo małą grę, ograniczenia platformy docelowej (rozmiar pamięci, rozmiar paczki, moc obliczeniowa i zużycie baterii) mogą nigdy nie stanowić problemu. Jednak tworząc większe gry, zwłaszcza na urządzeniach przenośnych czy na przeglądarki, zużycie pamięci będzie prawdopodobnie jednym z największych ograniczeń. Doświadczony zespół będzie starannie zarządzać zasobami w oparciu o ograniczenia platformy. Defold dostarcza szereg funkcji do zarządzania pamięcią i rozmiarem paczki. Ta instrukcja pozwala się z nimi zapoznać. +Jeśli tworzysz bardzo małą grę, ograniczenia platformy docelowej, takie jak zużycie pamięci, rozmiar bundla, moc obliczeniowa czy pobór energii, mogą w ogóle nie stanowić problemu. Jednak przy większych grach, szczególnie na urządzeniach mobilnych, zużycie pamięci bywa jednym z najważniejszych ograniczeń. Doświadczony zespół przygotowuje budżety zasobów z uwzględnieniem ograniczeń platformy. Defold udostępnia zestaw funkcji pomagających zarządzać pamięcią i rozmiarem bundla. Ta instrukcja daje ich przegląd. ## Statyczne drzewo zasobów -Podczas tworzenia gry w Defoldzie deklarujesz statycznie drzewo zasobów. Każda część gry jest łączona z drzewem, począwszy od kolekcji rozruchowej (ang. bootrstrap collection), zwykle nazywanej "main.collection". Drzewo zasobów podąża za każdym odniesieniem i zawiera wszystkie zasoby powiązane z tymi odniesieniami: +Podczas budowania gry w Defold statycznie deklarujesz drzewo zasobów. Każdy element gry jest włączony do tego drzewa, począwszy od kolekcji bootstrapowej, zwykle o nazwie `main.collection`. Drzewo zasobów podąża za wszystkimi odwołaniami i zawiera wszystkie zasoby z nimi powiązane: -- Dane obiektów gry (game objects) i komponentów (atlasy, dźwięki itp). -- Prototypy komponentów fabryki (obiekty gry i kolekcje). -- Odniesienia komponentów pełnomocników kolekcji (kolekcje). -- Niestandardowe zasoby deklarowane w *game.project*. +- dane obiektów gry i komponentów, takie jak atlasy czy dźwięki +- prototypy komponentów Factory, czyli obiekty gry i kolekcje +- odwołania komponentów pełnomocników kolekcji +- [Custom Resources](/manuals/project-settings/#custom-resources) zadeklarowane w *game.project* -![Drzewo zasobów](images/resource/resource_tree.png) +![Resource tree](images/resource/resource_tree.png) -Podczas tworzenia i pakowania gry, tylko to, co znajduje się w drzewie zasobów, zostanie uwzględnione w paczce. To, czego nie ma w drzewie, jest pomijane. Nie ma potrzeby ręcznego wybierania, co ma być uwzględnione lub wyłączone z paczki. +::: sidenote +Defold ma też pojęcie [bundle resources](/manuals/project-settings/#bundle-resources). Są one dołączane do bundla aplikacji, ale nie należą do drzewa zasobów. Mogą to być zarówno pliki pomocnicze specyficzne dla platformy, jak i zewnętrzne pliki [wczytywane z systemu plików](/manuals/file-access/#how-to-access-files-bundled-with-the-application) i używane przez grę, na przykład banki dźwięków FMOD. +::: -Podczas *uruchamiania* gry, silnik rozpoczyna działanie od korzenia drzewa rozruchowego (ang. bootstrap root) i ściąga zasoby do pamięci: +Podczas *bundlowania* do gry zostanie dołączone tylko to, co znajduje się w drzewie zasobów. Wszystko, do czego nie prowadzi żadne odwołanie w drzewie, zostanie pominięte. Nie trzeba ręcznie wybierać, co uwzględnić lub wykluczyć. -- Każda kolekcja, do której odniesienie istnieje, wraz z jej zawartością. -- Obiekty gry i dane komponentów. -- Prototypy komponentów fabryki (obiekty gry i kolekcje). +Podczas *uruchamiania* gry silnik startuje od bootstrapowego korzenia drzewa i ładuje zasoby do pamięci: -Defold nie ładuje jednak automatycznie następujących rodzajów odniesionych zasobów podczas działania: +- wszystkie wskazane kolekcje wraz z ich zawartością +- obiekty gry i dane komponentów +- prototypy komponentów Factory -- Kolekcji świata gry, do której odniesienie istnieje przez proxy kolekcji. Światy gry są stosunkowo duże, więc będziesz musiał ręcznie uruchamiać i wyłączać ich ładowanie w kodzie. Zobacz [instrukcję do pełnomocników kolekcji](/manuals/collection-proxy), aby poznać szczegóły. -- Pliki dodane za pomocą ustawienia *Custom Resources* (Niestandardowe zasoby) w *game.project*. Te pliki są ręcznie ładowane za pomocą funkcji [sys.load_resource()](/ref/sys/#sys.load_resource). +Silnik nie ładuje jednak automatycznie następujących typów zasobów wskazanych w drzewie: -Domyślny sposób, w jaki Defold pakuje i ładuje zasoby, można zmienić, aby uzyskać kontrolę nad tym, jak i kiedy zasoby wchodzą do pamięci. +- kolekcji światów gry wskazywanych przez pełnomocników kolekcji; światy gry są relatywnie duże, więc ich ładowanie i zwalnianie trzeba wyzwalać ręcznie w kodzie; szczegóły znajdziesz w [instrukcji Collection proxy](/manuals/collection-proxy) +- plików dodanych przez ustawienie *Custom Resources* w *game.project*; te pliki wczytuje się ręcznie funkcją [`sys.load_resource()`](/ref/sys/#sys.load_resource) -![Wczytywanie zasobów](images/resource/loading.png) +Domyślny sposób bundlowania i ładowania zasobów w Defold można zmieniać, aby precyzyjnie sterować tym, kiedy i jak zasoby trafiają do pamięci. -## Dynamiczne ładowanie zasobów fabryki +![Resource loading](images/resource/loading.png) -Zasoby odniesione przez komponenty fabryki (ang. factory components) są zazwyczaj ładowane do pamięci, w momencie, gdy komponent jest ładowany. Zasoby są gotowe do użycia w grze, zanim fabryka zostanie utworzona w czasie działania. Aby zmienić domyślne zachowanie i opóźnić ładowanie zasobów fabryki, można po prostu zaznaczyć w właściwościach fabryki opcję *Load Dynamically* (Ładuj dynamicznie). +## Dynamiczne ładowanie zasobów Factory -![Opcja Ładuj dynamicznie](images/resource/load_dynamically.png) +Zasoby wskazywane przez komponenty Factory są zwykle ładowane do pamięci razem z samym komponentem. Dzięki temu są gotowe do użycia od razu, gdy Factory istnieje w czasie działania. Aby zmienić to zachowanie i odroczyć ładowanie zasobów Factory, zaznacz pole *Load Dynamically*. -Zaznaczenie tej opcji spowoduje, że silnik wciąż zawierać będzie odniesione zasoby w paczce gry, ale nie załaduje ich automatycznie. Zamiast tego masz dwie opcje: +![Load dynamically](images/resource/load_dynamically.png) -1. Wywołać funckję [`factory.create()`](/ref/factory/#factory.create) lub [`collectionfactory.create()`](/ref/collectionfactory/#collectionfactory.create), gdy chcesz tworzyć obiekty. To spowoduje synchroniczne ładowanie zasobów, a następnie tworzenie nowych instancji. -2. Wywołać funckję [`factory.load()`](/ref/factory/#factory.load) lub [`collectionfactory.load()`](/ref/collectionfactory/#collectionfactory.load), aby asynchronicznie ładować zasoby. Gdy zasoby będą gotowe do tworzenia, zostanie odebrane odpowiednie wywołanie zwrotne (callback). +Po zaznaczeniu tego pola silnik nadal dołączy wskazane zasoby do bundla gry, ale nie załaduje ich automatycznie. Zamiast tego masz dwie możliwości: -Zobacz [instrukcję do fabryk](/manuals/factory) i [instrukcję do fabryk kolekcji](/manuals/collection-factory) po szczegóły dotyczące działania tych opcji. +1. Wywołaj [`factory.create()`](/ref/factory/#factory.create) albo [`collectionfactory.create()`](/ref/collectionfactory/#collectionfactory.create), gdy chcesz tworzyć obiekty. Spowoduje to synchroniczne załadowanie zasobów, a następnie utworzenie nowych instancji. +2. Wywołaj [`factory.load()`](/ref/factory/#factory.load) albo [`collectionfactory.load()`](/ref/collectionfactory/#collectionfactory.load), aby załadować zasoby asynchronicznie. Gdy będą gotowe do tworzenia instancji, otrzymasz callback. -## Dynamiczne zwalnianie ładowanych zasobów +Szczegóły działania znajdziesz w [instrukcji Factory](/manuals/factory) i [instrukcji Collection factory](/manuals/collection-factory). -Defold zachowuje liczniki odniesień dla wszystkich zasobów. Jeśli licznik odniesienia zasobu wynosi zero, oznacza to, że nie ma do niego już żadnego odniesienia. Zasób zostaje wtedy automatycznie usunięty z pamięci. Na przykład, jeśli usuniesz wszystkie obiekty utworzone przez fabrykę i dodatkowo usuniesz obiekt zawierający komponent fabryki, zasoby wcześniej odniesione przez fabrykę zostaną usunięte z pamięci. +## Zwalnianie dynamicznie wczytanych zasobów -Dla fabryk oznaczonych jako *Load Dynamically* można wywołać funkcję [`factory.unload()`](/ref/factory/#factory.unload) albo [`collectionfactory.unload()`](/ref/collectionfactory/#collectionfactory.unload). To wywołanie usuwa odniesienie komponentu fabryki do zasobu. Jeśli nic innego nie odnosi się do zasobu (np. wszystkie utworzone obiekty są usunięte), zasób zostanie zwolniony z pamięci. +Defold utrzymuje liczniki referencji dla wszystkich zasobów. Jeśli licznik zasobu spadnie do zera, oznacza to, że nic już się do niego nie odwołuje. Wtedy zasób jest automatycznie usuwany z pamięci. Przykładowo, jeśli usuniesz wszystkie obiekty utworzone przez Factory i dodatkowo usuniesz obiekt zawierający komponent Factory, zasoby wcześniej wskazywane przez tę fabrykę zostaną zwolnione. -## Wykluczanie zasobów z paczki +Dla fabryk oznaczonych jako *Load Dynamically* możesz wywołać [`factory.unload()`](/ref/factory/#factory.unload) albo [`collectionfactory.unload()`](/ref/collectionfactory/#collectionfactory.unload). To wywołanie usuwa referencję komponentu Factory do zasobu. Jeśli nic innego nie odwołuje się już do tego zasobu, na przykład wszystkie utworzone obiekty zostały usunięte, zasób zostanie zwolniony z pamięci. -Dzięki proxy (pełnomocnikom) kolekcji można pominąć wszystkie zasoby, do których odnosi się komponent, w procesie pakowania (bundling). Jest to przydatne, jeśli potrzebujesz zachować minimalny rozmiar paczki. Na przykład, podczas uruchamiania gier w sieci jako HTML5, przeglądarka pobierze całą paczkę przed uruchomieniem gry. +## Wykluczanie zasobów z bundla -![Wykluczanie zasobów z paczki](images/resource/exclude.png) +W przypadku pełnomocników kolekcji można pominąć w procesie bundlowania wszystkie zasoby, do których odwołuje się komponent. Jest to przydatne, jeśli chcesz zminimalizować rozmiar bundla. Na przykład przy uruchamianiu gry w przeglądarce jako HTML5 przeglądarka pobiera cały bundle przed rozpoczęciem wykonywania gry. -Zaznaczenie opcji pełnomocnika kolekcji nazwanej *Exclude* (Wyklucz) spowoduje, że odniesienie do zasobu zostanie pominięte w paczce gry. Zamiast tego można przechowywać wyłączone kolekcje w wybranym przechowywaniu w chmurze. W [instrukcji do aktualizacji na żywo - Live update](/manuals/live-update/) wyjaśniono, jak działa ta funkcja. +![Exclude](images/resource/exclude.png) + +Po oznaczeniu pełnomocnika kolekcji jako *Exclude* wskazany zasób nie trafi do bundla gry. Zamiast tego wykluczone kolekcje możesz przechowywać w wybranej chmurze. [Instrukcja Live update](/manuals/live-update/) wyjaśnia, jak działa ta funkcja. diff --git a/docs/pl/manuals/texture-profiles.md b/docs/pl/manuals/texture-profiles.md index 88dfbbb2..1ab5d2a9 100644 --- a/docs/pl/manuals/texture-profiles.md +++ b/docs/pl/manuals/texture-profiles.md @@ -1,211 +1,263 @@ --- -title: Profile tekstur w Defoldzie -brief: Defold wspiera automatyczne przetwarzanie tekstur i kompresję obrazów. Ta instrukcja opisuje te funckjonalności. +title: Profile tekstur w Defold +brief: Defold obsługuje automatyczne przetwarzanie tekstur i kompresję danych obrazów. Ta instrukcja opisuje dostępne funkcje. --- -# Profile tekstur w Defoldzie +# Profile tekstur -Defold obsługuje automatyczne przetwarzanie tekstur i kompresję danych obrazów (w Atlasie, Źródłach Kafelków (*Tile sources*), Mapach Kostkowych (*Cubemaps*) i samodzielnych teksturach używanych do modeli, GUI itp). +Defold obsługuje automatyczne przetwarzanie tekstur i kompresję danych obrazów w zasobach typu *Atlas*, *Tile source*, *Cubemap* oraz w samodzielnych teksturach używanych przez modele, GUI i inne elementy. -Istnieją dwa rodzaje kompresji: programowa i sprzętowa kompresja tekstur. +Istnieją dwa typy kompresji: programowa kompresja obrazów oraz sprzętowa kompresja tekstur. -1. Programowa kompresja tekstur (software texture compression) (takie jak PNG i JPEG) zmniejsza rozmiar pamięci zasobów obrazu. Powoduje to zmniejszenie ostatecznego rozmiaru paczki z grą. Jednak pliki obrazów muszą być rozpakowane podczas wczytywania do pamięci, więc nawet jeśli obraz jest mały na dysku, może zajmować dużo miejsca w pamięci. +1. Kompresja programowa, taka jak PNG i JPEG, zmniejsza rozmiar zasobów obrazów na dysku. Dzięki temu końcowy bundle jest mniejszy. Jednak pliki obrazów muszą zostać rozpakowane podczas wczytywania do pamięci, więc mimo niewielkiego rozmiaru na dysku mogą zajmować dużo pamięci RAM. -2. Sprzętowa kompresja tekstur (hardware texture compression) również zmniejsza rozmiar pamięci zasobów obrazu. Jednak w przeciwieństwie do kompresji programowej, zmniejsza rozmiar tekstur w pamięci. Dzieje się tak, ponieważ sprzęt graficzny może bezpośrednio zarządzać teksturami skompresowanymi, bez konieczności ich wcześniejszego dekompresowania. +2. Sprzętowa kompresja tekstur również zmniejsza rozmiar zasobów obrazów, ale w przeciwieństwie do kompresji programowej obniża także zużycie pamięci przez tekstury po załadowaniu. Dzieje się tak dlatego, że układ graficzny potrafi bezpośrednio pracować na skompresowanych teksturach, bez wcześniejszego rozpakowywania. -Przetwarzanie tekstur jest konfigurowane za pomocą konkretnego profilu tekstury (ang. texture profile). W tym pliku tworzysz _profile_, które wyrażają, jakie skompresowane formaty i jakiego typu powinny być używane przy tworzeniu paczki z grą dla określonej platformy. _Profile_ są przypisane do odpowiadających im wzorców plików - _paths patterns_, co pozwala na dokładną kontrolę nad tym, które pliki w twoim projekcie powinny być kompresowane i w jaki sposób dokładnie. +Przetwarzanie tekstur konfiguruje się za pomocą konkretnego profilu tekstur. W tym pliku tworzysz *profiles*, które określają, jakich skompresowanych formatów i jakiego typu kompresji należy użyć podczas tworzenia bundli dla konkretnej platformy. Następnie profile łączy się z pasującymi *path patterns*, co daje precyzyjną kontrolę nad tym, które pliki projektu mają zostać skompresowane i w jaki sposób. -Ponieważ każda dostępna sprzętowa kompresja tekstur jest stratna, otrzymasz tzw. artefakty w danych tekstury. Te artefakty są silnie zależne od tego, jak wygląda twój materiał źródłowy i jakie metody kompresji są używane. Powinieneś przetestować swój materiał źródłowy i eksperymentować, aby uzyskać najlepsze wyniki. Wujek Google może być twoim przyjacielem w tej kwestii. +Ponieważ wszystkie dostępne sprzętowe metody kompresji tekstur są stratne, w danych tekstury pojawią się artefakty. To, jak będą wyglądały, mocno zależy od materiału źródłowego i użytej metody kompresji. Warto testować własne zasoby i eksperymentować, aby uzyskać najlepszy rezultat. -Możesz wybrać, jakie kompresje obrazów oprogramowania są stosowane na ostatecznych danych tekstury (skompresowane lub nieskompresowane) w archiwum paczki (bundle archives). Defold obsługuje kompresję tekstury [Basis Universal](https://github.com/BinomialLLC/basis_universal), która kompresuje obraz w pośredni format. Ten format jest przekształcany w czasie rzeczywistym na format sprzętu odpowiedni dla GPU bieżącego urządzenia. Format Basis Universal jest formatem wysokiej jakości, ale stratnym. Wszystkie obrazy są również kompresowane za pomocą LZ4, aby jeszcze bardziej zmniejszyć rozmiar pliku, gdy są przechowywane w archiwum gry. +Możesz wybrać, jaka programowa kompresja obrazu zostanie zastosowana do końcowych danych tekstury w archiwach bundla, zarówno dla danych już skompresowanych, jak i surowych. Defold obsługuje formaty kompresji [Basis Universal](https://github.com/BinomialLLC/basis_universal) oraz [ASTC](https://www.khronos.org/opengl/wiki/ASTC_Texture_Compression). ::: sidenote -Kompresja jest operacją czasochłonną i wymagającą sporych zasobów, która może spowodować bardzo długie czasy kompilacji, w zależności od liczby obrazów do skompresowania oraz wybranych formatów tekstury i rodzaju wybranej programowej kompresji tekstur. +Kompresja jest operacją kosztowną obliczeniowo i czasowo. W zależności od liczby kompresowanych tekstur, wybranych formatów i rodzaju kompresji programowej może bardzo wydłużyć czas builda. ::: +### Basis Universal + +Basis Universal, w skrócie BasisU, kompresuje obraz do formatu pośredniego, który podczas działania jest transkodowany do sprzętowego formatu odpowiedniego dla GPU bieżącego urządzenia. Format Basis Universal zapewnia wysoką jakość, ale jest stratny. Wszystkie obrazy są dodatkowo kompresowane przy użyciu LZ4, aby jeszcze bardziej zmniejszyć rozmiar plików przechowywanych w archiwum gry. + +### ASTC + +ASTC to elastyczny i wydajny format kompresji tekstur opracowany przez ARM i ustandaryzowany przez Khronos Group. Oferuje szeroki zakres rozmiarów bloków i przepływności bitowej, dzięki czemu można skutecznie wyważyć jakość obrazu i zużycie pamięci. ASTC obsługuje rozmiary bloków od 4×4 do 12×12 texeli, co odpowiada przepływności od 8 bitów na texel do 0,89 bita na texel. Taka elastyczność pozwala bardzo precyzyjnie sterować kompromisem między jakością a wymaganiami pamięciowymi. + +Poniższa tabela pokazuje obsługiwane rozmiary bloków i odpowiadające im przepływności bitowe: + +| Rozmiar bloku (szerokość x wysokość) | Bity na piksel | +| ------------------------------------ | -------------- | +| 4x4 | 8.00 | +| 5x4 | 6.40 | +| 5x5 | 5.12 | +| 6x5 | 4.27 | +| 6x6 | 3.56 | +| 8x5 | 3.20 | +| 8x6 | 2.67 | +| 10x5 | 2.56 | +| 10x6 | 2.13 | +| 8x8 | 2.00 | +| 10x8 | 1.60 | +| 10x10 | 1.28 | +| 12x10 | 1.07 | +| 12x12 | 0.89 | + +#### Obsługiwane urządzenia + +Choć ASTC daje bardzo dobre rezultaty, nie jest wspierane przez wszystkie karty graficzne. Oto skrócona lista wsparcia według producenta GPU: + +| Producent GPU | Wsparcie | +| ------------------- | ------------------------------------------------------------------------ | +| ARM (Mali) | Wszystkie układy ARM Mali obsługujące OpenGL ES 3.2 lub Vulkan wspierają ASTC. | +| Qualcomm (Adreno) | Układy Adreno obsługujące OpenGL ES 3.2 lub Vulkan wspierają ASTC. | +| Apple | GPU Apple od układu A8 obsługują ASTC. | +| NVIDIA | Wsparcie ASTC dotyczy głównie mobilnych GPU, np. układów Tegra. | +| AMD (Radeon) | GPU AMD obsługujące Vulkan zwykle wspierają ASTC programowo. | +| Intel (Integrated) | Nowoczesne GPU Intela wspierają ASTC programowo. | + ## Profile tekstur -Każdy projekt zawiera określony plik *.texture_profiles*, który zawiera konfigurację używaną podczas kompresji tekstur. Domyślnie ten plik to *builtins/graphics/default.texture_profiles* i zawiera konfigurację dopasowującą każdy zasób tekstury do profilu przy użyciu RGBA bez sprzętowej kompresji tekstur i z domyślną kompresją plików ZLib. +Każdy projekt zawiera plik `*.texture_profiles`, który przechowuje konfigurację używaną podczas kompresji tekstur. Domyślnie jest to `builtins/graphics/default.texture_profiles`, a jego konfiguracja przypisuje każdy zasób tekstury do profilu używającego formatu RGBA, bez sprzętowej kompresji tekstur i z domyślną kompresją plików ZLib. Aby dodać kompresję tekstur: -- Wybierz File ▸ New..., a następnie *Texture Profiles* (Profile tekstur), aby utworzyć nowy plik profili tekstur. (Albo skopiuj *default.texture_profiles* poza folder *builtins* na wybrane miejsce) +- Wybierz File ▸ New... i utwórz nowy plik *Texture Profiles*. Alternatywnie skopiuj `default.texture_profiles` poza katalog `builtins`. - Wybierz nazwę i lokalizację nowego pliku. -- Zmień wpis *texture_profiles* w *game.project*, aby wskazywał na nowy plik. -- Otwórz plik *.texture_profiles* i skonfiguruj go zgodnie z własnymi wymaganiami. +- Zmień wpis `texture_profiles` w `game.project`, aby wskazywał na nowy plik. +- Otwórz plik `*.texture_profiles` i skonfiguruj go zgodnie z potrzebami projektu. -![Nowy plik profili tekstur](images/texture_profiles/texture_profiles_new_file.png) +![New profiles file](images/texture_profiles/texture_profiles_new_file.png) -![Ustawienia profilu tekstur](images/texture_profiles/texture_profiles_game_project.png) +![Setting the texture profile](images/texture_profiles/texture_profiles_game_project.png) -W preferencjach Edytora można włączyć i wyłączyć korzystanie z profili tekstur. Wybierz File ▸ Preferences.... Karta *General* zawiera opcję *Enable texture profiles* (Włącz profile tekstur). +Możesz włączać i wyłączać użycie profili tekstur w preferencjach edytora. Wybierz File ▸ Preferences.... W zakładce *General* znajduje się pole wyboru *Enable texture profiles*. -![Preferencje profili tekstur](images/texture_profiles/texture_profiles_preferences.png) +![Texture profiles preferences](images/texture_profiles/texture_profiles_preferences.png) -## Ustawienia ścieżki +## Ustawienia ścieżek -Sekcja *Path Settings* (Ustawienia ścieżki) w pliku profilów tekstur zawiera listę wzorców ścieżek i informacje, który *profil* ma być używany przy przetwarzaniu zasobów odpowiadających danej ścieżce. Ścieżki wyrażone są jako wzorce "Ant Glob" ([zobacz tutaj](http://ant.apache.org/manual/dirtasks.html#patterns) w celu uzyskania szczegółów). Wzorce można wyrazić przy użyciu następujących symboli wieloznacznych (wildcards): +Sekcja *Path Settings* w pliku profili tekstur zawiera listę wzorców ścieżek oraz informację, który *profile* należy zastosować do zasobów pasujących do danej ścieżki. Ścieżki zapisuje się jako wzorce "Ant Glob" - szczegóły znajdziesz w [dokumentacji](http://ant.apache.org/manual/dirtasks.html#patterns). Można używać następujących wildcardów: `*` -: Dopasowanie do zera lub więcej znaków. Na przykład `sprite*.png` pasuje do plików `sprite.png`, `sprite1.png` i `sprite_with_a_long_name.png`. +: Dopasowuje zero lub więcej znaków. Na przykład `sprite*.png` pasuje do plików `sprite.png`, `sprite1.png` i `sprite_with_a_long_name.png`. `?` -: Dopasowanie dokładnie do jednego znaku. Na przykład `sprite?.png` pasuje do plików `sprite1.png`, `spriteA.png`, ale nie pasuje do `sprite.png` ani `sprite_with_a_long_name.png`. +: Dopasowuje dokładnie jeden znak. Na przykład `sprite?.png` pasuje do plików `sprite1.png` i `spriteA.png`, ale nie do `sprite.png` ani `sprite_with_a_long_name.png`. `**` -: Dopasowanie do całego drzewa katalogów lub - gdy używane jako nazwa katalogu - do zera lub więcej katalogów. Na przykład `/gui/**` pasuje do wszystkich plików w katalogu `/gui` i wszystkich jego podkatalogach. +: Dopasowuje całe drzewo katalogów albo, gdy jest użyte jako nazwa katalogu, zero lub więcej katalogów. Na przykład `/gui/**` pasuje do wszystkich plików w katalogu `/gui` i jego podkatalogach. -![Ścieżki](images/texture_profiles/texture_profiles_paths.png) +![Paths](images/texture_profiles/texture_profiles_paths.png) Ten przykład zawiera dwa wzorce ścieżek i odpowiadające im profile. `/gui/**/*.atlas` -: Wszystkie pliki *.atlas* w katalogu */gui* lub którymkolwiek z jego podkatalogów będą przetwarzane zgodnie z profilem "gui_atlas". +: Wszystkie pliki `*.atlas` w katalogu `/gui` i jego podkatalogach będą przetwarzane zgodnie z profilem `gui_atlas`. `/**/*.atlas` -: Wszystkie pliki *.atlas* w dowolnym miejscu w projekcie będą przetwarzane zgodnie z profilem "atlas". +: Wszystkie pliki `*.atlas` w dowolnym miejscu projektu będą przetwarzane zgodnie z profilem `atlas`. -Należy zauważyć, że bardziej ogólna ścieżka jest podawana na końcu. Kryterium działania jest określone jako od góry do dołu. Pierwsze wystąpienie, które pasuje do ścieżki zasobu, zostanie użyte. Dopasowanie ścieżki niżej na liście nigdy nie zastępuje pierwszego trafienia. Gdyby ścieżki były podane w odwrotnej kolejności, każda mapa kostek zostałaby przetworzona profilem "atlas", nawet te w katalogu */gui*. +Zwróć uwagę, że bardziej ogólny wzorzec umieszczono na końcu. Algorytm dopasowania działa od góry do dołu. Zostanie użyte pierwsze wystąpienie pasujące do ścieżki zasobu. Dopasowanie niżej na liście nigdy nie nadpisuje pierwszego trafienia. Gdyby kolejność była odwrotna, każdy atlas zostałby przetworzony profilem `atlas`, również te z katalogu `/gui`. -Zasoby tekstur, które _nie_ pasują do żadnej ścieżki w pliku profili, zostaną skompilowane i przeskalowane do najbliżej potęgi liczby 2, ale poza tym pozostaną nietknięte. +Zasoby tekstur, które *nie* pasują do żadnej ścieżki z pliku profili, zostaną skompilowane i przeskalowane do najbliższej potęgi dwójki, ale poza tym pozostaną bez zmian. ## Profile -Sekcja *profiles* (profile) w pliku profili tekstur zawiera listę nazwanych profili. Każdy profil zawiera jedną lub więcej platform (*platforms*), a każdą platformę opisuje lista właściwości. +Sekcja *profiles* w pliku profili tekstur zawiera listę nazwanych profili. Każdy profil zawiera jedną lub więcej pozycji *platforms*, a każda platforma jest opisana zestawem właściwości. -![Profile](images/texture_profiles/texture_profiles_profiles.png) +![Profiles](images/texture_profiles/texture_profiles_profiles.png) *Platforms* -: Określa pasującą platformę. `OS_ID_GENERIC` pasuje do wszystkich platform, w tym do wersji dev-app na urządzeniu, `OS_ID_WINDOWS` pasuje do wersji docelowych systemów Windows, `OS_ID_IOS` pasuje do wersji na urządzenia iOS itp. Należy zauważyć, że jeśli określono `OS_ID_GENERIC`, zostanie on uwzględniony we wszystkich platformach. +: Określa pasującą platformę. `OS_ID_GENERIC` pasuje do wszystkich platform, `OS_ID_WINDOWS` do bundli Windows, `OS_ID_IOS` do bundli iOS itd. Jeśli podasz `OS_ID_GENERIC`, zostanie on uwzględniony dla wszystkich platform. ::: important -Jeśli dwa [ustawienia ścieżki](#path-settings) pasują do tego samego pliku i ścieżka używa różnych profili z różnymi platformami, zostaną użyte **oba** profile i zostaną wygenerowane **dwie** tekstury. +Jeśli dwa [ustawienia ścieżek](#ustawienia-ścieżek) pasują do tego samego pliku, a dana ścieżka używa różnych profili z różnymi platformami, zostaną użyte **oba** profile i wygenerowane zostaną **dwie** tekstury. ::: *Formats* -: Jedna lub więcej formatów tekstury do wygenerowania. Jeśli określono wiele formatów, zostaną wygenerowane tekstury dla każdego formatu i dołączone do paczki. Silnik wybiera tekstury formatu obsługiwanego przez platformę uruchomieniową. +: Jeden lub więcej formatów tekstur do wygenerowania. Jeśli podasz kilka formatów, do bundla trafią tekstury w każdym z nich. Silnik wybierze podczas działania format obsługiwany przez bieżącą platformę. *Mipmaps* -: Jeśli zaznaczone, generowane są [mipmapy](https://pl.wikipedia.org/wiki/Mipmapping) dla platformy. Domyślnie nie jest zaznaczone. +: Jeśli opcja jest zaznaczona, dla tej platformy zostaną wygenerowane mipmapy. Domyślnie jest wyłączona. *Premultiply alpha* -: Jeśli zaznaczone, alfa, czyli wskaźnik przezroczystości, jest wstępnie mnożona do danych tekstury. Domyślnie jest zaznaczone. +: Jeśli opcja jest zaznaczona, kanał alfa zostanie przemnożony z danymi tekstury. Domyślnie jest włączona. *Max Texture Size* -: Maksymalny rozmiar tekstury. Jeśli ustawiono tę opcję na wartość różną od zera, tekstury są ograniczone pod względem liczby pikseli do określonej liczby. Każda tekstura, która ma szerokość lub wysokość większą niż określona wartość, zostanie przeskalowana w dół. +: Jeśli ustawisz wartość inną niż zero, rozmiar tekstur w pikselach zostanie ograniczony do tej wartości. Każda tekstura szersza lub wyższa od tej granicy zostanie przeskalowana w dół. -Do każdego profilu dodawane są następujące formaty (*Formats*): +Każdy wpis *Formats* dodany do profilu ma następujące właściwości: *Format* -: Format do użycia podczas enkodowania tekstury. Poniżej znajdują się dostępne formaty tekstur. +: Format używany podczas kodowania tekstury. Listę dostępnych formatów znajdziesz poniżej. -*Compression* -: Kompresja. Wybiera poziom jakości wynikowego obrazu skompresowanego. +*Compressor* +: Kompresor używany do kodowania tekstury. -| Poziom | Informacja | -| -------- | ----------------------------------------------- | -| `FAST` | Najszybsza kompresja. Niska jakość grafiki | -| `NORMAL` | Domyślna kompresja. Najlepsza jakość grafiki | -| `HIGH` | Najwolniejsza kompresja. Mniejszy rozmiar pliku | -| `BEST` | Wolna kompresja. Najmniejszy rozmiar pliku | +*Compressor Preset* +: Ustawia preset kompresji używany podczas kodowania wynikowego obrazu. Każdy preset zależy od danego kompresora i jego wewnętrznych ustawień. Dla uproszczenia dostępne presety mają obecnie cztery poziomy: -::: sidenote -Od wersji 1.2.185 nazwy te zostały zmienione - zredefiniowane, aby uniknąć niejednoznaczności. -::: +| Preset | Informacja | +| ----------- | ------------------------------------------- | +| `LOW` | Najszybsza kompresja. Niska jakość obrazu | +| `MEDIUM` | Domyślna kompresja. Najlepsza jakość obrazu | +| `HIGH` | Najwolniejsza kompresja. Mniejszy plik | +| `HIGHEST` | Wolna kompresja. Najmniejszy plik | -*Type* -: Pozwala określić typ kompresji dla obrazów, `COMPRESSION_TYPE_DEFAULT` albo `COMPRESSION_TYPE_BASIS_UASTC`. Zobacz [Typy Kompresji tutaj](#compression-types). +Pamiętaj, że kompresor `uncompressed` ma tylko jeden preset o nazwie `uncompressed`, co oznacza brak kompresji tekstur. +Listę dostępnych kompresorów znajdziesz w sekcji [Kompresory](#compressors). ## Formaty tekstur -Tekstury sprzętowe mogą być przetwarzane na dane nieskompresowane lub skompresowane *stratnie* o różnej liczbie kanałów i głębi bitowej. Kompresja sprzętowa oznacza, że ostateczny obraz będzie miał stały rozmiar, niezależnie od zawartości obrazu. Oznacza to, że utrata jakości podczas kompresji zależy od zawartości oryginalnej tekstury. +Tekstury sprzętowe mogą być przetwarzane do danych nieskompresowanych albo *stratnie* skompresowanych, z różną liczbą kanałów i różną głębią bitową. W przypadku stałorozmiarowej kompresji sprzętowej wynikowy obraz ma zawsze z góry określony rozmiar, niezależnie od treści. Oznacza to, że utrata jakości zależy od zawartości oryginalnej tekstury. + +Ponieważ transkodowanie Basis Universal zależy od możliwości GPU urządzenia, zalecane formaty do stosowania z kompresją Basis Universal to formaty ogólne: +`TEXTURE_FORMAT_RGB`, `TEXTURE_FORMAT_RGBA`, `TEXTURE_FORMAT_RGB_16BPP`, `TEXTURE_FORMAT_RGBA_16BPP`, `TEXTURE_FORMAT_LUMINANCE` oraz `TEXTURE_FORMAT_LUMINANCE_ALPHA`. + +Transkoder Basis Universal obsługuje wiele formatów wyjściowych, między innymi `ASTC4x4`, `BCx`, `ETC2`, `ETC1` i `PVRTC1`. -Ponieważ transkodowanie kompresji Basis Universal zależy od możliwości karty graficznej (GPU) urządzenia, zalecane formaty do użycia z kompresją Basis Universal to ogólne formaty, takie jak: -`TEXTURE_FORMAT_RGB`, `TEXTURE_FORMAT_RGBA`, `TEXTURE_FORMAT_RGB_16BPP`, `TEXTURE_FORMAT_RGBA_16BPP`, `TEXTURE_FORMAT_LUMINANCE` i `TEXTURE_FORMAT_LUMINANCE_ALPHA`. +Obecnie obsługiwane są następujące formaty stratnej kompresji: -Transkoder Basis Universal obsługuje wiele formatów wyjściowych, takich jak: `ASTC4x4`, `BCx`, `ETC2`, `ETC1` i `PVRTC1`. +| Format | Kompresja | Szczegóły | +| -------------------------------- | --------- | --------- | +| `TEXTURE_FORMAT_RGB` | brak | Kolor 3-kanałowy. Kanał alfa jest odrzucany. | +| `TEXTURE_FORMAT_RGBA` | brak | Kolor 3-kanałowy i pełny kanał alfa. | +| `TEXTURE_FORMAT_RGB_16BPP` | brak | Kolor 3-kanałowy. 5+6+5 bitów. | +| `TEXTURE_FORMAT_RGBA_16BPP` | brak | Kolor 3-kanałowy i pełny kanał alfa. 4+4+4+4 bity. | +| `TEXTURE_FORMAT_LUMINANCE` | brak | 1-kanałowa skala szarości, bez alfy. Kanały RGB są zredukowane do jednego. Alfa jest odrzucana. | +| `TEXTURE_FORMAT_LUMINANCE_ALPHA` | brak | 1-kanałowa skala szarości i pełny kanał alfa. Kanały RGB są zredukowane do jednego. | -Obecnie obsługiwane są następujące formaty kompresji stratnej: +W przypadku ASTC liczba kanałów zawsze wynosi 4 (RGB + alfa), a sam format określa rozmiar kompresji blokowej. +Te formaty są zgodne wyłącznie z kompresorem ASTC. Każda inna kombinacja spowoduje błąd builda. -| Format | Kompresja | Szczegóły | -| --------------------------------- | ----------- | -------------------------------- | ---- | -| `TEXTURE_FORMAT_RGB` | brak | Kolor 3-kanałowy. Alfa jest usuwana. | -| `TEXTURE_FORMAT_RGBA` | brak | Kolor 3-kanałowy i pełna alfa. | -| `TEXTURE_FORMAT_RGB_16BPP` | brak | Kolor 3-kanałowy. 5+6+5 bitów. | -| `TEXTURE_FORMAT_RGBA_16BPP` | brak | Kolor 3-kanałowy i pełna alfa. 4+4+4+4 bity. | -| `TEXTURE_FORMAT_LUMINANCE` | brak | Skala szarości 1-kanałowa, brak alfy. Kanały RGB pomnożone przez siebie. Alfa jest usuwana. | -| `TEXTURE_FORMAT_LUMINANCE_ALPHA` | brak | Skala szarości 1-kanałowa i pełna alfa. Kanały RGB pomnożone przez siebie. | +`TEXTURE_FORMAT_RGBA_ASTC_4X4` +`TEXTURE_FORMAT_RGBA_ASTC_5X4` +`TEXTURE_FORMAT_RGBA_ASTC_5X5` +`TEXTURE_FORMAT_RGBA_ASTC_6X5` +`TEXTURE_FORMAT_RGBA_ASTC_6X6` +`TEXTURE_FORMAT_RGBA_ASTC_8X5` +`TEXTURE_FORMAT_RGBA_ASTC_8X6` +`TEXTURE_FORMAT_RGBA_ASTC_8X8` +`TEXTURE_FORMAT_RGBA_ASTC_10X5` +`TEXTURE_FORMAT_RGBA_ASTC_10X6` +`TEXTURE_FORMAT_RGBA_ASTC_10X8` +`TEXTURE_FORMAT_RGBA_ASTC_10X10` +`TEXTURE_FORMAT_RGBA_ASTC_12X10` +`TEXTURE_FORMAT_RGBA_ASTC_12X12` +## Kompresory -## Typy kompresji +Domyślnie obsługiwane są następujące kompresory tekstur. Dane zostaną rozpakowane po załadowaniu pliku tekstury do pamięci. -Obsługiwane są następujące typy programowych kompresji obrazów. Dane są rozpakowywane, gdy plik tekstury jest ładowany do pamięci. +| Nazwa | Formaty | Informacja | +| -------------- | -------------------- | ---------- | +| `Uncompressed` | Wszystkie formaty | Brak kompresji. Ustawienie domyślne. | +| `BasisU` | Wszystkie formaty RGB/RGBA | Wysokiej jakości, stratna kompresja Basis Universal. Niższa jakość daje mniejszy rozmiar. | +| `ASTC` | Wszystkie formaty ASTC | Stratna kompresja ASTC. Niższa jakość daje mniejszy rozmiar. | ::: sidenote -Obecnie analizujemy, jak ponownie wprowadzić obsługę sprzętowa formatów, a także dodatkową obsługę kompresji WEBP. -Nasze obecne długotrwałe zadanie polegające na wprowadzeniu wtyczek do przetwarzania treści ma na celu rozwiązanie tego problemu. +W Defold 1.9.7 przebudowano pipeline kompresji tekstur tak, aby obsługiwał instalowalne kompresory. To pierwszy krok do umożliwienia implementowania algorytmów kompresji tekstur w rozszerzeniach, na przykład WEBP albo własnych rozwiązań. ::: -| Typ | Formaty | Szczegóły | -| --------------------------------- | -------------------------- | --------- | -| `COMPRESSION_TYPE_DEFAULT` | Wszystkie formaty | Ogólna kompresja danych bez utraty. Domyślna. | -| `COMPRESSION_TYPE_BASIS_UASTC` | Wszystkie formaty RGB/RGBA | Wysoka jakość kompresji Basis Universal, utrata jakości. Niższy poziom jakości prowadzi do mniejszego rozmiaru. | - ## Przykładowy obraz -Aby lepiej zrozumieć wyniki, oto przykład. -Należy pamiętać, że jakość obrazu, czas kompresji i rozmiar kompresji zawsze zależą od obrazu wejściowego i mogą się różnić. +Aby lepiej pokazać wynik działania kompresji, poniżej znajduje się przykład. Pamiętaj, że jakość obrazu, czas kompresji i rozmiar skompresowanych danych zawsze zależą od obrazu wejściowego i mogą się różnić. -Obraz oryginalny (1024x512): -![Obraz oryginalny](images/texture_profiles/kodim03_pow2.png) +Obraz bazowy (1024x512): +![New profiles file](images/texture_profiles/kodim03_pow2.png) -### Czasy kompresji +### Czas kompresji -| Poziom | Czas kompresji | Czasy relatywny | -| ----------------------------- | --------------- | -| `FAST` | 0m0.143s | 0.5x | -| `NORMAL` | 0m0.294s | 1.0x | -| `HIGH` | 0m1.764s | 6.0x | -| `BEST` | 0m1.109s | 3.8x | +| Preset | Czas kompresji | Czas względny | +| ----------- | -------------- | ------------- | +| `LOW` | 0m0.143s | 0.5x | +| `MEDIUM` | 0m0.294s | 1.0x | +| `HIGH` | 0m1.764s | 6.0x | +| `HIGHEST` | 0m1.109s | 3.8x | ### Utrata sygnału -Porównanie wykonuje się za pomocą narzędzia `basisu` (pomiar PSNR) -100 dB oznacza brak utraty sygnału (jest to to samo co oryginalny obraz) - -| Poziom | Sygnał | -| ------------------------------------------------------------ | -| `FAST` | Max: 34 Mean: 0.470 RMS: 1.088 PSNR: 47.399 dB | -| `NORMAL` | Max: 35 Mean: 0.439 RMS: 1.061 PSNR: 47.620 dB | -| `HIGH` | Max: 37 Mean: 0.898 RMS: 1.606 PSNR: 44.018 dB | -| `BEST` | Max: 51 Mean: 1.298 RMS: 2.478 PSNR: 40.249 dB | +Porównanie wykonano narzędziem `basisu`, mierząc PSNR. +100 dB oznacza brak utraty sygnału, czyli identyczny obraz jak oryginał. -### Rozmiary plików skompresowanych +| Preset | Sygnał | +| ----------- | ------ | +| `LOW` | Max: 34 Mean: 0.470 RMS: 1.088 PSNR: 47.399 dB | +| `MEDIUM` | Max: 35 Mean: 0.439 RMS: 1.061 PSNR: 47.620 dB | +| `HIGH` | Max: 37 Mean: 0.898 RMS: 1.606 PSNR: 44.018 dB | +| `HIGHEST` | Max: 51 Mean: 1.298 RMS: 2.478 PSNR: 40.249 dB | -Oryginalny rozmiar pliku wynosi 1572882 bajtów. +### Rozmiary skompresowanych plików -| Poziom | Rozmiar pliku | Procent | -| ------------------------------------- | -| `FAST` | 357225 | 22.71 % | -| `NORMAL` | 365548 | 23.24 % | -| `HIGH` | 277186 | 17.62 % | -| `BEST` | 254380 | 16.17 % | +Oryginalny plik ma rozmiar 1572882 bajtów. +| Preset | Rozmiar pliku | Udział | +| ----------- | ------------- | ------ | +| `LOW` | 357225 | 22.71 % | +| `MEDIUM` | 365548 | 23.24 % | +| `HIGH` | 277186 | 17.62 % | +| `HIGHEST` | 254380 | 16.17 % | ### Jakość obrazu -Oto wynikowe obrazy (pobrane z kodowania ASTC przy użyciu narzędzia `basisu`) +Poniżej znajdują się obrazy wynikowe uzyskane z kodowania ASTC przy użyciu narzędzia `basisu`. -`FAST` -![fast compression level](images/texture_profiles/kodim03_pow2.fast.png) +`LOW` +![low compression preset](images/texture_profiles/kodim03_pow2.fast.png) -`NORMAL` -![normal compression level](images/texture_profiles/kodim03_pow2.normal.png) +`MEDIUM` +![medium compression preset](images/texture_profiles/kodim03_pow2.normal.png) `HIGH` -![high compression level](images/texture_profiles/kodim03_pow2.high.png) - -`BEST` -![best compression level](images/texture_profiles/kodim03_pow2.best.png) - +![high compression preset](images/texture_profiles/kodim03_pow2.high.png) +`HIGHEST` +![best compression preset](images/texture_profiles/kodim03_pow2.best.png) diff --git a/docs/pl/manuals/writing-code.md b/docs/pl/manuals/writing-code.md index 2c780cd9..4e110d43 100644 --- a/docs/pl/manuals/writing-code.md +++ b/docs/pl/manuals/writing-code.md @@ -1,59 +1,74 @@ --- title: Pisanie kodu -brief: Ta instrukcja krótko omawia, jak pracować z kodem w Defold. +brief: Ta instrukcja krótko omawia pracę z kodem w silniku Defold. --- # Pisanie kodu -Podczas gdy Defold pozwala tworzyć wiele zawartości gry za pomocą narzędzi wizualnych, takich jak Edytory map kafelków (tilemap) i efektów cząsteczkowych (particle FX), logikę gry tworzysz za pomocą Edytora kodu. Logikę gry pisze się za pomocą języka programowania [Lua](https://www.lua.org/), podczas gdy rozszerzenia samego silnika pisze się przy użyciu języków niskopoziomowych dedykowanych dla docelowej platformy. +Choć Defold pozwala tworzyć znaczną część zawartości gry za pomocą narzędzi wizualnych, takich jak edytory map kafelków i efektów cząsteczkowych, logikę gry nadal tworzysz w edytorze kodu. Logikę gry pisze się w [języku Lua](https://www.lua.org/), natomiast rozszerzenia samego silnika tworzy się w języku lub językach natywnych dla docelowej platformy. ## Pisanie kodu Lua -Defold używa Lua 5.1 i LuaJIT (w zależności od docelowej platformy) i należy stosować specyfikację tego języka dla konkretnych wersji Lua podczas pisania logiki gry. Aby uzyskać więcej szczegółów na temat pracy z Lua w Defoldzie, zobacz nasz [podręcznik Lua w Defold](/manuals/lua). +Defold używa Lua 5.1 oraz LuaJIT, zależnie od platformy docelowej, dlatego podczas pisania logiki gry trzeba trzymać się specyfikacji tych wersji języka. Więcej informacji znajdziesz w [instrukcji Lua w silniku Defold](/manuals/lua). + +## Używanie innych języków kompilowanych do Lua + +Defold obsługuje transpiler’y generujące kod Lua. Po zainstalowaniu rozszerzenia transpiler’a możesz używać alternatywnych języków, takich jak [Teal](https://github.com/defold/extension-teal), aby pisać statycznie sprawdzany kod Lua. To funkcja podglądowa i ma ograniczenia: obecna obsługa transpiler’ów nie udostępnia informacji o modułach i funkcjach zdefiniowanych w środowisku uruchomieniowym Lua w Defold. Oznacza to, że używając API Defold, takiego jak `go.animate`, musisz samodzielnie przygotować zewnętrzne definicje. ## Pisanie kodu natywnego -Defold pozwala na rozszerzenie silnika gry kodem natywnym (native extensions), aby uzyskać dostęp do funkcji specyficznych dla danej platformy, których nie dostarcza sam silnik. Możesz również użyć kodu natywnego, gdy wydajność Lua nie jest wystarczająca (obliczenia wymagające dużych zasobów, przetwarzanie obrazów itp.). Aby dowiedzieć się więcej, zajrzyj do naszych [podręczników dotyczących Rozszerzeń Natywnych](/manuals/extensions/). +Defold pozwala rozszerzać silnik gry kodem natywnym, aby uzyskać dostęp do funkcji specyficznych dla platformy, których sam silnik nie udostępnia. Kod natywny przydaje się też wtedy, gdy wydajność Lua okazuje się niewystarczająca, na przykład przy kosztownych obliczeniach lub przetwarzaniu obrazów. Szczegóły znajdziesz w [instrukcjach o Native Extensions](/manuals/extensions/). -## Używanie wbudowanego Edytora kodu +## Używanie wbudowanego edytora kodu -Defold posiada wbudowany Edytor kodu, który pozwala na otwieranie i edytowanie plików Lua (.lua), plików skryptów Defold (.script, .gui_script i .render_script) oraz innych plików z rozszerzeniem, które nie są obsługiwane natywnie przez Edytor. Dodatkowo Edytor ten oferuje podświetlanie składni dla plików Lua i skryptów oraz podręczny dostęp do dokumentacji dla funkcji API. +Defold ma wbudowany edytor kodu, który pozwala otwierać i edytować pliki Lua (`.lua`), pliki skryptów Defold (`.script`, `.gui_script` i `.render_script`), a także inne pliki z rozszerzeniami, których edytor nie obsługuje natywnie. Edytor zapewnia również podświetlanie składni dla plików Lua i skryptów. ![](/images/editor/code-editor.png) +### Uzupełnianie kodu -### Dodawanie sprawdzania poprawności kodu Lua za pomocą LSP +Wbudowany edytor kodu wyświetla podpowiedzi funkcji podczas pisania: -Defold obsługuje część protokołu Language Server Protocol (LSP), który można użyć do analizy kodu i wskazywania błędów programistycznych i stylowych. Proces ten jest również znany jako sprawdzanie poprawności kodu (linting). +![](/images/editor/codecompletion.png) -Serwer języka Lua i linter kodu są dostępne jako wtyczka (plugin). Zainstaluj wtyczkę, [dodając ją jako zależność](/manuals/libraries/#setting-up-library-dependencies): +Naciśnięcie CTRL + Space pokazuje dodatkowe informacje o funkcjach, argumentach i wartościach zwracanych: -``` -https://github.com/defold/lua-language-server/releases/download/v0.0.5/release.zip -``` -Dostępne wersje można znaleźć na [stronie wydań](https://github.com/defold/lua-language-server/releases) wtyczki. Dowiedz się więcej na temat tej wtyczki na [stronie wsparcia na forum Defold](https://forum.defold.com/t/linting-in-the-code-editor/72465). +![](/images/editor/apireference.png) +### Konfiguracja lintingu + +Wbudowany edytor kodu wykonuje linting przy użyciu [Luacheck](https://luacheck.readthedocs.io/en/stable/index.html) oraz [Lua language server](https://luals.github.io/wiki/diagnostics/). Aby skonfigurować Luacheck, utwórz plik `.luacheckrc` w katalogu głównym projektu. Listę dostępnych opcji znajdziesz na [stronie konfiguracji Luacheck](https://luacheck.readthedocs.io/en/stable/config.html). Defold używa domyślnie następującej konfiguracji Luacheck: + +```lua +unused_args = false -- don't warn on unused arguments (common for .script files) +max_line_length = false -- don't warn on long lines +ignore = { + "611", -- line contains only whitespace + "612", -- line contains trailing whitespace + "614" -- trailing whitespace in a comment +}, +``` -## Użycie zewnętrznego Edytora kodu +## Używanie zewnętrznego edytora kodu -Edytor kodu w Defoldzie zapewnia podstawową funkcjonalność do pisania kodu, ale dla bardziej zaawansowanych przypadków użycia lub dla użytkowników z ulubionym Edytorem kodu, można pozwolić Defoldowi otwierać pliki za pomocą zewnętrznego Edytora, ponieważ skrypty i pliki tworzone przez Defolda w projekcie są edytowalnymi plikami tekstowymi. W [oknie preferencji w zakładce "Code"](/manuals/editor-preferences/#code) można zdefiniować zewnętrzny Edytor, który ma być używany podczas edycji kodu. +Edytor kodu w Defold zapewnia podstawowe możliwości potrzebne do pisania kodu, ale w bardziej zaawansowanych zastosowaniach lub jeśli wolisz własne narzędzie, możesz skonfigurować Defold tak, aby otwierał pliki w zewnętrznym edytorze. W [oknie Preferences, w zakładce Code](/manuals/editor-preferences/#code), można wskazać zewnętrzny edytor używany podczas pracy z kodem. ### Visual Studio Code - Defold Kit -Defold Kit to wtyczka dla Visual Studio Code z następującymi funkcjami: +Defold Kit to wtyczka do Visual Studio Code z następującymi funkcjami: -* Instalowanie zalecanych rozszerzeń -* Podświetlanie, autouzupełnianie i sprawdzanie poprawności (linting) Lua -* Zastosowanie odpowiednich ustawień do przestrzeni roboczej -* Adnotacje Lua dla interfejsu API Defold -* Adnotacje Lua dla zależności -* Budowanie i uruchamianie -* Debugowanie z punktami przerwania (breakpoints) -* Budowanie i pakowanie dla wszystkich platform -* Wdrażanie na podłączone urządzenia mobilne +* instalacja zalecanych rozszerzeń +* podświetlanie, autouzupełnianie i linting Lua +* stosowanie odpowiednich ustawień do obszaru roboczego +* adnotacje Lua dla API Defold +* adnotacje Lua dla zależności +* budowanie i uruchamianie +* debugowanie z punktami przerwania +* bundlowanie na wszystkie platformy +* wdrażanie na podłączone urządzenia mobilne -Dowiedz się więcej i zainstaluj Defold Kit z [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=astronachos.defold). +Więcej informacji i instalację Defold Kit znajdziesz w [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=astronachos.defold). ## Oprogramowanie dokumentacyjne -Dostępne są paczki przygotowane przez społeczność Defolda do generowania dokumentacji API dla [Dash i Zeal](https://forum.defold.com/t/defold-docset-for-dash/2417). +Społeczność przygotowała pakiety referencji API do programów [Dash i Zeal](https://forum.defold.com/t/defold-docset-for-dash/2417). From 91f83436b386c106ef90691bcee5c01e7dadcf6e Mon Sep 17 00:00:00 2001 From: AGulev Date: Fri, 13 Mar 2026 13:19:40 +0100 Subject: [PATCH 2/3] actualization butch two --- docs/pl/manuals/camera.md | 269 +++++++-- docs/pl/manuals/editor-scripts.md | 857 +++++++++++++++++++++++----- docs/pl/manuals/editor.md | 341 ++++++++--- docs/pl/manuals/font.md | 230 ++++++-- docs/pl/manuals/gui-layouts.md | 105 ++-- docs/pl/manuals/live-update.md | 374 +++--------- docs/pl/manuals/physics-shapes.md | 153 +++-- docs/pl/manuals/project-settings.md | 788 +++++++++++++++++-------- docs/pl/manuals/script.md | 187 +++--- docs/pl/manuals/sprite.md | 108 ++-- 10 files changed, 2340 insertions(+), 1072 deletions(-) diff --git a/docs/pl/manuals/camera.md b/docs/pl/manuals/camera.md index 93f522d3..983be98b 100644 --- a/docs/pl/manuals/camera.md +++ b/docs/pl/manuals/camera.md @@ -1,63 +1,120 @@ --- -title: Kamera -brief: Ta instrukcja opisuje komponent Kamery w Defoldzie. +title: Instrukcja komponentu Camera +brief: Ta instrukcja opisuje działanie komponentu Camera w silniku Defold. --- -# Kamera +# Kamery -Kamera (ang. camera) w Defoldzie jest komponentem, który zmienia widok i projekcję świata gry. Komponent kamery definiuje podstawową kamerę perspektywiczną lub ortograficzną, która dostarcza macierz widoku i projekcji do skryptu renderującego (ang. render script). +Kamera (ang. camera) w silniku Defold jest komponentem, który zmienia obszar widoczny i projekcję świata gry. Komponent Camera definiuje prostą kamerę perspektywiczną albo ortograficzną i przekazuje do skryptu renderującego macierz widoku oraz macierz projekcji. -Kamera perspektywiczna jest zazwyczaj używana w grach 3D, gdzie widok kamery oraz wielkość i perspektywa obiektów oparte są na tzw. bryle widokowej (ang. view frustum) oraz odległości i kącie widzenia od kamery do obiektów w grze. +Kamera perspektywiczna jest zwykle używana w grach 3D, gdzie widok kamery oraz rozmiar i perspektywa obiektów zależą od bryły widoku (frustum), odległości od kamery i kąta patrzenia na obiekty w grze. -W grach 2D często pożądane jest renderowanie sceny za pomocą rzutu ortograficznego. Oznacza to, że widok kamery jest określany przez specjalną bryłę widokową - prostopadłościan. Rzut ortograficzny jest nierealistyczny, ponieważ nie zmienia rozmiaru obiektów na podstawie ich odległości. Obiekt oddalony o 1000 jednostek zostanie narysowany w takim samym rozmiarze jak obiekt tuż przed kamerą. +W grach 2D często pożądane jest renderowanie sceny z użyciem projekcji ortograficznej. Oznacza to, że widok kamery nie jest już wyznaczany przez bryłę widoku, lecz przez prostopadłościenny obszar. Projekcja ortograficzna jest niefotorealistyczna, ponieważ nie zmienia rozmiaru obiektów zależnie od ich odległości. Obiekt oddalony o 1000 jednostek zostanie narysowany w takim samym rozmiarze jak obiekt znajdujący się tuż przed kamerą. -![projekcje](images/camera/projections.png) +![projections](images/camera/projections.png) ## Tworzenie kamery -Aby utworzyć kamerę, kliknij prawym przyciskiem myszy na obiekcie gry i wybierz Add Component ▸ Camera. Możesz także utworzyć plik komponentu w hierarchii projektu (*Outline*) i dodać go do obiektu gry. +Aby utworzyć kamerę, kliknij prawym przyciskiem myszy obiekt gry i wybierz Add Component ▸ Camera. Możesz też utworzyć plik komponentu w hierarchii projektu i dodać ten plik komponentu do obiektu gry. -![tworzenie kamery](images/camera/create.png) +![create camera component](images/camera/create.png) -Komponent kamery ma następujące właściwości, które definiują bryłę kamery (*frustum*): +Komponent Camera ma następujące właściwości definiujące jego *frustum*: -![ustawienia kamery](images/camera/settings.png) +![camera settings](images/camera/settings.png) Id -: Identyfikator komponentu +: Identyfikator (Id) komponentu. Aspect Ratio -: (**Tylko dla kamery perspektywicznej**) Współczynnik proporcji - stosunek szerokości bryły widokowej do jej wysokości. Wartość 1.0 oznacza założenie kwadratowego widoku. 1.33 jest odpowiednie dla widoku 4:3, takiego jak 1024x768. 1.78 jest odpowiednie dla widoku 16:9. To ustawienie jest ignorowane, jeśli jest ustawiony *Auto Aspect Ratio*. +: (**Tylko dla kamery perspektywicznej**) Stosunek szerokości bryły widoku do jej wysokości. `1.0` oznacza widok kwadratowy. `1.33` dobrze pasuje do widoku 4:3, takiego jak 1024x768. `1.78` dobrze pasuje do widoku 16:9. To ustawienie jest ignorowane, jeśli włączone jest *Auto Aspect Ratio*. Fov -: (**Tylko dla kamery perspektywicznej**) Pionowe pole widzenia kamery wyrażone w radianach. Im szersze pole widzenia, tym więcej zobaczy kamera. +: (**Tylko dla kamery perspektywicznej**) *Pionowe* pole widzenia kamery wyrażone w radianach. Im szersze pole widzenia, tym większy obszar zobaczy kamera. Near Z -: wartość Z bliskiej płaszczyzny odcięcia (ang. clipping plane). +: Wartość Z bliskiej płaszczyzny odcięcia (ang. clipping plane). Far Z : Wartość Z dalekiej płaszczyzny odcięcia. Auto Aspect Ratio -: (**Tylko dla kamery perspektywicznej**) - Automatyczny współczynnik proporcji - ustaw tę opcję, aby kamera automatycznie obliczała współczynnik proporcji. +: (**Tylko dla kamery perspektywicznej**) Włącz tę opcję, aby kamera automatycznie obliczała współczynnik proporcji. Orthographic Projection -: Projekcja ortograficzna - ustaw tę opcję, aby przełączyć kamerę na projekcję ortograficzną (patrz niżej). +: Włącz tę opcję, aby przełączyć kamerę na projekcję ortograficzną. Orthographic Zoom -: (**Tylko dla kamery ortograficznej**) - Powiększenie używane dla rzutu ortograficznego (> 1 = przybliż, < 1 = oddal). +: (**Tylko dla kamery ortograficznej**) Powiększenie używane w projekcji ortograficznej (`> 1` = przybliżenie, `< 1` = oddalenie). + +Orthographic Mode +: (**Tylko dla kamery ortograficznej**) Określa, jak kamera ortograficzna wyznacza zoom względem rozmiaru okna i rozdzielczości projektowej, czyli wartości `game.project` → `display.width/height`. + - `Fixed` (stały zoom): używa bieżącej wartości *Orthographic Zoom* bez zmian. + - `Auto Fit` (contain): automatycznie dopasowuje zoom tak, aby cały obszar projektowy mieścił się w oknie. Może pokazać dodatkową zawartość po bokach albo u góry i na dole. + - `Auto Cover` (cover): automatycznie dopasowuje zoom tak, aby obszar projektowy wypełniał całe okno. Może przycinać zawartość po bokach albo u góry i na dole. + Ta opcja jest dostępna tylko wtedy, gdy włączone jest *Orthographic Projection*. ## Używanie kamery -Aby aktywować kamerę i przekazać jej macierze widoku i projekcji do skryptu renderującego, wyślij komponentowi wiadomość `acquire_camera_focus`: +Wszystkie kamery są automatycznie włączane i aktualizowane w każdej klatce, a moduł Lua `camera` jest dostępny we wszystkich kontekstach skryptowych. Od Defold 1.8.1 nie trzeba już jawnie włączać kamery przez wysłanie do komponentu wiadomości `acquire_camera_focus`. Stare wiadomości acquire i release nadal istnieją, ale zaleca się używanie wiadomości `enable` i `disable`, tak samo jak w przypadku innych komponentów, które chcesz włączać i wyłączać: + +```lua +msg.post("#camera", "disable") +msg.post("#camera", "enable") +``` + +Aby wyświetlić listę wszystkich obecnie dostępnych kamer, możesz użyć `camera.get_cameras()`: + +```lua +-- Uwaga: wywołania render są dostępne tylko w skrypcie renderującym. +-- Funkcji camera.get_cameras() można używać wszędzie, +-- ale render.set_camera tylko w skrypcie renderującym. + +for k,v in pairs(camera.get_cameras()) do + -- tabela kamer zawiera URL-e wszystkich kamer + render.set_camera(v) + -- tutaj wykonaj renderowanie; wszystko, co zostanie tu narysowane + -- z użyciem materiałów korzystających z macierzy widoku i projekcji, + -- będzie używać macierzy z tej kamery. +end +-- aby wyłączyć kamerę, przekaż nil (albo nie podawaj argumentów) do render.set_camera. +-- po tym wywołaniu wszystkie operacje renderowania będą używać macierzy widoku i projekcji +-- ustawionych bezpośrednio w kontekście renderowania (render.set_view i render.set_projection) +render.set_camera() +``` + +Moduł skryptowy `camera` udostępnia wiele funkcji do manipulowania kamerą. Poniżej kilka przykładów; pełną listę znajdziesz w [dokumentacji API](/ref/camera/). + +```lua +camera.get_aspect_ratio(camera) -- pobierz współczynnik proporcji +camera.get_far_z(camera) -- pobierz far z +camera.get_fov(camera) -- pobierz pole widzenia +camera.get_orthographic_mode(camera) -- pobierz tryb ortograficzny (jedna z wartości camera.ORTHO_MODE_*) +camera.set_aspect_ratio(camera, ratio) -- ustaw współczynnik proporcji +camera.set_far_z(camera, far_z) -- ustaw far z +camera.set_near_z(camera, near_z) -- ustaw near z +camera.set_orthographic_mode(camera, camera.ORTHO_MODE_AUTO_FIT) -- ustaw tryb ortograficzny +... I tak dalej +``` + +Kamera jest identyfikowana przez URL, czyli pełną ścieżkę komponentu w scenie, obejmującą kolekcję, obiekt gry, do którego należy, oraz id komponentu. W tym przykładzie do identyfikacji komponentu kamery z tej samej kolekcji użyjesz URL `/go#camera`, a przy dostępie do kamery z innej kolekcji albo ze skryptu renderującego użyjesz `main:/go#camera`. + +![create camera component](images/camera/create.png) ```lua -msg.post("#camera", "acquire_camera_focus") +-- Dostęp do kamery ze skryptu w tej samej kolekcji: +camera.get_fov("/go#camera") + +-- Dostęp do kamery ze skryptu w innej kolekcji: +camera.get_fov("main:/go#camera") + +-- Dostęp do kamery ze skryptu renderującego: +render.set_camera("main:/go#camera") ``` -Co klatkę, komponent kamery, który obecnie ma fokus kamery, wyśle wiadomość `set_view_projection` do gniazda `"@render"`, czyli dotrze to do twojego skryptu renderującego: +W każdej klatce komponent kamery, który ma aktualnie fokus kamery, wysyła wiadomość `set_view_projection` do gniazda `"@render"`: ```lua -- builtins/render/default.render_script @@ -69,73 +126,161 @@ function on_message(self, message_id, message) end end ``` +1. Wiadomość wysyłana z komponentu kamery zawiera macierz widoku i macierz projekcji. -1. Wiadomość wysłana z komponentu kamery zawiera macierz widoku (view matrix) i macierz projekcji (projection matrix). +Komponent Camera dostarcza skryptowi renderującemu macierz projekcji perspektywicznej albo ortograficznej, zależnie od właściwości *Orthographic Projection*. Macierz projekcji uwzględnia też ustawione bliską i daleką płaszczyznę odcięcia, pole widzenia oraz współczynnik proporcji kamery. -Komponent kamery dostarcza skryptowi renderującemu macierz projekcji albo perspektywiczną, albo ortograficzną, w zależności od właściwości *Orthographic Projection* kamery. Macierz projekcji uwzględnia również określone płaszczyzny odcięcia bliskie i dalekie (near Z, far Z), pole widzenia (FOV) oraz ustawienia współczynnika proporcji kamery. +Macierz widoku dostarczana przez kamerę definiuje położenie i orientację kamery. Kamera z włączonym *Orthographic Projection* centruje widok na pozycji obiektu gry, do którego jest podłączona, natomiast kamera z projekcją perspektywiczną ma lewy dolny róg widoku ustawiony w pozycji obiektu gry, do którego jest podłączona. -Macierz widoku dostarczana przez kamerę określa położenie i orientację kamery. Kamera z Projekcją Ortograficzną (*Orthographic Projection*) będzie miała widok wycentrowany na pozycji obiektu gry, do którego jest podłączona, podczas gdy kamera z Projekcją Perspektywiczną (*Perspective Projection*) będzie miała lewy dolny róg widoku na obiekcie gry, do którego jest podłączona. -::: important -Dla zachowania kompatybilności wstecznej domyślny skrypt renderujący ignoruje projekcję dostarczoną przez kamerę i zawsze używa rzutu ortograficznego. Dowiedz się więcej o skrypcie renderującym oraz macierzach widoku i projekcji w [instrukcji do renderowania](/manuals/render/#default-view-projection). -::: +### Render script + +Podczas używania domyślnego skryptu renderującego Defold automatycznie ustawia ostatnią włączoną kamerę, która ma być używana do renderowania. Wcześniej skrypt w projekcie musiał jawnie wysyłać do renderera wiadomość `use_camera_projection`, aby poinformować go, że ma korzystać z widoku i projekcji z komponentów kamery. Nie jest to już konieczne, ale nadal można tak robić dla zachowania kompatybilności wstecznej. + +Alternatywnie możesz ustawić w skrypcie renderującym konkretną kamerę, której należy użyć do renderowania. Przydaje się to wtedy, gdy chcesz dokładniej kontrolować, która kamera jest używana, na przykład w grze wieloosobowej. + +```lua +-- render.set_camera będzie automatycznie używać macierzy widoku i projekcji +-- przy każdym renderowaniu aż do wywołania render.set_camera(). +render.set_camera("main:/my_go#camera") +``` -Możesz powiedzieć skryptowi renderującemu, aby używał projekcji dostarczonej przez kamerę, wysyłając wiadomość do skryptu renderującego. +Aby sprawdzić, czy kamera jest aktywna, możesz użyć funkcji `get_enabled` z [Camera API](https://defold.com/ref/alpha/camera/#camera.get_enabled:camera): ```lua -msg.post("@render:", "use_camera_projection") +if camera.get_enabled("main:/my_go#camera") then + -- kamera jest włączona, użyj jej do renderowania! + render.set_camera("main:/my_go#camera") +end ``` +::: sidenote +Aby używać funkcji `set_camera` razem z odrzucaniem poza bryłą widoku (frustum culling), musisz przekazać do niej taką opcję: +`render.set_camera("main:/my_go#camera", {use_frustum = true})` +::: + ### Poruszanie kamerą -Aby przesuwać kamerę po obszarze gry, należy przesuwać obiekt gry, do którego jest przypisany komponent kamery. Komponent kamery automatycznie będzie wysyłał zaktualizowaną macierz widoku na podstawie bieżącej pozycji kamery wzdłuż osi X i Y. +Kamerę przesuwa się po świecie gry przez przesuwanie obiektu gry, do którego przypisany jest komponent Camera. Komponent automatycznie wyśle zaktualizowaną macierz widoku na podstawie bieżącej pozycji kamery na osiach X i Y. ### Zoomowanie kamery -Możesz przybliżać i oddalać, używając kamery perspektywicznej, przesuwając obiekt gry, do którego jest przypisana kamera, wzdłuż osi Z. Komponent kamery automatycznie będzie wysyłał zaktualizowaną macierz widoku na podstawie bieżącej pozycji kamery wzdłuż osi Z. +Przy użyciu kamery perspektywicznej możesz przybliżać i oddalać widok, przesuwając obiekt gry, do którego przypisana jest kamera, wzdłuż osi Z. Komponent Camera automatycznie wyśle zaktualizowaną macierz widoku na podstawie bieżącej pozycji kamery na osi Z. -Możesz również przybliżać i oddalać, używając kamery ortograficznej, poprzez zmianę właściwości *Orthographic Zoom* kamery: +W przypadku kamery ortograficznej możesz przybliżać i oddalać widok przez zmianę właściwości *Orthographic Zoom*: ```lua go.set("#camera", "orthographic_zoom", 2) ``` -### Śledzenie obiektu gry +Przy użyciu kamery ortograficznej możesz też przełączać sposób wyznaczania zoomu za pomocą ustawienia *Orthographic Mode* albo z poziomu skryptu: -Kamerę można ustawić tak, aby śledziła obiekt gry, ustawiając obiekt gry, do którego przypisany jest komponent kamery, jako potomka obiektu gry, który ma być śledzony: +```lua +-- pobierz bieżący tryb (jedna z wartości camera.ORTHO_MODE_FIXED, _AUTO_FIT, _AUTO_COVER) +local mode = camera.get_orthographic_mode("#camera") -![Śledzenie obiektu gry](images/camera/follow.png) +-- przełącz na auto-fit (contain), aby cały obszar projektowy zawsze pozostawał widoczny +camera.set_orthographic_mode("#camera", camera.ORTHO_MODE_AUTO_FIT) -Alternatywnym sposobem jest aktualizacja pozycji obiektu gry, do którego przypisany jest komponent kamery, co klatkę, w miarę jak obiekt gry do śledzenia się przemieszcza. +-- przełącz na auto-cover, aby obszar projektowy zawsze wypełniał okno +camera.set_orthographic_mode("#camera", camera.ORTHO_MODE_AUTO_COVER) -### Konwersja współrzędnych ekranu na współrzędne świata +-- wróć do trybu fixed, aby ręcznie sterować zoomem przez orthographic_zoom +camera.set_orthographic_mode("#camera", camera.ORTHO_MODE_FIXED) +``` -Gdy kamera jest przesunięta, przybliżona lub zmieniła projekcję względem domyślnego rozciągniętego rzutu ortograficznego, współrzędne myszy na ekranie dostarczone w funkcji cyklu życia `on_input()` nie będą już odpowiadać współrzędnym świata twoich obiektów gry. Musisz ręcznie uwzględnić zmianę widoku lub projekcji. Konwersja z współrzędnych myszy/ekranu na współrzędne świata z domyślnego skryptu renderującego wygląda tak: +### Adaptive zoom + +Idea adaptive zoom polega na dostosowywaniu wartości zoomu kamery, gdy rozdzielczość ekranu zmienia się względem początkowej rozdzielczości ustawionej w *game.project*. + +Dwa częste podejścia do adaptive zoom to: + +1. Maksymalny zoom: oblicz taką wartość zoomu, aby obszar zawartości odpowiadający początkowej rozdzielczości z *game.project* wypełniał ekran i wykraczał poza jego krawędzie, co może ukryć część zawartości po bokach albo u góry i na dole. +2. Minimalny zoom: oblicz taką wartość zoomu, aby obszar zawartości odpowiadający początkowej rozdzielczości z *game.project* w całości mieścił się w granicach ekranu, co może pokazać dodatkową zawartość po bokach albo u góry i na dole. + +Przykład: + +```lua +local DISPLAY_WIDTH = sys.get_config_int("display.width") +local DISPLAY_HEIGHT = sys.get_config_int("display.height") + +function init(self) + local initial_zoom = go.get("#camera", "orthographic_zoom") + local display_scale = window.get_display_scale() + window.set_listener(function(self, event, data) + if event == window.WINDOW_EVENT_RESIZED then + local window_width = data.width + local window_height = data.height + local design_width = DISPLAY_WIDTH / initial_zoom + local design_height = DISPLAY_HEIGHT / initial_zoom + + -- maksymalny zoom: upewnij się, że początkowe wymiary projektu + -- wypełnią ekran i wyjdą poza jego granice + local zoom = math.max(window_width / design_width, window_height / design_height) / display_scale + + -- minimalny zoom: upewnij się, że początkowe wymiary projektu + -- zmieszczą się w granicach ekranu + --local zoom = math.min(window_width / design_width, window_height / design_height) / display_scale + + go.set("#camera", "orthographic_zoom", zoom) + end + end) +end +``` + +Pełny przykład adaptive zoom znajdziesz w [tym projekcie przykładowym](https://github.com/defold/sample-adaptive-zoom). + +Uwaga: przy użyciu kamery ortograficznej możesz teraz uzyskać zachowanie contain/cover bez własnego kodu, ustawiając *Orthographic Mode* na `Auto Fit` (contain) albo `Auto Cover` (cover). W tych trybach efektywny zoom jest obliczany automatycznie na podstawie rozmiaru okna i rozdzielczości projektowej. -::: sidenote -[Rozwiązania dla kamer od społeczności](/manuals/camera/#rozwiązania-dla-kamer-od-społeczności) wymienione w tym podręczniku oferują funkcje do konwersji między współrzędnymi ekranu a świata. -::: + +### Śledzenie obiektu gry + +Możesz sprawić, aby kamera śledziła obiekt gry, ustawiając obiekt gry, do którego przypisany jest komponent Camera, jako dziecko śledzonego obiektu: + +![follow game object](images/camera/follow.png) + +Innym sposobem jest aktualizowanie co klatkę pozycji obiektu gry, do którego przypisany jest komponent Camera, zgodnie z ruchem śledzonego obiektu. + +### Konwersja współrzędnych myszy na współrzędne świata + +Gdy kamera została przesunięta, przybliżona lub korzysta z innej projekcji niż domyślna rozciągnięta projekcja ortograficzna, współrzędne myszy dostarczane do funkcji cyklu życia `on_input()` przestają odpowiadać współrzędnym świata obiektów gry. Trzeba wtedy ręcznie uwzględnić zmianę widoku albo projekcji. Kod konwertujący współrzędne myszy i ekranu na współrzędne świata wygląda tak: ```Lua --- builtins/render/default.render_script --- -local function screen_to_world(x, y, z) - local inv = vmath.inv(self.projection * self.view) - x = (2 * x / render.get_width()) - 1 - y = (2 * y / render.get_height()) - 1 - z = (2 * z) - 1 - local x1 = x * inv.m00 + y * inv.m01 + z * inv.m02 + inv.m03 - local y1 = x * inv.m10 + y * inv.m11 + z * inv.m12 + inv.m13 - local z1 = x * inv.m20 + y * inv.m21 + z * inv.m22 + inv.m23 - return x1, y1, z1 +--- Konwertuje współrzędne ekranu na współrzędne świata, +-- biorąc pod uwagę widok i projekcję konkretnej kamery +-- @param camera URL kamery używanej do konwersji +-- @param screen_x Współrzędna x na ekranie do przeliczenia +-- @param screen_y Współrzędna y na ekranie do przeliczenia +-- @param z opcjonalna współrzędna z przekazywana przez konwersję, domyślnie 0 +-- @return world_x Wynikowa współrzędna x w świecie +-- @return world_y Wynikowa współrzędna y w świecie +-- @return world_z Wynikowa współrzędna z w świecie +function M.screen_to_world(camera, screen_x, screen_y, z) + local projection = go.get(camera, "projection") + local view = go.get(camera, "view") + local w, h = window.get_size() + + -- https://defold.com/manuals/camera/#converting-mouse-to-world-coordinates + local inv = vmath.inv(projection * view) + local x = (2 * screen_x / w) - 1 + local y = (2 * screen_y / h) - 1 + local x1 = x * inv.m00 + y * inv.m01 + z * inv.m02 + inv.m03 + local y1 = x * inv.m10 + y * inv.m11 + z * inv.m12 + inv.m13 + return x1, y1, z or 0 end ``` -## Manipulacja w czasie rzeczywistym +Pamiętaj, że jako argumentów tej funkcji należy używać wartości `action.screen_x` i `action.screen_y` z `on_input()`. Zobacz [stronę Examples](https://defold.com/examples/render/screen_to_world/), aby sprawdzić konwersję współrzędnych ekranu na współrzędne świata w praktyce. Dostępny jest też [projekt przykładowy](https://github.com/defold/sample-screen-to-world-coordinates/) pokazujący, jak wykonać taką konwersję. + +::: sidenote +[Rozwiązania kamer od społeczności wymienione w tym podręczniku](/manuals/camera/#third-party-camera-solutions) zawierają funkcje konwersji do współrzędnych ekranu i z powrotem. +::: + +## Manipulacja w czasie działania -Kamery można manipulować w czasie rzeczywistym za pomocą różnych wiadomości i właściwości ([patrz w dokumentacji API](/ref/camera/)).). +Kamerami można manipulować w czasie działania za pomocą różnych wiadomości i właściwości. Sposób użycia znajdziesz w [dokumentacji API](/ref/camera/). -Kamera ma wiele różnych właściwości (properties), które można manipulować za pomocą `go.get()` i `go.set()`: +Kamera ma kilka właściwości, którymi można sterować przy użyciu `go.get()` i `go.set()`: `fov` : Pole widzenia kamery (typ `number`). @@ -150,18 +295,18 @@ Kamera ma wiele różnych właściwości (properties), które można manipulowa : Zoom kamery ortograficznej (typ `number`). `aspect_ratio` -: Dodane w Defold 1.4.8. Stosunek szerokości bryły widokowej do jej wysokości. Używane do obliczania projekcji kamery perspektywicznej (typ `number`). +: Stosunek szerokości bryły widoku do jej wysokości. Używany przy obliczaniu projekcji kamery perspektywicznej (`number`). `view` -: Dodane w Defold 1.4.8. Obliczona macierz widoku kamery. TYLKO DO ODCZYTU. (typ `matrix4`). +: Obliczona macierz widoku kamery. TYLKO DO ODCZYTU (`matrix4`). `projection` -: Dodane w Defold 1.4.8. Obliczona macierz projekcji kamery. TYLKO DO ODCZYTU. (typ `matrix4`). +: Obliczona macierz projekcji kamery. TYLKO DO ODCZYTU (`matrix4`). -## Rozwiązania dla kamer od społeczności +## Rozwiązania kamer od społeczności -Istnieje biblioteka wspomagająca kamery, która implementuje wspólne funkcje, takie jak śledzenie obiektu gry, trzęsienie ekranu, konwersja współrzędnych ekranu na współrzędne świata i inne. Jest dostępna na portalu zasobów społeczności Defold (Assets portal): +Społeczność stworzyła rozwiązania kamerowe implementujące typowe funkcje, takie jak trzęsienie ekranu, śledzenie obiektów gry, konwersję współrzędnych ekranu na współrzędne świata i wiele innych. Można je pobrać z portalu zasobów Defold: -- [Orthographic camera](https://defold.com/assets/orthographic/) (2D only) by Björn Ritzl. -- [Defold Rendy](https://defold.com/assets/defold-rendy/) (2D and 3D) by Klayton Kowalski. +- [Orthographic camera](https://defold.com/assets/orthographic/) (tylko 2D) autorstwa Björna Ritzla. +- [Defold Rendy](https://defold.com/assets/defold-rendy/) (2D i 3D) autorstwa Klaytona Kowalskiego. diff --git a/docs/pl/manuals/editor-scripts.md b/docs/pl/manuals/editor-scripts.md index 162e911b..6e7b83c4 100644 --- a/docs/pl/manuals/editor-scripts.md +++ b/docs/pl/manuals/editor-scripts.md @@ -1,67 +1,93 @@ --- -title: Skrypty Edytora -brief: Ta instrukcja wyjaśnia, jak rozszerzać Edytor za pomocą Lua. +title: Skrypty edytora +brief: Ta instrukcja wyjaśnia, jak rozszerzać edytor Defold przy użyciu Lua. --- -# Skrypty Edytora +# Skrypty edytora -Możesz tworzyć niestandardowe pozycje menu oraz rozszerzać cyklu życia Edytora, używając plików Lua o specjalnym rozszerzeniu: `.editor_script`. Dzięki temu systemowi możesz dostosować dowolnie Edytor, aby zwiększyć swoją wydajność w procesie tworzenia gier. +Możesz tworzyć własne polecenia menu i haki cyklu życia edytora przy użyciu plików Lua ze specjalnym rozszerzeniem `.editor_script`. Dzięki temu mechanizmowi da się dostosować edytor tak, aby usprawnić własny workflow. -## Uruchamianie skryptów Edytora +## Środowisko uruchomieniowe skryptów edytora -Skrypty Edytora (editor scripts) działają wewnątrz Edytora, w maszynie wirtualnej Lua emulowanej przez maszynę wirtualną Java. Wszystkie skrypty współdzielą to samo środowisko, co oznacza, że mogą ze sobą współdziałać. Możesz wymagać (require) modułów Lua, tak samo jak w przypadku plików `.script`, ale wersja Lua uruchamiana wewnątrz Edytora jest inna, więc upewnij się, że twój współdzielony kod jest zgodny. Edytor używa wersji Lua 5.2.x, a dokładniej [silnika luaj](https://github.com/luaj/luaj), który jest obecnie jedynym dostępnym rozwiązaniem do uruchamiania Lua w JVM. Oprócz tego istnieją pewne ograniczenia: -- brak pakietów `debug` i `coroutine`; -- brak funkcji `os.execute` — zapewniamy bardziej przyjazny i bezpieczny sposób wykonywania skryptów powłoki (shell scripts) w sekcji "akcje" - [actions](#actions); -- brak funkcji `os.tmpname` i `io.tmpfile` — obecnie skrypty Edytora mają dostęp tylko do plików wewnątrz katalogu projektu; -- obecnie brak funkcji `os.rename`, choć zamierzamy ją dodać; -- brak funkcji `os.exit` i `os.setlocale`. +Skrypty edytora działają wewnątrz edytora, w maszynie wirtualnej Lua emulowanej przez JVM. Wszystkie skrypty współdzielą jedno środowisko, więc mogą ze sobą współpracować. Możesz używać modułów Lua przez `require()`, podobnie jak w plikach `.script`, ale wersja Lua uruchamiana w edytorze jest inna, dlatego współdzielony kod musi być z nią zgodny. Edytor używa Lua 5.2.x, a dokładniej środowiska [luaj](https://github.com/luaj/luaj), które obecnie jest jedynym sensownym sposobem uruchamiania Lua na JVM. Poza tym obowiązuje kilka ograniczeń: -Wszystkie rozszerzenia Edytora zdefiniowane w skryptach Edytora są ładowane podczas otwierania projektu. Podczas pobierania bibliotek rozszerzenia są ponownie ładowane, ponieważ w bibliotekach, od których zależysz, mogą znajdować się nowe skrypty Edytora. Podczas tego ponownego ładowania nie są wykrywane żadne zmiany w twoich własnych skryptach Edytora, ponieważ mogłeś być w trakcie ich zmian. Aby również je ponownie załadować, musisz uruchomić komendę Project → Reload Editor Scripts (Przeładuj skrypty Edytora). +- nie ma pakietu `debug`; +- nie ma `os.execute`, ale dostępna jest podobna funkcja `editor.execute()`; +- nie ma `os.tmpname` ani `io.tmpfile` — obecnie skrypty edytora mogą uzyskiwać dostęp tylko do plików wewnątrz katalogu projektu; +- obecnie nie ma `os.rename`, choć planujemy je dodać; +- nie ma `os.exit` ani `os.setlocale`; +- w kontekstach, w których edytor potrzebuje natychmiastowej odpowiedzi od skryptu, nie wolno używać niektórych długo działających funkcji; szczegóły znajdziesz w sekcji [Execution modes](#execution-modes). -## Anatomia skryptu `.editor_script` +Wszystkie rozszerzenia edytora zdefiniowane w skryptach edytora są ładowane podczas otwierania projektu. Gdy pobierasz biblioteki, rozszerzenia są przeładowywane, ponieważ w zależnościach mogą pojawić się nowe skrypty edytora. Podczas takiego przeładowania zmiany w twoich własnych skryptach nie są wykrywane, bo możesz być akurat w trakcie ich edycji. Aby przeładować także je, uruchom polecenie **Project → Reload Editor Scripts**. + +## Anatomia pliku `.editor_script` + +Każdy skrypt edytora powinien zwracać moduł, na przykład: -Każdy skrypt Edytora powinien zwracać moduł, na przykład: ```lua local M = {} function M.get_commands() - -- TODO - define editor commands + -- TODO - zdefiniuj polecenia edytora end function M.get_language_servers() - -- TODO - define language servers + -- TODO - zdefiniuj serwery językowe +end + +function M.get_prefs_schema() + -- TODO - zdefiniuj preferencje end return M ``` -Edytor zbiera wszystkie skrypty Edytora zdefiniowane w projekcie i bibliotekach, ładuje je do pojedynczej maszyny Lua i wywołuje je w odpowiednich momentach (więcej na ten temat w sekcjach "komendy": [commands](#commands) i "haki cyklu życia": [lifecycle hooks](#lifecycle-hooks)). - -## Edytor API - -Możesz komunikować się z Edytorem za pomocą pakietu `editor`, który definiuje to API: - -- `editor.platform` — string oznaczający platformę: `"x86_64-win32"` dla systemu Windows, `"x86_64-macos"` dla macOS lub `"x86_64-linux"` dla systemu Linux. -- `editor.version` — string - nazwa wersji Defold, na przykład `"1.4.8"`. -- `editor.engine_sha1` — string - SHA1 silnika Defold. -- `editor.editor_sha1` — string - SHA1 Edytora Defold. -- `editor.get(node_id, property)` — pobierz wartość węzła (node) w Edytorze. Węzły w kontekście Edytora Defold to różne elementy, takie jak pliki skryptów, pliki kolekcji, obiekty gry w kolekcjach, pliki JSON wczytywane jako zasoby itp. `"node_id"` to userdata przekazywane do Skryptu Edytora przez sam Edytor. Możesz również podać ścieżkę zasobu zamiast identyfikatora węzła, na przykład `"/main/game.script"`. `"property"` to string. Obecnie obsługiwane są tylko te właściwości: - - `"path"` — ścieżka pliku od katalogu projektu dla zasobów — elementów, które istnieją jako pliki. Przykład zwracanej wartości: `"/main/game.script"` - - `"text"` — treść tekstowa zasobu edytowalna jako tekst (na przykład pliki skryptów lub pliki JSON). Przykład zwracanej wartości: `"function init(self)\nend"`. Należy zauważyć, że to nie jest to samo co odczytywanie pliku za pomocą `io.open()`, ponieważ możesz edytować plik bez zapisywania go, a te edycje są dostępne tylko podczas dostępu do właściwości `"text"`. - - niektóre właściwości wyświetlane w widoku Properties (Właściwości), gdy coś jest zaznaczone w panelu Outline. Obsługiwane są następujące typy właściwości: - - string - ciągi znaków - - boolean - zmienne logiczne - - number - liczby - - vec2/vec3/vec4 - wektory - - resource - zasoby - -Należy zauważyć, że niektóre z tych właściwości mogą być tylko do odczytu (read-only), a niektóre mogą być niedostępne w różnych kontekstach, więc przed ich odczytaniem powinieneś użyć `editor.can_get`, a przed ich zmianą - `editor.can_set`, które zwrócą informację, czy daną właściwość można odczytać i czy można zmienić i zapisać. Najedź wskaźnikiem myszki na właściwość w panelu Properties (właściwości), żeby zobaczyć tooltop z informacją o jej nazwie w skryptach Edytora. Możesz ustawić właściwości zasobów jako `nil` używając pustej wartości `""`. -- `editor.can_get(node_id, property)` — sprawdź czy można odczytać daną właściwość w danym kontekście. Jeśli tak (true), to `editor.get()` nie zwróci błędu. -- `editor.can_set(node_id, property)` — sprawdź czy można zmienić i zapisać daną właściwość w danym kontekście. Jeśli tak (true), to akcja `"set"` na tej właściwości nie zwróci błędu. - -## Komendy - -Jeśli Skrypt Edytora definiuje funckję `get_commands`, to będzie one wywołana podczas przeładowania rozszerzenia i zwróci komendy możliwe do użycia w Edytorze w pasku menu lub w kontekstowym menu w panelach Assets i Outline. Przykład: +Edytor zbiera wszystkie skrypty edytora zdefiniowane w projekcie i bibliotekach, ładuje je do jednej maszyny Lua i wywołuje wtedy, gdy są potrzebne. Więcej informacji znajdziesz w sekcjach [Commands](#commands) i [Lifecycle hooks](#lifecycle-hooks). + +## API edytora + +Z edytorem możesz komunikować się przez pakiet `editor`, który udostępnia następujące API: + +- `editor.platform` — łańcuch znaków określający platformę: `"x86_64-win32"` dla Windows, `"x86_64-macos"` dla macOS albo `"x86_64-linux"` dla Linux; +- `editor.version` — łańcuch znaków z nazwą wersji Defold, na przykład `"1.4.8"`; +- `editor.engine_sha1` — łańcuch znaków z SHA1 silnika Defold; +- `editor.editor_sha1` — łańcuch znaków z SHA1 edytora Defold; +- `editor.get(node_id, property)` — odczytuje wartość wybranego węzła wewnątrz edytora. Węzły w edytorze to różne byty, na przykład pliki skryptów lub kolekcji, obiekty gry wewnątrz kolekcji, pliki JSON wczytane jako zasoby itd. `node_id` to wartość userdata przekazywana skryptowi przez edytor. Zamiast `node_id` możesz też podać ścieżkę zasobu, na przykład `"/main/game.script"`. `property` to łańcuch znaków. Obecnie obsługiwane są między innymi: + - `"path"` — ścieżka zasobu względem katalogu projektu dla zasobów istniejących jako pliki lub katalogi. Przykładowa wartość: `"/main/game.script"`; + - `"children"` — lista ścieżek zasobów potomnych dla zasobów będących katalogami; + - `"text"` — tekstowa zawartość zasobu edytowalnego jako tekst, na przykład plików skryptów lub JSON. Przykładowa wartość: `"function init(self)\nend"`. To nie jest to samo co odczyt pliku przez `io.open()`, ponieważ plik może być zmieniony, ale jeszcze niezapisany, a takie zmiany są dostępne tylko przez właściwość `"text"`; + - dla atlasów: `images` (lista węzłów obrazów atlasu) oraz `animations` (lista węzłów animacji); + - dla animacji atlasu: `images`; + - dla tilemap: `layers` (lista węzłów warstw tilemapy); + - dla warstw tilemapy: `tiles` (nieograniczona dwuwymiarowa siatka kafelków), więcej w `tilemap.tiles.*`; + - dla `particlefx`: `emitters` (lista węzłów emiterów) i `modifiers` (lista węzłów modyfikatorów); + - dla emiterów `particlefx`: `modifiers`; + - dla obiektów kolizji: `shapes` (lista węzłów kształtów kolizji); + - dla plików GUI: `layers` (lista węzłów warstw); + - część właściwości widocznych w panelu `Properties`, gdy w `Outline` coś jest zaznaczone. Obecnie obsługiwane są typy: + - `strings` + - `booleans` + - `numbers` + - `vec2`/`vec3`/`vec4` + - `resources` + - `curves` + Niektóre z tych właściwości mogą być tylko do odczytu albo niedostępne w danym kontekście, dlatego przed odczytem użyj `editor.can_get`, a przed zapisem `editor.can_set`. Po najechaniu kursorem na nazwę właściwości w panelu `Properties` zobaczysz podpowiedź z nazwą używaną w skryptach edytora. Właściwości zasobów możesz ustawić na `nil`, przekazując `""`. +- `editor.can_get(node_id, property)` — sprawdza, czy odczyt danej właściwości przez `editor.get()` nie zakończy się błędem; +- `editor.can_set(node_id, property)` — sprawdza, czy krok transakcji `editor.tx.set()` dla tej właściwości nie zakończy się błędem; +- `editor.create_directory(resource_path)` — tworzy katalog, jeśli nie istnieje, wraz z brakującymi katalogami nadrzędnymi; +- `editor.create_resources(resources)` — tworzy co najmniej jeden zasób, z szablonów albo z własną zawartością; +- `editor.delete_directory(resource_path)` — usuwa katalog, jeśli istnieje, wraz z istniejącymi podkatalogami i plikami; +- `editor.execute(cmd, [...args], [options])` — uruchamia polecenie powłoki, opcjonalnie przechwytując jego wynik; +- `editor.save()` — zapisuje wszystkie niezapisane zmiany na dysk; +- `editor.transact(txs)` — modyfikuje stan edytora w pamięci przy użyciu jednego lub wielu kroków transakcji utworzonych przez `editor.tx.*`; +- `editor.ui.*` — funkcje związane z interfejsem; szczegóły w [instrukcji UI](/manuals/editor-scripts-ui); +- `editor.prefs.*` — funkcje do pracy z preferencjami edytora; szczegóły w sekcji [Preferences](#preferences). + +Pełne API edytora znajdziesz [tutaj](https://defold.com/ref/alpha/editor/). + +## Commands + +Jeśli moduł skryptu edytora definiuje funkcję `get_commands`, zostanie ona wywołana podczas przeładowywania rozszerzeń, a zwrócone polecenia będą dostępne w pasku menu edytora albo w menu kontekstowych paneli `Assets` i `Outline`. Przykład: ```lua local M = {} @@ -80,14 +106,9 @@ function M.get_commands() end, run = function(opts) local text = editor.get(opts.selection, "text") - return { - { - action = "set", - node_id = opts.selection, - property = "text", - value = strip_comments(text) - } - } + editor.transact({ + editor.tx.set(opts.selection, "text", strip_comments(text)) + }) end }, { @@ -101,12 +122,7 @@ function M.get_commands() end, run = function(opts) local path = editor.get(opts.selection, "path") - return { - { - action = "shell", - command = {"./scripts/minify-json.sh", path:sub(2)} - } - } + editor.execute("./scripts/minify-json.sh", path:sub(2)) end } } @@ -115,116 +131,471 @@ end return M ``` -Edytor oczekuje, że funkcja `get_commands()` zwróci tablicę tablic, z których każda opisuje osobne polecenie. Opis polecenia składa się z: +Edytor oczekuje, że `get_commands()` zwróci tablicę tabel, z których każda opisuje jedno polecenie. Opis polecenia składa się z: -- `label` (wymagane) — tekst, który zostanie wyświetlony użytkownikowi jako pozycja w menu. -- `locations` (wymagane) — tablica zawierająca jedno z poniższych: `"Edit"`, `"View"`, `"Assets"` lub `"Outline"` - określa, w jakim miejscu Edytora menu powinno być dostępne. `"Edit"` i `"View"` oznaczają pasek menu na górze, `"Assets"` oznacza menu kontekstowe w panelu `"Assets"`, a `"Outline"` oznacza menu kontekstowe w panelu `"Outline"`. -- `query` — sposób, w jaki polecenie pyta Edytor o odpowiednie informacje i definiuje, na jakich danych operuje. Dla każdego klucza w tabeli `query` istnieje odpowiadający klucz w tabeli `opts`, który jest przekazywany jako argument do funkcji `active` i `run`. Obsługiwane klucze to: - - `selection` — oznacza, że polecenie jest ważne, gdy coś w Edytorze jest zaznaczone, i działa na tym zaznaczeniu. - - `type` — określa typ zaznaczonych węzłów, na które polecenie jest zainteresowane. Obecnie dozwolone są następujące rodzaje: - - `"resource"` — w panelach `"Assets"` i `"Outline"` oznacza zaznaczony element, który ma odpowiadający plik. W pasku menu (`Edit` lub `View`), `"resource"` to aktualnie otwarty plik; - - `"outline"` — coś, co może być wyświetlane w `"Outline"`. W `"Outline"` to zaznaczony element, w pasku menu to aktualnie otwarty plik; - - `cardinality` — określa, ile zaznaczonych elementów powinno być. Jeśli jest to `"one"`, zaznaczenie przekazywane do funkcji obsługującej polecenie będzie zawierać tylko jeden identyfikator węzła. Jeśli jest to `"many"`, przekazywana tablica będzie zawierać jeden lub więcej identyfikatorów węzła. -- `active` - funkcja wywoływana w celu sprawdzenia, czy polecenie jest aktywne, powinna zwracać wartość logiczną. Jeśli w locations zawarte są `"Assets"` lub `"Outline"`, funkcja `active` zostanie wywołana podczas wyświetlania menu kontekstowego. Jeśli w `locations` zawarte są `"Edit"` lub `"View"`, funkcja `active` zostanie wywołana przy każdej interakcji użytkownika, takiej jak pisanie na klawiaturze lub klikanie myszą, dlatego upewnij się, że funkcja `active` działa stosunkowo szybko. -- `run` - funkcja wywoływana, gdy użytkownik wybierze pozycję z menu, i powinna zwrócić tablicę akcji - [actions](#actions). +- `label` (wymagane) — tekst pozycji menu widoczny dla użytkownika; +- `locations` (wymagane) — tablica zawierająca `"Edit"`, `"View"`, `"Project"`, `"Debug"`, `"Assets"`, `"Bundle"`, `"Scene"` albo `"Outline"`, określająca, gdzie polecenie ma być dostępne. `"Edit"`, `"View"`, `"Project"` i `"Debug"` oznaczają górny pasek menu, `"Assets"` oznacza menu kontekstowe panelu `Assets`, `"Outline"` oznacza menu kontekstowe panelu `Outline`, a `"Bundle"` oznacza podmenu **Project → Bundle**; +- `query` — sposób, w jaki polecenie prosi edytor o potrzebne dane i definiuje, na czym operuje. Dla każdego klucza w tabeli `query` pojawi się odpowiadający klucz w tabeli `opts`, przekazywanej do funkcji `active` i `run`. Obsługiwane klucze: + - `selection` oznacza, że polecenie działa na aktualnym zaznaczeniu. + - `type` określa typ zaznaczonych węzłów. Obecnie dozwolone są: + - `"resource"` — w `Assets` i `Outline` oznacza zaznaczony element mający odpowiadający mu plik. W pasku menu (`Edit` lub `View`) oznacza aktualnie otwarty plik; + - `"outline"` — coś, co może być pokazane w `Outline`. W `Outline` to zaznaczony element, w pasku menu — aktualnie otwarty plik; + - `"scene"` — coś, co da się wyrenderować w `Scene`; + - `cardinality` określa liczbę zaznaczonych elementów. Dla `"one"` callback otrzyma pojedynczy `node_id`, a dla `"many"` — tablicę co najmniej jednego `node_id`; + - `argument` — argument polecenia. Obecnie tylko polecenia z lokalizacją `"Bundle"` otrzymują argument: `true`, gdy użytkownik jawnie wybrał bundlowanie, i `false` przy rebundle; +- `id` — identyfikator polecenia, używany na przykład do zapamiętywania ostatnio użytego polecenia bundlowania w `prefs`; +- `active` — callback sprawdzający, czy polecenie ma być aktywne. Powinien zwracać wartość logiczną. Jeśli `locations` zawiera `"Assets"`, `"Scene"` albo `"Outline"`, `active` zostanie wywołane przy otwieraniu menu kontekstowego. Jeśli `locations` zawiera `"Edit"` albo `"View"`, `active` będzie uruchamiane przy każdej interakcji użytkownika, na przykład podczas pisania na klawiaturze lub kliknięć myszą, więc musi działać stosunkowo szybko; +- `run` — callback wykonywany po wybraniu polecenia przez użytkownika. -## Actions +### Używanie poleceń do zmiany stanu edytora w pamięci -Action (akcja) to tabela opisująca, co Edytor powinien zrobić. Każda akcja zawiera klucz `action`. Akcje dzielą się na dwa rodzaje: możliwe do cofnięcia (undoable) i niemożliwe do cofnięcia (non-undoable). +Wewnątrz `run` możesz odczytywać i zmieniać stan edytora zapisany w pamięci. Odczyt odbywa się przez `editor.get()`, co pozwala pobierać aktualny stan plików i zaznaczenia. Możesz pobrać właściwość `"text"` plików skryptów oraz wybrane właściwości widoczne w panelu `Properties` — najedź kursorem na nazwę właściwości, aby zobaczyć, jak nazywa się w skryptach edytora. Zmiany w stanie edytora wykonuje się przez `editor.transact()`, gdzie grupujesz jedną lub więcej modyfikacji w pojedynczy krok z możliwością cofnięcia. Na przykład polecenie resetujące transformację obiektu gry może wyglądać tak: -### Akcje możliwe do cofnięcia +```lua +{ + label = "Reset transform", + locations = {"Outline"}, + query = {selection = {type = "outline", cardinality = "one"}}, + active = function(opts) + local node = opts.selection + return editor.can_set(node, "position") + and editor.can_set(node, "rotation") + and editor.can_set(node, "scale") + end, + run = function(opts) + local node = opts.selection + editor.transact({ + editor.tx.set(node, "position", {0, 0, 0}), + editor.tx.set(node, "rotation", {0, 0, 0}), + editor.tx.set(node, "scale", {1, 1, 1}) + }) + end +} +``` -Undoable action - możliwa do cofnięcia akcja może zostać cofnięta po jej wykonaniu (Undo or Ctrl + Z). Jeśli polecenie zwraca wiele akcji możliwych do cofnięcia, są one wykonywane razem i cofane razem. Należy używać akcji możliwych do cofnięcia, jeśli to możliwe. Ich wadą są większe ograniczenia. +#### Edycja atlasów -Istniejące działania możliwe do cofnięcia to: +Poza odczytem i zapisem właściwości atlasu możesz też odczytywać i modyfikować obrazy oraz animacje atlasu. Atlas definiuje właściwości listowe `images` i `animations`, a animacje mają dodatkowo listową właściwość `images`. Z tymi właściwościami można używać kroków transakcji `editor.tx.add`, `editor.tx.remove` i `editor.tx.clear`. -- `"set"` — ustawienie właściwości węzła w Edytorze na określoną wartość. Przykład: - ```lua - { - action = "set", - node_id = opts.selection, - property = "text", - value = "current time is " .. os.date() - } - ``` -Akcja `"set"` wymaga podania tych parametrów: - - `node_id` — identyfikator węzła jako userdata. Alternatywnie, można użyć ścieżki zasobu zamiast identyfikatora węzła otrzymanego od Edytora, na przykład `"/main/game.script"`; - - `property` — właściwość węzła do ustawienia, obecnie obsługiwane jes tylko `"text"`; - - `value` — nowa wartość właściwości. Dla właściwości `"text"` powinno to być łańcuchem znaków (string). +Na przykład, aby dodać obraz do atlasu, uruchom w `run` takie polecenie: -### Akcje niemożliwe do cofnięcia +```lua +editor.transact({ + editor.tx.add("/main.atlas", "images", {image="/assets/hero.png"}) +}) +``` -Akcje możliwe do cofnięcia czyszczą historię cofnięć (undo), więc z poziomu Edytora nie można ich cofnąć i jeśli użytkownik chce to zrobić, musi użyć innych środków, np. systemów kontroli wersji. +Aby zbudować zbiór wszystkich obrazów w atlasie: -Istniejące działania niemożliwe do cofnięcia to: -- `"shell"` — wykonanie skryptu powłoki. Przykład: - ```lua - { - action = "shell", - command = { - "./scripts/minify-json.sh", - editor.get(opts.selection, "path"):sub(2) -- trim leading "/" - } - } - ``` -Działanie `"shell"` wymaga parametru `command`, który jest tablicą polecenia, oraz jego argumentów. Główna różnica w porównaniu do `os.execute` polega na tym, że jest to potencjalnie niebezpieczna operacja, dlatego Edytor wyświetli okno dialogowe z pytaniem do użytkownika czy na pewno chce wywołać daną komendę. Edytor zapamięta, jeśli użytkownik już wyraził zgodę na wykonanie takiej komendy. +```lua +local all_images = {} ---@type table +-- najpierw zbierz "gołe" obrazy +local image_nodes = editor.get("/main.atlas", "images") +for i = 1, #image_nodes do + all_images[editor.get(image_nodes[i], "image")] = true +end +-- następnie zbierz obrazy używane w animacjach +local animation_nodes = editor.get("/main.atlas", "animations") +for i = 1, #animation_nodes do + local animation_image_nodes = editor.get(animation_nodes[i], "images") + for j = 1, #animation_image_nodes do + all_images[editor.get(animation_image_nodes[j], "image")] = true + end +end +pprint(all_images) +-- { +-- ["/assets/hero.png"] = true, +-- ["/assets/enemy.png"] = true, +-- }} +``` -### Łączenie akcji i efekty uboczne +Aby zastąpić wszystkie animacje w atlasie: -Możesz łączyć akcje możliwe do cofnięcia (undoable) i akcje niemożliwe do cofnięcia (non-undoable). Akcje są wykonywane sekwencyjnie, dlatego w zależności od kolejności działań możesz stracić możliwość cofania części tego polecenia. +```lua +editor.transact({ + editor.tx.clear("/main.atlas", "animations"), + editor.tx.add("/main.atlas", "animations", { + id = "hero_run", + images = { + {image = "/assets/hero_run_1.png"}, + {image = "/assets/hero_run_2.png"}, + {image = "/assets/hero_run_3.png"}, + {image = "/assets/hero_run_4.png"} + } + }) +}) +``` + +#### Edycja tilesource -Zamiast zwracać akcje z funkcji, które ich oczekują, możesz po prostu czytać i zapisywać dane bezpośrednio do plików, korzystając z funkcji `io.open()`. Spowoduje to ponowne załadowanie zasobów, co wyczyści historię cofania (undo history). +Poza zwykłymi właściwościami z `Outline`, tilesource definiuje jeszcze: -## Haki cyklu życia (Lifecycle Hooks) +- `animations` — listę węzłów animacji tilesource; +- `collision_groups` — listę węzłów grup kolizji tilesource; +- `tile_collision_groups` — tabelę przypisań grup kolizji do kafelków tilesource. -Istnieje jeden, specjalnie traktowany plik Skryptu Edytora: `hooks.editor_script`, znajdujący się w głównym katalogu twojego projektu, w tym samym katalogu co `game.project`. Tylko ten plik Skryptu Edytora otrzyma zdarzenia cyklu życia od Edytora. Oto przykład takiego pliku: +Przykładowa konfiguracja tilesource: ```lua -local M = {} +local tilesource = "/game/world.tilesource" +editor.transact({ + editor.tx.add(tilesource, "animations", {id = "idle", start_tile = 1, end_tile = 1}), + editor.tx.add(tilesource, "animations", {id = "walk", start_tile = 2, end_tile = 6, fps = 10}), + editor.tx.add(tilesource, "collision_groups", {id = "player"}), + editor.tx.add(tilesource, "collision_groups", {id = "obstacle"}), + editor.tx.set(tilesource, "tile_collision_groups", { + [1] = "player", + [7] = "obstacle", + [8] = "obstacle" + }) +}) +``` -function M.on_build_started(opts) - local file = io.open("assets/build.json", "w") - file:write("{\"build_time\": \"".. os.date() .."\"}") - file:close() +#### Edycja tilemap + +Tilemapy definiują właściwość `layers`, która jest listą węzłów warstw. Każda warstwa ma z kolei właściwość `tiles`, przechowującą nieograniczoną dwuwymiarową siatkę kafelków. To zachowuje się inaczej niż w silniku: kafelki nie mają ograniczonych granic i można je dodawać w dowolnym miejscu, także na ujemnych współrzędnych. Do pracy z kafelkami API skryptów edytora udostępnia moduł `tilemap.tiles` z funkcjami: + +- `tilemap.tiles.new()` — tworzy pustą strukturę danych dla nieograniczonej siatki kafelków; +- `tilemap.tiles.get_tile(tiles, x, y)` — zwraca indeks kafelka na podanych współrzędnych; +- `tilemap.tiles.get_info(tiles, x, y)` — zwraca pełne informacje o kafelku w danym punkcie (kształt danych jest zgodny z `tilemap.get_tile_info` w silniku); +- `tilemap.tiles.iterator(tiles)` — tworzy iterator po wszystkich kafelkach tilemapy; +- `tilemap.tiles.clear(tiles)` — usuwa wszystkie kafelki; +- `tilemap.tiles.set(tiles, x, y, tile_or_info)` — ustawia kafelek w podanym miejscu; +- `tilemap.tiles.remove(tiles, x, y)` — usuwa kafelek z podanych współrzędnych. + +Przykład wypisania całej zawartości tilemapy: + +```lua +local layers = editor.get("/level.tilemap", "layers") +for i = 1, #layers do + local layer = layers[i] + local id = editor.get(layer, "id") + local tiles = editor.get(layer, "tiles") + print("layer " .. id .. ": {") + for x, y, tile in tilemap.tiles.iterator(tiles) do + print(" [" .. x .. ", " .. y .. "] = " .. tile) + end + print("}") end +``` -return M +Przykład dodania nowej warstwy z kafelkami: + +```lua +local tiles = tilemap.tiles.new() +tilemap.tiles.set(tiles, 1, 1, 2) +editor.transact({ + editor.tx.add("/level.tilemap", "layers", { + id = "new_layer", + tiles = tiles + }) +}) ``` -Zdecydowaliśmy się ograniczyć haki cyklu życia do jednego pliku Skryptu Edytora, ponieważ kolejność wykonywania haków budowania (build hooks) jest ważniejsza niż łatwość dodawania kolejnego kroku buildu. Polecenia są niezależne od siebie, więc nie ma znaczenia, w jakiej kolejności są wyświetlane w menu. W końcu to użytkownik wykonuje konkretne polecenie, które wybrał. Gdyby można było określać haki cyklu życia w różnych plikach Skryptu Edytora, stworzyłoby to problem: w jakiej kolejności mają się wykonywać haki? Chcesz prawdopodobnie utworzyć sumy kontrolne zawartości po jej skompresowaniu... Dlatego posiadanie jednego pliku, który ustala kolejność kroków buildu, wywołując każdą funkcję kroku, jest sposobem na rozwiązanie tego problemu. +#### Edycja particlefx -Każdy hak cyklu życia może zwracać akcje lub zapisywać pliki w katalogu projektu. +`particlefx` możesz edytować przez właściwości `modifiers` i `emitters`. Na przykład dodanie emitera kołowego z modyfikatorem przyspieszenia wygląda tak: -Istniejące haki cyklu życia, które plik `hooks.editor_script` może określić: -- `on_build_started(opts)` — wykonywane, gdy gra jest budowana w celu uruchomienia jej lokalnie lub na zdalnym, docelowym urządzeniu, używając opcji `"Project Build"` lub `"Debug Start"`. Twoje zmiany, czy to zwracane akcje czy zaktualizowane zawartości pliku, pojawią się w zbudowanej grze. Wyrzucenie błędu z tego haka spowoduje przerwanie budowy. `opts` to tabela zawierająca obecnie następujący klucz: - - `platform` — łańcuch w formacie `%arch%-%os%`, opisujący platformę, dla której budowana jest gra, zawsze taki sam jak `editor.platform`. -- `on_build_finished(opts)` — wykonywane, gdy budowa zostanie zakończona, niezależnie od tego, czy zakończyła się sukcesem czy nie. `opts` w tym przypadku to tabela zawierająca następujące klucze: - - `platform` — to samo, co w `on_build_started`. - - `success` — czy budowa zakończyła się sukcesem, true lub false. -- `on_bundle_started(opts)` — wykonywane, gdy tworzysz paczkę z grą lub budujesz wersję HTML5 gry. Podobnie jak `on_build_started`, zmiany wywołane przez ten hak pojawią się w paczce, a błędy spowodują przerwanie procesu pakowania (bundle). `opts` zawiera tutaj następujące klucze: - - `output_directory — ścieżka do katalogu wyjściowego paczki, na przykład `"/path/to/project/build/default/__htmlLaunchDir"` - - `platform` — platforma, dla której paczka jest tworzona. Zobacz listę możliwych wartości platform w podręczniku Boba (narzędzia do budowania i pakowania). - - `variant` — wariant paczki, `"debug"`, `"release"` lub `"headless"`. -- `on_bundle_finished(opts)` — wykonywane, gdy budowanie paczki (bundle) zostanie ukończone, niezależnie od tego, czy zakończyło się sukcesem. `opts` w tym przypadku to tabela zawierająca te same dane co `opts` w `on_bundle_started`, oraz dodatkowo klucz `success`, który wskazuje, czy budowa zakończyła się sukcesem. - - `on_target_launched(opts)` — wykonywane, gdy użytkownik uruchomił grę i uruchomienie zakończyło się sukcesem. `opts` zawiera klucz `url` wskazujący na uruchomioną usługę silnika, na przykład `"http://127.0.0.1:35405"`. - - `on_target_terminated(opts)` — wykonywane, gdy uruchomiona gra zostaje zamknięta. `opts` ma te same klucze co `on_target_launched`. +```lua +editor.transact({ + editor.tx.add("/fire.particlefx", "emitters", { + type = "emitter-type-circle", + modifiers = { + {type = "modifier-type-acceleration"} + } + }) +}) +``` -Należy zauważyć, że haki cyklu życia są obecnie funkcją dostępną tylko w Edytorze i nie są wykonywane przez Boba podczas pakowania z wiersza poleceń. +Wiele właściwości `particlefx` to krzywe albo krzywe ze spreadem (czyli krzywa plus losowy rozrzut). Krzywe są reprezentowane jako tabela z niepustą listą `points`, gdzie każdy punkt jest tabelą z właściwościami: -## Skrypty Edytora w bibliotekach +- `x` — współrzędna x punktu; powinna zaczynać się od 0 i kończyć na 1; +- `y` — wartość punktu; +- `tx` (0 do 1) i `ty` (-1 do 1) — tangensy punktu. Dla kąta 80 stopni `tx` powinno być równe `math.cos(math.rad(80))`, a `ty` — `math.sin(math.rad(80))`. -Możesz publikować biblioteki dla użytku przez inne osoby, które zawierają polecenia, i zostaną one automatycznie wykryte przez Edytor. Haki cyklu życia nie mogą być jednak automatycznie wykrywane, ponieważ muszą być zdefiniowane w pliku znajdującym się w głównym katalogu projektu, a biblioteki wystawiają tylko podkatalogi. Ma to na celu umożliwienie większej kontroli nad procesem budowy: nadal możesz tworzyć haki cyklu życia jako proste funkcje w plikach `.lua`, więc użytkownicy twojej biblioteki mogą je zaimportować i używać w swoim pliku `hooks.editor_script`. +Krzywe ze spreadem mają dodatkowo właściwość liczbową `spread`. -Należy również zauważyć, że chociaż zależności są wyświetlane w widoku `"Assets"`, to nie istnieją one jako pliki (są wpisami w archiwum zip), więc obecnie nie ma łatwego sposobu na wykonanie skryptu powłoki dostarczonego jako zależności (biblioteki). Jeśli jest to absolutnie konieczne, będziesz musiał wydobyć dostarczone skrypty, pobierając ich tekst za pomocą `editor.get()` i zapisując go gdzieś za pomocą `file:write()`, na przykład w katalogu `build/editor-scripts/your-extension-name`. +Przykład ustawienia krzywej alpha czasu życia cząsteczki dla istniejącego emitera: -Prostszym sposobem na wydobycie niezbędnych plików jest wykorzystanie systemu wtyczek rozszerzeń natywnych (native extensions). Aby to zrobić, musisz utworzyć plik `ext.manifest` w katalogu twojej biblioteki, a następnie utworzyć katalog `plugins/bin/${platform}` w tym samym katalogu, w którym znajduje się plik `ext.manifest`. Pliki w tym katalogu zostaną automatycznie wydobyte do katalogu `/build/plugins/${extension-path}/plugins/bin/${platform}`, dzięki czemu twoje Skrypty Edytora mogą się do nich odnosić. +```lua +local emitter = editor.get("/fire.particlefx", "emitters")[1] +editor.transact({ + editor.tx.set(emitter, "particle_key_alpha", { points = { + {x = 0, y = 0, tx = 0.1, ty = 1}, -- startuj od 0 i szybko rośnij + {x = 0.2, y = 1, tx = 1, ty = 0}, -- osiągnij 1 po 20% czasu życia + {x = 1, y = 0, tx = 1, ty = 0} -- powoli opadaj do 0 + }}) +}) +``` + +Oczywiście można też użyć klucza `particle_key_alpha` bezpośrednio w tabeli podczas tworzenia emitera. Dodatkowo zamiast krzywej możesz podać pojedynczą liczbę reprezentującą krzywą statyczną. + +#### Edycja obiektów kolizji + +Poza domyślnymi właściwościami z `Outline` obiekty kolizji definiują listową właściwość `shapes`. Dodawanie nowych kształtów kolizji wygląda tak: + +```lua +editor.transact({ + editor.tx.add("/hero.collisionobject", "shapes", { + type = "shape-type-box" -- albo "shape-type-sphere", "shape-type-capsule" + }) +}) +``` -## Serwery językowy (language servers) +Właściwość `type` kształtu jest wymagana podczas tworzenia i nie można jej zmienić po dodaniu kształtu. Dostępne są trzy typy: -Edytor obsługuje niewielki podzbiór protokołu [Language Server Protocol](https://microsoft.github.io/language-server-protocol/). Chociaż zamierzamy rozwijać obsługę Edytora dla funkcji LSP w przyszłości, obecnie obsługuje on tylko wykrywanie diagnoz (lints) w edytowanych plikach. +- `shape-type-box` — kształt pudełkowy z właściwością `dimensions`; +- `shape-type-sphere` — kształt sferyczny z właściwością `diameter`; +- `shape-type-capsule` — kapsuła z właściwościami `diameter` i `height`. -Aby zdefiniować serwer językowy, musisz edytować funkcję `get_language_servers` w swoim Skrypcie Edytora, jak w poniższym przykładzie: +#### Edycja plików GUI +Poza właściwościami z `Outline` pliki GUI definiują: + +- `layers` — listę węzłów warstw GUI z możliwością zmiany kolejności; +- `materials` — listę węzłów materiałów. + +Warstwy GUI można edytować przez właściwość `layers`, na przykład: + +```lua +editor.transact({ + editor.tx.add("/main.gui", "layers", {name = "foreground"}), + editor.tx.add("/main.gui", "layers", {name = "background"}) +}) +``` + +Można też zmieniać kolejność warstw: + +```lua +local fg, bg = table.unpack(editor.get("/main.gui", "layers")) +editor.transact({ + editor.tx.reorder("/main.gui", "layers", {bg, fg}) +}) +``` + +Podobnie fonty, materiały, tekstury i `particlefx` są edytowane przez właściwości `fonts`, `materials`, `textures` i `particlefxs`: + +```lua +editor.transact({ + editor.tx.add("/main.gui", "fonts", {font = "/main.font"}), + editor.tx.add("/main.gui", "materials", {name = "shine", material = "/shine.material"}), + editor.tx.add("/main.gui", "particlefxs", {particlefx = "/confetti.material"}), + editor.tx.add("/main.gui", "textures", {texture = "/ui.atlas"}) +}) +``` + +Te właściwości nie obsługują zmiany kolejności. + +Na końcu możesz też edytować węzły GUI przez listową właściwość `nodes`, na przykład: + +```lua +editor.transact({ + editor.tx.add("/main.gui", "nodes", { + type = "gui-node-type-box", + position = {20, 20, 20} + }), + editor.tx.add("/main.gui", "nodes", { + type = "gui-node-type-template", + template = "/button.gui" + }), +}) +``` + +Wbudowane typy węzłów: + +- `gui-node-type-box` +- `gui-node-type-particlefx` +- `gui-node-type-pie` +- `gui-node-type-template` +- `gui-node-type-text` + +Jeśli korzystasz z rozszerzenia Spine, możesz też używać typu `gui-node-type-spine`. + +Jeżeli plik GUI definiuje layouty, możesz pobierać i ustawiać wartości z layoutów przez składnię `layout:property`, na przykład: + +```lua +local node = editor.get("/main.gui", "nodes")[1] + +-- ODCZYT: +local position = editor.get(node, "position") +pprint(position) -- {20, 20, 20} +local landscape_position = editor.get(node, "Landscape:position") +pprint(landscape_position) -- {20, 20, 20} + +-- ZAPIS: +editor.transact({ + editor.tx.set(node, "Landscape:position", {30, 30, 30}) +}) +pprint(editor.get(node, "Landscape:position")) -- {30, 30, 30} +``` + +Właściwości layoutów, które zostały ustawione, można przywracać do wartości domyślnych przez `editor.tx.reset`: + +```lua +print(editor.can_reset(node, "Landscape:position")) -- true +editor.transact({ + editor.tx.reset(node, "Landscape:position") +}) +``` + +Drzewa węzłów szablonu można odczytywać, ale nie można ich edytować — da się ustawiać tylko właściwości węzłów w drzewie szablonu: + +```lua +local template = editor.get("/main.gui", "nodes")[2] +print(editor.can_add(template, "nodes")) -- false +local node_in_template = editor.get(template, "nodes")[1] +editor.transact({ + editor.tx.set(node_in_template, "text", "Button text") +}) +print(editor.can_reset(node_in_template, "text")) -- true (nadpisuje wartość z szablonu) +``` + +#### Edycja obiektów gry + +Skrypty edytora potrafią edytować komponenty pliku obiektu gry. Komponenty występują w dwóch wariantach: referencyjne i osadzone. Komponenty referencyjne mają typ `component-reference` i działają jako odwołania do innych zasobów, pozwalając jedynie nadpisywać właściwości `go` zdefiniowane w skryptach. Komponenty osadzone mają typy takie jak `sprite`, `label` itd. i pozwalają edytować wszystkie właściwości właściwe dla danego typu komponentu, a także dodawać podkomponenty, na przykład kształty obiektów kolizji. Przykładowa konfiguracja obiektu gry: + +```lua +editor.transact({ + editor.tx.add("/npc.go", "components", { + type = "sprite", + id = "view" + }), + editor.tx.add("/npc.go", "components", { + type = "collisionobject", + id = "collision", + shapes = { + { + type = "shape-type-box", + dimensions = {32, 32, 32} + } + } + }), + editor.tx.add("/npc.go", "components", { + type = "component-reference", + path = "/npc.script", + id = "controller", + __hp = 100 -- ustaw właściwość go zdefiniowaną w skrypcie + }) +}) +``` + +#### Edycja kolekcji + +Skrypty edytora potrafią też edytować kolekcje. Możesz dodawać obiekty gry (osadzone albo referencyjne) oraz kolekcje referencyjne. Na przykład: + +```lua +local coll = "/char.collection" +editor.transact({ + editor.tx.add(coll, "children", { + -- osadzony obiekt gry + type = "go", + id = "root", + children = { + { + -- referencyjny obiekt gry + type = "go-reference", + path = "/char-view.go", + id = "view" + }, + { + -- referencyjna kolekcja + type = "collection-reference", + path = "/body-attachments.collection", + id = "attachments" + } + }, + -- osadzone obiekty gry mogą też zawierać komponenty + components = { + { + type = "collisionobject", + id = "collision", + shapes = { + {type = "shape-type-box", dimensions = {2.5, 2.5, 2.5}} + } + }, + { + type = "component-reference", + id = "controller", + path = "/char.script", + __hp = 100 -- ustaw właściwość go zdefiniowaną w skrypcie + } + } + }) +}) +``` + +Podobnie jak w edytorze, referencyjne kolekcje można dodawać tylko do korzenia edytowanej kolekcji, a obiekty gry można dodawać tylko do osadzonych albo referencyjnych obiektów gry, ale nie do referencyjnych kolekcji ani do obiektów gry wewnątrz takich kolekcji. + +### Używanie poleceń powłoki + +Wewnątrz `run` możesz zapisywać pliki przy użyciu modułu `io` i uruchamiać polecenia powłoki przez `editor.execute()`. Przy wykonywaniu poleceń możesz też przechwycić ich tekstowy wynik i użyć go dalej w kodzie. Jeśli na przykład chcesz dodać polecenie formatujące JSON przez globalnie zainstalowane [`jq`](https://jqlang.github.io/jq/), możesz napisać: + +```lua +{ + label = "Format JSON", + locations = {"Assets"}, + query = {selection = {type = "resource", cardinality = "one"}}, + action = function(opts) + local path = editor.get(opts.selection, "path") + return path:match(".json$") ~= nil + end, + run = function(opts) + local text = editor.get(opts.selection, "text") + local new_text = editor.execute("jq", "-n", "--argjson", "data", text, "$data", { + reload_resources = false, -- nie przeładowuj zasobów, bo jq nie zapisuje nic na dysku + out = "capture" -- zwróć tekstowy wynik zamiast braku wyniku + }) + editor.transact({ editor.tx.set(opts.selection, "text", new_text) }) + end +} +``` + +Ponieważ to polecenie uruchamia program powłoki tylko do odczytu i informuje o tym edytor przez `reload_resources = false`, akcję nadal da się cofnąć. + +::: sidenote +Jeśli chcesz dystrybuować skrypt edytora jako bibliotekę, możesz chcieć dołączyć binarny program dla platform edytora w ramach zależności. Więcej informacji znajdziesz w sekcji [Editor scripts in libraries](#editor-scripts-in-libraries). +::: + +## Lifecycle hooks + +Istnieje specjalnie traktowany plik skryptu edytora: `hooks.editor_script`, umieszczony w katalogu głównym projektu, obok pliku `game.project`. Tylko ten jeden skrypt edytora otrzymuje zdarzenia cyklu życia z edytora. Przykład: + +```lua +local M = {} + +function M.on_build_started(opts) + local file = io.open("assets/build.json", "w") + file:write('{"build_time": "' .. os.date() .. '"}') + file:close() +end + +return M +``` + +Zdecydowaliśmy się ograniczyć haki cyklu życia do jednego pliku skryptu edytora, ponieważ kolejność wykonywania kroków builda jest ważniejsza niż łatwość dodania kolejnego kroku. Polecenia są od siebie niezależne, więc kolejność wyświetlania ich w menu nie ma większego znaczenia — i tak użytkownik uruchamia konkretne wybrane polecenie. Gdyby haki builda dało się definiować w wielu skryptach edytora, pojawiłby się problem: w jakiej kolejności miałyby działać? Prawdopodobnie chcesz wyliczać sumy kontrolne dopiero po skompresowaniu zawartości. Jeden plik, który jawnie ustala kolejność kroków builda przez wywoływanie odpowiednich funkcji, rozwiązuje ten problem. + +Istniejące haki cyklu życia, które może zdefiniować `/hooks.editor_script`: + +- `on_build_started(opts)` — wywoływany, gdy gra jest budowana do uruchomienia lokalnie albo na zdalnym urządzeniu przez `Project Build` lub `Debug Start`. Twoje zmiany pojawią się w zbudowanej grze. Wyrzucenie błędu z tego haka przerwie build. `opts` to tabela z kluczami: + - `platform` — łańcuch w formacie `%arch%-%os%`, opisujący platformę docelową; obecnie zawsze taki sam jak `editor.platform`; +- `on_build_finished(opts)` — wywoływany po zakończeniu builda, niezależnie od wyniku. `opts` zawiera: + - `platform` — to samo co w `on_build_started`; + - `success` — `true` albo `false`, w zależności od tego, czy build zakończył się powodzeniem; +- `on_bundle_started(opts)` — wywoływany podczas tworzenia bundla albo budowania wersji HTML5. Podobnie jak `on_build_started`, zmiany wykonane przez ten hak trafią do bundla, a błędy przerwą proces. `opts` zawiera: + - `output_directory` — ścieżkę do katalogu z wynikowym bundlem, na przykład `"/path/to/project/build/default/__htmlLaunchDir"`; + - `platform` — platformę, dla której tworzony jest bundle. Listę możliwych wartości znajdziesz w [instrukcji Boba](/manuals/bob); + - `variant` — wariant bundla: `"debug"`, `"release"` albo `"headless"`; +- `on_bundle_finished(opts)` — wywoływany po zakończeniu bundlowania, niezależnie od wyniku. `opts` zawiera te same dane co `on_bundle_started`, plus klucz `success`; +- `on_target_launched(opts)` — wywoływany, gdy użytkownik uruchomi grę i start zakończy się sukcesem. `opts` zawiera klucz `url` wskazujący uruchomioną usługę silnika, na przykład `"http://127.0.0.1:35405"`; +- `on_target_terminated(opts)` — wywoływany po zamknięciu uruchomionej gry; otrzymuje taki sam `opts` jak `on_target_launched`. + +Pamiętaj, że haki cyklu życia są obecnie funkcją dostępną wyłącznie w edytorze i nie są wykonywane przez Boba podczas bundlowania z wiersza poleceń. + +## Language servers + +Edytor obsługuje podzbiór [Language Server Protocol](https://microsoft.github.io/language-server-protocol/). Docelowo chcemy rozszerzyć obsługę funkcji LSP, ale obecnie edytor potrafi tylko pokazywać diagnostykę (czyli linty) w edytowanych plikach oraz podpowiedzi. + +Aby zdefiniować serwer językowy, edytuj funkcję `get_language_servers` w swoim skrypcie edytora na przykład tak: ```lua function M.get_language_servers() @@ -244,10 +615,218 @@ function M.get_language_servers() end ``` -Edytor uruchomi serwer językowy, korzystając z określonej komendy, używając standardowego wejścia i wyjścia procesu serwera do komunikacji. +Edytor uruchomi serwer językowy przy użyciu zdefiniowanego `command`, komunikując się z procesem przez standardowe wejście i wyjście. + +Tabela definicji serwera językowego może zawierać: + +- `languages` (wymagane) — listę języków, którymi serwer jest zainteresowany; identyfikatory są zdefiniowane [tutaj](https://code.visualstudio.com/docs/languages/identifiers#_known-language-identifiers), ale działają też rozszerzenia plików; +- `command` (wymagane) — tablicę z poleceniem i argumentami; +- `watched_files` — tablicę tabel z kluczami `pattern` (glob), które będą wyzwalały powiadomienie serwera o [zmianie obserwowanych plików](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_didChangeWatchedFiles). + +## HTTP server + +Każda uruchomiona instancja edytora ma aktywny serwer HTTP. Można go rozszerzać przy użyciu skryptów edytora. Aby dodać własne endpointy, zdefiniuj funkcję `get_http_server_routes`, która zwróci dodatkowe trasy: + +```lua +print("My route: " .. http.server.url .. "/my-extension") + +function M.get_http_server_routes() + return { + http.server.route("/my-extension", "GET", function(request) + return http.server.response(200, "Hello world!") + end) + } +end +``` + +Po przeładowaniu skryptów edytora w konsoli zobaczysz komunikat podobny do `My route: http://0.0.0.0:12345/my-extension`. Po otwarciu tego linku w przeglądarce zobaczysz komunikat `"Hello world!"`. + +Argument `request` jest prostą tabelą Lua z informacjami o żądaniu. Zawiera między innymi klucze `path` (segment ścieżki URL zaczynający się od `/`), `method` (na przykład `"GET"`), `headers` (tabela z nazwami nagłówków zapisanymi małymi literami), a opcjonalnie także `query` oraz `body`, jeśli dana trasa definiuje sposób interpretacji body. Na przykład endpoint przyjmujący body w formacie JSON definiuje się z konwerterem `"json"`: + +```lua +http.server.route("/my-extension/echo-request", "POST", "json", function(request) + return http.server.json_response(request) +end) +``` + +Taki endpoint możesz przetestować w terminalu przez `curl` i `jq`: + +```sh +curl 'http://0.0.0.0:12345/my-extension/echo-request?q=1' -X POST --data '{"input": "json"}' | jq +{ + "path": "/my-extension/echo-request", + "method": "POST", + "query": "q=1", + "headers": { + "host": "0.0.0.0:12345", + "content-type": "application/x-www-form-urlencoded", + "accept": "*/*", + "user-agent": "curl/8.7.1", + "content-length": "17" + }, + "body": { + "input": "json" + } +} +``` + +Ścieżka trasy obsługuje wzorce, które można wyłuskać z `request.path` i przekazać do handlera jako część obiektu `request`, na przykład: + +```lua +http.server.route("/my-extension/setting/{category}.{key}", function(request) + return http.server.response(200, tostring(editor.get("/game.project", request.category .. "." .. request.key))) +end) +``` + +Jeśli otworzysz adres taki jak `http://0.0.0.0:12345/my-extension/setting/project.title`, zobaczysz tytuł gry odczytany z pliku `/game.project`. + +Poza wzorcami pojedynczego segmentu można też dopasowywać resztę ścieżki URL składnią `{*name}`. Na przykład prosty endpoint serwujący pliki z katalogu projektu może wyglądać tak: + +```lua +http.server.route("/my-extension/files/{*file}", function(request) + local attrs = editor.external_file_attributes(request.file) + if attrs.is_file then + return http.server.external_file_response(request.file) + else + return 404 + end +end) +``` + +Po otwarciu adresu takiego jak `http://0.0.0.0:12345/my-extension/files/main/main.collection` w przeglądarce zobaczysz zawartość pliku `main/main.collection`. + +## Editor scripts in libraries + +Możesz publikować biblioteki zawierające polecenia dla innych użytkowników, a edytor wykryje je automatycznie. Haki nie mogą być jednak wykrywane automatycznie, bo muszą być zdefiniowane w pliku znajdującym się w katalogu głównym projektu, podczas gdy biblioteki udostępniają tylko podkatalogi. To celowe: użytkownik powinien mieć większą kontrolę nad procesem builda. Nadal możesz definiować haki cyklu życia jako zwykłe funkcje w plikach `.lua`, a użytkownicy biblioteki mogą je potem załadować i wykorzystać w swoim `/hooks.editor_script`. + +Warto też pamiętać, że choć zależności są widoczne w `Assets`, nie istnieją jako zwykłe pliki — są wpisami w archiwum zip. Edytor potrafi jednak wypakować wybrane pliki z zależności do katalogu `build/plugins/`. W tym celu utwórz plik `ext.manifest` w katalogu biblioteki, a następnie katalog `plugins/bin/${platform}` obok tego pliku. Zawartość tego katalogu zostanie automatycznie wypakowana do `/build/plugins/${extension-path}/plugins/bin/${platform}`, dzięki czemu skrypty edytora będą mogły się do niej odwoływać. + +## Preferences + +Skrypty edytora mogą definiować i używać preferencji, czyli trwałych, niecommitowanych danych przechowywanych na komputerze użytkownika. Preferencje mają trzy główne cechy: + +- są typowane: każda preferencja ma definicję schematu zawierającą typ danych i dodatkowe metadane, takie jak wartość domyślna; +- mają zakres: preferencje są ograniczone albo do projektu, albo do użytkownika; +- są zagnieżdżone: każdy klucz preferencji jest łańcuchem rozdzielanym kropkami, gdzie pierwszy segment identyfikuje skrypt edytora, a kolejne opisują strukturę danej preferencji. + +Wszystkie preferencje trzeba zarejestrować przez zdefiniowanie schematu: + +```lua +function M.get_prefs_schema() + return { + ["my_json_formatter.jq_path"] = editor.prefs.schema.string(), + ["my_json_formatter.indent.size"] = editor.prefs.schema.integer({default = 2, scope = editor.prefs.SCOPE.PROJECT}), + ["my_json_formatter.indent.type"] = editor.prefs.schema.enum({values = {"spaces", "tabs"}, scope = editor.prefs.SCOPE.PROJECT}), + } +end +``` + +Po przeładowaniu takiego skryptu edytor rejestruje schemat. Następnie skrypt może odczytywać i zapisywać preferencje, na przykład: + +```lua +-- Pobierz konkretną preferencję +editor.prefs.get("my_json_formatter.indent.type") +-- Zwróci: "spaces" + +-- Pobierz całą grupę preferencji +editor.prefs.get("my_json_formatter") +-- Zwróci: +-- { +-- jq_path = "", +-- indent = { +-- size = 2, +-- type = "spaces" +-- } +-- } + +-- Ustaw wiele zagnieżdżonych preferencji naraz +editor.prefs.set("my_json_formatter.indent", { + type = "tabs", + size = 1 +}) +``` + +## Execution modes + +Środowisko uruchomieniowe skryptów edytora używa dwóch trybów wykonania, które w większości są przezroczyste dla samego skryptu: **immediate** i **long-running**. + +Tryb **immediate** jest używany wtedy, gdy edytor potrzebuje odpowiedzi od skryptu możliwie natychmiast. Na przykład callbacki `active` poleceń menu są wykonywane w tym trybie, ponieważ sprawdzenia aktywności odbywają się w wątku UI edytora i muszą odświeżyć interfejs w tej samej klatce. + +Tryb **long-running** jest używany wtedy, gdy odpowiedź nie musi być natychmiastowa. Na przykład callbacki `run` poleceń menu działają w trybie **long-running**, więc skrypt może poświęcić więcej czasu na wykonanie zadania. + +Niektóre funkcje dostępne dla skryptów edytora mogą wykonywać się długo. Na przykład `editor.execute("git", "status", {reload_resources=false, out="capture"})` może w dużym projekcie działać nawet sekundę. Aby zachować responsywność i wydajność edytora, takich funkcji nie wolno używać w kontekstach wymagających natychmiastowej odpowiedzi. Próba użycia ich w takim kontekście zakończy się błędem: `Cannot use long-running editor function in immediate context`. Rozwiązaniem jest unikanie tych funkcji w trybie `immediate`. + +Za długo działające uznawane są: + +- `editor.create_directory()`, `editor.create_resources()`, `editor.delete_directory()`, `editor.save()`, `os.remove()` i `file:write()` — modyfikują pliki na dysku, przez co edytor musi zsynchronizować drzewo zasobów w pamięci ze stanem dysku, co w dużych projektach może trwać sekundy; +- `editor.execute()` — uruchamianie poleceń powłoki może zająć nieprzewidywalnie dużo czasu; +- `editor.transact()` — duże transakcje na szeroko referencjonowanych węzłach mogą trwać setki milisekund, co jest zbyt wolne dla responsywnego UI. + +W trybie `immediate` działają: + +- callbacki `active` poleceń menu — edytor potrzebuje odpowiedzi w tej samej klatce UI; +- kod wykonywany na najwyższym poziomie skryptów edytora — sam proces przeładowywania skryptów nie powinien powodować skutków ubocznych. + +## Actions + +::: sidenote +Wcześniej edytor komunikował się z maszyną Lua w sposób blokujący, więc skrypty edytora nie mogły blokować działania edytora, bo część interakcji była wykonywana z wątku UI. Z tego powodu nie było na przykład `editor.execute()` ani `editor.transact()`. Uruchamianie skryptów i zmiany stanu edytora były wtedy inicjowane przez zwracanie tablicy "actions" z hooków i callbacków `run`. + +Obecnie edytor komunikuje się z maszyną Lua w sposób nieblokujący, więc akcje nie są już potrzebne: korzystanie z funkcji takich jak `editor.execute()` jest wygodniejsze, krótsze i daje większe możliwości. Akcje są teraz **DEPRECATED**, choć nie planujemy ich usuwać. +::: + +Skrypty edytora mogą zwracać tablicę akcji z funkcji `run` poleceń albo z hooków w `/hooks.editor_script`. Edytor wykona potem te akcje. + +Action to tabela opisująca, co edytor ma zrobić. Każda akcja ma klucz `action`. Akcje występują w dwóch wariantach: z możliwością cofnięcia i bez możliwości cofnięcia. + +### Undoable actions + +::: sidenote +Preferuj używanie `editor.transact()`. +::: + +Undoable action można cofnąć po jej wykonaniu. Jeśli polecenie zwraca kilka akcji tego typu, zostaną wykonane i cofnięte razem. W miarę możliwości warto ich używać, choć są bardziej ograniczone. + +Obecnie dostępne undoable actions: + +- `"set"` — ustawia właściwość węzła w edytorze na wybraną wartość. Przykład: + ```lua + { + action = "set", + node_id = opts.selection, + property = "text", + value = "current time is " .. os.date() + } + ``` + Akcja `"set"` wymaga: + - `node_id` — identyfikatora węzła jako userdata. Alternatywnie można podać ścieżkę zasobu, na przykład `"/main/game.script"`; + - `property` — właściwości do ustawienia, na przykład `"text"`; + - `value` — nowej wartości właściwości. Dla `"text"` powinna to być wartość typu string. + +### Non-undoable actions + +::: sidenote +Preferuj używanie `editor.execute()`. +::: + +Non-undoable action czyści historię cofania, więc jeśli chcesz ją odwrócić, musisz użyć innych metod, na przykład systemu kontroli wersji. + +Obecnie dostępne non-undoable actions: + +- `"shell"` — uruchamia skrypt powłoki. Przykład: + ```lua + { + action = "shell", + command = { + "./scripts/minify-json.sh", + editor.get(opts.selection, "path"):sub(2) -- usuń początkowy "/" + } + } + ``` + Akcja `"shell"` wymaga klucza `command`, czyli tablicy z poleceniem i argumentami. + +### Mixing actions and side effects -Tabela definicji serwera językowego może określać: +Możesz mieszać akcje z możliwością cofnięcia i bez niej. Akcje są wykonywane sekwencyjnie, więc w zależności od kolejności możesz utracić możliwość cofnięcia części polecenia. -- `languages` (wymagane) — listę języków, których serwer dotyczy, zdefiniowanych [tutaj](https://code.visualstudio.com/docs/languages/identifiers#_known-language-identifiers) (rozszerzenia plików także działają); -- `command` (wymagane) - tablicę komendy i jej argumentów -- `watched_files` - tablicę tablic z kluczami `pattern` (glob), które będą powiadomiać serwer o zmianie plików, zgodnie z powiadomieniami o [zmianie plików śledzonych](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#workspace_didChangeWatchedFiles). +Zamiast zwracać akcje z funkcji, które ich oczekują, możesz też po prostu czytać i zapisywać pliki bezpośrednio przez `io.open()`. Spowoduje to przeładowanie zasobów, a to z kolei wyczyści historię cofania. diff --git a/docs/pl/manuals/editor.md b/docs/pl/manuals/editor.md index 533e6534..78fb3824 100644 --- a/docs/pl/manuals/editor.md +++ b/docs/pl/manuals/editor.md @@ -1,163 +1,336 @@ --- -title: Edytor Defold -brief: Ta instrukcja opisuje ogólnie Edytor Defold, jak wygląda i działa oraz jak w nim się poruszać. +title: Przegląd edytora +brief: Ta instrukcja przedstawia, jak wygląda i działa edytor Defold oraz jak się po nim poruszać. --- -# Edytor Defold +# Przegląd edytora -Edytor Defold pozwala przeglądać i zarządzać plikami w Twoim projekcie w wydajny sposób. Edytowanie różnych plików otwiera odpowiednie widoki ukazujące wszystkie niezbędne informacje. +Edytor pozwala sprawnie przeglądać i modyfikować wszystkie pliki oraz foldery w projekcie gry. Po otwarciu pliku edytor wybiera odpowiedni widok dla jego typu i pokazuje powiązane informacje w osobnych panelach. ## Uruchamianie Edytora -Kiedy uruchamiasz Edytor Defold zostaje najpierw otwarte okno wyboru i tworzenia projektu. Wybierz spośród: +Po uruchomieniu edytora Defold zobaczysz ekran wyboru i tworzenia projektu. Kliknij to, co chcesz zrobić: -Home (Strona domowa) -: Kliknij, żeby zobaczyć swoje ostatnio otwierane projekty. To jest domyślny widok. +MY PROJECTS +: Tutaj znajdziesz ostatnio otwierane projekty, dzięki czemu możesz szybko do nich wrócić. To domyślny widok ekranu startowego. -New Project (Nowy Projekt) -: Kliknij, jeśli chcesz stworzyć nowy projekt. Następnie wybierz bazę swojego projektu spośród dostępnych szablonów (z zakładki *From Template*), tutoriali (*From Tutorial*) lub wypróbować jecen z przykładowych projektów (*From Sample*). + Jeśli wcześniej nie otwierałeś żadnych projektów albo usunąłeś je z listy, zobaczysz dwa przyciski. `Open From Disk…` pozwala znaleźć i otworzyć projekt przez systemową przeglądarkę plików, a `Create New Project` przełącza do zakładki `TEMPLATES`. - ![new project](images/editor/new_project.png) + ![my projects](images/editor/start_no_projects.png) - Kiedy utworzysz nowy projekt będzie on zapisany na Twoim lokalnym dysku, tak jak wszystkie zmiany, które w nim zrobisz. + Jeśli wcześniej otwierałeś już projekty, zobaczysz ich listę, jak na ilustracji poniżej: -Szczegóły dotyczące różnych zakładek znajdziesz w [instrukcji do rozpoczynania projektu](https://www.defold.com/manuals/project-setup/). + ![my projects](images/editor/start_my_projects.png) -## Widoki w Edytorze +TEMPLATES +: Zawiera puste lub prawie puste projekty startowe, przygotowane do szybkiego rozpoczęcia nowego projektu Defold dla wybranych platform albo z użyciem określonych rozszerzeń. -Edytor Defold jest podzielony na oddzielne widoki/sekcje, które zawierają specyficzne informacje. +TUTORIALS +: Zawiera projekty z samouczkami, które można uruchamiać, analizować i modyfikować, jeśli chcesz uczyć się krok po kroku. -![Editor 2](images/editor/editor2_overview.png) +SAMPLES +: Zawiera projekty przygotowane do prezentowania określonych zastosowań. -Widok *Assets* (Zasoby) -: Zawiera listę wszystkich plików projektu, reprezentowaną podobnie do systemowego eksploratora plików, zgodnie z hierarchią katalogów. Możesz klikać, przewijać i rozwijać elementy: + ![New project](images/editor/start_templates.png) - - Kliknij dwukrotnie lewym przyciskem myszki nazwę pliku, żeby otworzyć go w Edytorze. - - Przeciągaj i upuszczaj pliki, aby zmieniać ich lokalizację w strukturze projektu lub dodawać nowe pliki z dysku. - - Kliknij prawy przycisk myszki, żeby otworzyć _menu kontekstowe_, z którego możesz utworzyć nowe pliki i foldery, zmienić nazwę, usunąć czy śledzić zależności i wiele więcej. +Gdy utworzysz nowy projekt, zostanie on zapisany na lokalnym dysku, a wszystkie kolejne zmiany również będą zapisywane lokalnie. -Widok *Editor* (Edytor) +Więcej o dostępnych opcjach przeczytasz w [instrukcji o konfiguracji projektu](https://www.defold.com/manuals/project-setup/). -: Centralna sekcja wyświetla aktualnie otwarty plik w Edytorze odpowiedniem dla danego typu pliku. Wszystkie rodzaje takich Edytorów, które są wizualne pozwalają na manipulację widokiem kamery: +## Język edytora -- Przesuwanie: Alt + Lewy przycisk myszki. -- Oddalanie/przybliżanie: Alt + Prawy przycisk myszki (myszki trójprzyciskowe) lub Ctrl + Lewy przycisk myszki (jeden przycisk). Jeśli myszka ma kółko, może ono być również używane do przybliżania i oddalania. -- Obracaj w 3D: Ctrl + Lewy przycisk myszki. +W lewym dolnym rogu ekranu startowego znajduje się wybór języka. Możesz wybrać jedną z aktualnie dostępnych lokalizacji językowych od wersji Defold 1.11.2. Ta sama opcja jest dostępna także w edytorze w `File ▸ Preferences ▸ General ▸ Editor Language`. -W prawym górnym rogu Edytora aktualnie otwartego pliku (sceny) znajduje się zestaw narzędzi obsługi widoku kamery: *Move* (Przesuwanie), *Rotate* (Obracanie) and *Scale* (Skalowanie). +![Languages](images/editor/languages.png) -![toolbar](images/editor/toolbar.png) +## Panele edytora -Widok *Outline* (Zawartość pliku) -: Widok ten pokazuje zawartość aktualnie otwartego pliku, w strukturze drzewa. Odzwierciedla widok Edytora i pozwala na wykonywanie operacji na zawartości: +Edytor Defold jest podzielony na zestaw paneli, czyli widoków pokazujących określone informacje. - - Kliknij lewym przyciskem myszki aby wybrać wskazany element. Przytrzymaj klawisz Shift lub Option, żeby zaznaczyć wiele elementów. - - Przeciągaj i upuszczaj elementy, żeby zmieniać ich położenie w strukturze. Upuść obiekty gry (game object) na innym obiekcie w kolekcji, żeby stworzyć relację rodzic-dziecko. - - Kliknij prawy przycisk myszki, żeby otworzyć _menu kontekstowe_, z którego możesz utworzyć nowe komponenty, usunąć wybrane i wiele więcej. +![Editor 2](images/editor/editor_overview.png) -Widok *Properties* (Właściwości)) -: Widok ten pokazuje właściwości aktualnie wybranego komponentu, takie jak Pozycja, Rotacja, Animacja, Id, etc. +### 1. Panel Assets -Widok *Tools* (Narzędzia) -: Dolny widok pokazuje w zależności od wybranej zakładki: konsolę (ang. *Console*) wyświetlającą logi działającego programu, Edytor krzywych (ang. *Curve Editor*) umożliwiający edytowanie wykresu krzywej, używany np. przy tworzeniu efektów cząsteczkowych (particle fx), błędy budowania (ang. *Build Errors*) i wyniki wyszukiwania (ang. *Search Results*). Konsola jest również używana podczas używania zintegrowanego debuggera. +Pokazuje wszystkie pliki i foldery należące do projektu w strukturze drzewa odpowiadającej układowi na dysku. Możesz klikać i przewijać, aby poruszać się po liście. W tym widoku wykonuje się wszystkie operacje związane z plikami: -Widok *Changed Files* (Zmienione pliki): -: Widok pokazuje wszystkie pliki, które zostały zmienione, dodane lub usunięte z Twojego projektu od ostatniej zapisanej w systemie kontroli wersji zmiany (commit). This view lists any files that has been changed, added or deleted in your project. By synchronizing the project regularly you can bring your local copy in sync with what is stored in the project Git repository, that way you can collaborate within a team, and you won’t lose your work if unfortune strikes. Some file oriented operations can be performed in this view: +- Left Mouse Click, aby wybrać plik lub folder. Przytrzymując ⇧ Shift, rozszerzysz zaznaczenie, a przytrzymując Ctrl/⌘ Cmd, zaznaczysz lub odznaczysz kliknięty element. +- Double Mouse Click na pliku, aby otworzyć go w edytorze właściwym dla tego typu pliku. +- Drag and Drop, aby dodać pliki z innych miejsc na dysku do projektu albo przenosić pliki i foldery w obrębie projektu. +- Right Mouse Click, aby otworzyć _Context Menu_, z którego możesz tworzyć nowe pliki i foldery, zmieniać nazwy, usuwać elementy, śledzić zależności plików i wykonywać inne operacje. - - Double click a file to open a diff view of the file. Editor 2 opens the file in a suitable editor, just like in the assets view. - - Right click a file to open a pop up menu from where you can open a diff view, revert all changes done to the file, find the file on the filesystem and more (editor 2). +### 2. Panel Editor -## Edytowanie równolegle (Side-by-side) +Środkowy widok pokazuje aktualnie otwarty plik w edytorze odpowiednim dla jego typu. Na przykład pliki skryptów otwierają się we wbudowanym Code Editor, a komponenty wizualne w trójwymiarowym Visual Editor. Wszystkie Visual Editors pozwalają zmieniać widok kamery: -Jeśli masz otwartych kilka plików jednocześnie, dla każdego z nich pokazywana jest osobna zakładka na górnym pasku Edytora Defold. Możliwe jest również otworzenie dwóch Edytorów/.paneli naraz, jeden obok drugiego. Wybierz plik, klikająć prawym przyciskiem myszy na danej zakładce w górnym pasku i wybierz Move to Other Tab Pane z menu kontekstowego. +- Przesuwanie: Alt/⌥ Option + Left Mouse Button lub Right Mouse Button +- Przybliżanie i oddalanie: Scroll Mouse Wheel albo Alt/⌥ Option + Right Mouse Button +- Obracanie w 3D wokół zaznaczenia: Ctrl/^ Control + Left Mouse Button + +#### Pasek narzędzi + +W prawym górnym rogu widoku sceny znajduje się pasek narzędzi z narzędziami do manipulacji obiektami. Od lewej są to: + +*Move* (W), *Rotate* (E), *Scale* (R), *Grid Settings* `▦`, *Align Camera 2D/3D* `2D`, przełącznik *Camera Perspective/Orthographic* oraz *Visibility Filters* `👁`. + +![Toolbar](images/editor/toolbar.png) + +### 3. Panel Outline + +Ten widok pokazuje zawartość aktualnie edytowanego pliku w strukturze hierarchicznego drzewa. `Outline` odzwierciedla widok edytora i pozwala wykonywać operacje na elementach: + +- Left Mouse Click, aby zaznaczyć element. Przytrzymując ⇧ Shift, rozszerzysz zaznaczenie, a przytrzymując Ctrl/⌘ Cmd, zaznaczysz lub odznaczysz kliknięty element. +- Drag and Drop, aby przenosić elementy. Upuszczenie obiektu gry na inny obiekt gry w kolekcji tworzy relację rodzic-dziecko. +- Right Mouse Click, aby otworzyć _Context Menu_, z którego możesz dodawać elementy, usuwać zaznaczone obiekty i wykonywać inne operacje. + +Widoczność obiektów gry i komponentów wizualnych można przełączać, klikając małą ikonę oka `👁` po prawej stronie elementu na liście. Funkcja jest dostępna od Defold 1.9.8. + +![Outline](images/editor/outline.png) + +### 4. Panel Properties + +Ten widok pokazuje właściwości powiązane z aktualnie zaznaczonym elementem, na przykład `Id`, `URL`, `Position`, `Rotation`, `Scale`, właściwości specyficzne dla komponentu oraz własne właściwości skryptów. + +Możesz też Drag ikonę strzałki `↕` i poruszać myszą, aby zmieniać wartość danej właściwości liczbowej. Ta funkcja jest dostępna od wersji 1.10.2. + +![Properties](images/editor/properties.png) + +### 5. Panel Tools + +Ten widok zawiera kilka kart: + +*Console* +: pokazuje błędy, ostrzeżenia, informacje wypisywane przez silnik oraz komunikaty, które sam wypisujesz, gdy gra jest uruchomiona. + +*Build Errors* +: pokazuje błędy z procesu budowania. + +*Search Results* +: pokazuje wyniki wyszukiwania w całym projekcie po użyciu Ctrl/⌘ Cmd + Shift + F, jeśli klikniesz `Keep Results`. + +*Curve Editor* +: jest używany podczas edytowania krzywych w [Particle Editor](/manuals/particlefx/). + +Panel `Tools` służy również do pracy ze zintegrowanym debuggerem. Więcej informacji znajdziesz w [instrukcji debugowania](/manuals/debugging/). + +### 6. Panel Changed Files + +Jeśli projekt używa rozproszonego systemu kontroli wersji Git, ten widok pokazuje wszystkie pliki zmienione, dodane lub usunięte w projekcie. Regularna synchronizacja projektu pozwala utrzymywać lokalną kopię zgodną z tym, co znajduje się w repozytorium Git projektu. Dzięki temu łatwiej pracować zespołowo i uniknąć utraty efektów pracy. Więcej o Git znajdziesz w [instrukcji kontroli wersji](/manuals/version-control/). W tym widoku można wykonywać część operacji na plikach: + +- Left Mouse Click, aby wybrać plik. Przytrzymując ⇧ Shift, rozszerzysz zaznaczenie, a przytrzymując Ctrl/⌘ Cmd, zaznaczysz lub odznaczysz kliknięty element. Jeśli zaznaczony jest jeden zmieniony plik, możesz kliknąć `Diff`, aby zobaczyć różnice. Kliknięcie `Revert` cofa zmiany we wszystkich zaznaczonych plikach. +- Double Left Mouse Click na pliku, aby otworzyć jego widok. Edytor otworzy plik w odpowiednim edytorze, tak jak w panelu `Assets`. +- Right Mouse Click na pliku, aby otworzyć menu podręczne, z którego możesz wyświetlić `diff`, cofnąć wszystkie zmiany w pliku, znaleźć go w systemie plików i wykonać inne operacje. + +### Pasek menu + +Na górze widoku edytora, a na Macu w systemowym pasku menu, znajduje się pasek z sześcioma menu: `File`, `Edit`, `View`, `Project`, `Debug` i `Help`. Ich funkcje opisano w odpowiednich instrukcjach. + +### Pasek stanu + +Na dolnym pasku edytora znajduje się wąski obszar, w którym wyświetlany jest status, na przykład: + +- gdy dostępna jest nowa wersja, zobaczysz klikalny przycisk `Update Available`; patrz sekcja o aktualizowaniu edytora poniżej +- podczas budowania lub bundlowania będzie tam widoczny postęp operacji + +## Rozmiar i widoczność paneli + +Rozmiar paneli można zmieniać w edytorze przez Dragging granic pomiędzy opisanymi wyżej sześcioma panelami. + +Widoczność paneli można przełączać z menu `View` albo skrótami: + +- `Toggle Assets Pane` (F6) przełącza widoczność paneli `Assets` i `Changed Files` +- `Toggle Changed Files` przełącza widoczność samego panelu `Changed Files` +- `Toggle Tools Pane` (F7) przełącza widoczność panelu `Tools` +- `Toggle Properties Pane` (F8) przełącza widoczność paneli `Outline` i `Properties` + +![Panes Visibility](images/editor/editor_panes.png) + +W menu `View` możesz też przełączać lub zmieniać inne ustawienia widoczności, takie jak siatka, prowadnice czy kamera. Możesz też dopasować widok do zaznaczenia za pomocą `Frame Selection` lub klawisza F, a także przełączać się między domyślnym widokiem 2D i 3D za pomocą `Realign Camera` lub klawisza .. Wiele z tych funkcji jest również dostępnych z paska narzędzi albo przez skróty. + +## Zakładki + +Jeśli masz otwartych kilka plików, u góry panelu `Editor` pojawi się osobna zakładka dla każdego pliku. Zakładki w obrębie jednego panelu można przestawiać przez Drag and Drop, aby zamieniać ich kolejność. Możesz też: + +- Right Mouse Click na zakładce, aby otworzyć _Context Menu_ +- kliknąć `Close` (Ctrl/⌘ Cmd + W), aby zamknąć jedną zakładkę +- kliknąć `Close Others`, aby zamknąć wszystkie zakładki poza wybraną +- kliknąć `Close All` (Ctrl/⌘ Cmd + Shift + W), aby zamknąć wszystkie zakładki w aktywnym panelu +- wybrać `➝| Open As`, aby użyć innego niż domyślny edytora albo zewnętrznego narzędzia ustawionego w `File ▸ Preferences ▸ Code ▸ Custom Editor`; więcej informacji znajdziesz w [instrukcji Preferences](/manuals/editor-preferences) + +![Tabs](images/editor/tabs_custom.png) + +## Edycja obok siebie + +Możliwe jest otwarcie dwóch widoków edytora obok siebie. + +- Right Mouse Click na zakładce edytora, który chcesz przenieść, a następnie wybierz `Move to Other Tab Pane` ![2 panes](images/editor/2-panes.png) -Następnie, możesz również z tego samego menu kontekstowego wybrać opcje Swap With Other Tab Pane, żeby zamienić panele miejscami lub Join Tab Panes, żeby z powrotem połączyć panele w jeden. +Z tego samego menu zakładki możesz też użyć `Swap with Other Tab Pane`, aby przenieść wybraną zakładkę między panelami, albo `Join Tab Panes`, aby z powrotem połączyć oba panele w jeden. ## Edytor sceny -Kliknij dwukrotnie lewym przyciskiem myszki na kolekcji lub obiekcie gry, żeby otworzyć *Edytor Sceny*: +Dwukrotne kliknięcie kolekcji, obiektu gry albo pliku komponentu wizualnego otwiera *Scene Editor*. Domyślnie wszystkie sceny wizualne otwierają się w ortograficznym widoku 2D: + +![Scene Editor](images/editor/2d_scene.png) + +Jeśli pracujesz nad projektem 3D, warto zajrzeć do paska narzędzi i dostosować `Grid Settings` `▦`, na przykład przełączyć wyrównanie kamery między 2D i 3D przez `2D` lub klawisz ., ustawić wyświetlanie siatki na płaszczyźnie `Y` albo innej, która będzie dla Ciebie bardziej intuicyjna, i przełączyć kamerę na perspektywiczną za pomocą przełącznika na pasku narzędzi albo `View ▸ Perspective Camera`: + +![Scene Editor 3D](images/editor/3d_scene.png) + +### Manipulowanie obiektami + +Left Mouse Click na obiekcie w głównym oknie zaznacza go. Prostokąt lub prostopadłościan otaczający obiekt w widoku edytora zostanie podświetlony na kolor cyjan, aby wskazać zaznaczony element. Zaznaczony obiekt zostanie też podświetlony w widoku `Outline`, jak na ilustracji powyżej. + +Możesz też zaznaczać obiekty w następujący sposób: + +- Left Mouse Click i Drag, aby zaznaczyć wszystkie obiekty mieszczące się w obszarze zaznaczenia +- Left Mouse Click na obiektach w `Outline`; przytrzymując ⇧ Shift, rozszerzysz zaznaczenie, a przytrzymując Ctrl/⌘ Cmd, zaznaczysz lub odznaczysz kliknięty element + +#### Narzędzie Move -![Select object](images/editor/select.png) +![Move tool](images/editor/icon_move.png){.left} -Wybieranie obiektów: -: Kliknij na obiekt w głównym oknie, żeby go wybrać. Prostokąt wokół wybranego obiektu zostanie podświetlony na zielono. Wybrany obiekty zostanie również podświetlony w widoku *Outline* po prawej stronie. +Aby przesuwać obiekty, użyj *Move Tool*. Narzędzie znajduje się na pasku narzędzi w prawym górnym rogu edytora sceny albo możesz włączyć je klawiszem W. - Obiekty możesz wybierać również: +![Move object](images/editor/move.png){.inline}![Move object 3D](images/editor/move_3d.png){.inline} - - Klikając i przeciągając, żeby wybrać wszystkie obiekty w zaznaczonym, prostokątnym obszarze. - - Klikając na obiekt w widoku Outline po prawej stronie. +Gizmo zmienia się i pokazuje zestaw manipulatorów, czyli kwadratów i strzałek. Zaznaczony manipulator zmienia kolor na pomarańczowy. Możesz je Drag, aby przesuwać obiekty: - Naciśnij i przytrzymaj Shift lub (Mac) / Ctrl (Win/Linux) podczas wybierania obiektów, aby wybrać więcej na raz. +- środkowy cyjanowy kwadrat przesuwa obiekt tylko w przestrzeni ekranu +- trzy czerwone, zielone i niebieskie strzałki przesuwają obiekt tylko wzdłuż odpowiednio osi X, Y i Z +- trzy czerwone, zielone i niebieskie kwadratowe uchwyty przesuwają obiekt tylko po wybranej płaszczyźnie, na przykład X-Y (niebieska), a po obróceniu kamery w 3D także X-Z (zielona) i Y-Z (czerwona) -Narzędzie przesuwania (Move) -: ![Move tool](images/editor/icon_move.png){.left} - Do przesuwania obiektów można użyć narzędzia przesuwania *Move*. Znajdziesz je w pasku narzędzi w prawym górnym rogu Edytora sceny lub klikając klawisz W. +#### Narzędzie Rotate - ![Move object](images/editor/move.png) +![Rotate tool](images/editor/icon_rotate.png){.left} - Nad wybranym obiektem wyświetla się zestaw wizualnych manipulatorów (kwadraty i strzałki). Klikaj i przeciągaj środkowym kwadratem, aby dowolnie przesuwać obiektem po ekranie lub klikaj i przeciągaj pojedyncze strzałki, aby przesuwać obiekt tylko wzdłuż wybranej osi. Są tutaj również kwadratowe wskaźniki umożliwiające poruszanie się po płaszczyznach XY oraz X-Z i Y-Z (widoczne po obróceniu kamery). +Aby obracać obiekty, użyj *Rotate Tool*, wybierając je na pasku narzędzi albo naciskając E. -Narzędzie obracania (Rotate) -: ![Rotate tool](images/editor/icon_rotate.png){.left} - Do obracania obiektów, można użyć narzędzia obracania *Rotate* wybierając je z górnego paska narzędzi lub naciskając klawisz E. +![Rotate object](images/editor/rotate.png){.inline}![Rotate object 3D](images/editor/rotate_3d.png){.inline} - ![Move object](images/editor/rotate.png) +To narzędzie składa się z czterech okrągłych manipulatorów, które możesz Drag, aby obracać obiekt. Zaznaczony manipulator zmienia kolor na pomarańczowy: - Nad wybranym obiektem wyświetla się zestaw wizualnych, okrągłych manipulatorów. Pomarańczowy manipulator obraca obiektem w płaszczyźnie ekranu, a pozostałe wokół osi X, Y i Z. Pamiętaj, że domyślny widok jest prostopadły do osi X i Y, więc okręgi służące do obrotu wokół tych osi są widoczne wtedy po prostu jako linie. +- zewnętrzny, największy, cyjanowy manipulator obraca obiekt w płaszczyźnie ekranu +- trzy mniejsze czerwone, zielone i niebieskie manipulatory pozwalają obracać osobno wokół osi X, Y i Z; w widoku ortograficznym 2D dwa z nich są prostopadłe do osi X i Y, więc są widoczne tylko jako linie przecinające obiekt -Narzędzie skalowania (Scale) -: ![Scale tool](images/editor/icon_scale.png){.left} - Do skalowania obiektów, można użyć narzędzia skalowania *Scale* wybierając je z górnego paska narzędzi lub naciskając klawisz R. +#### Narzędzie Scale - ![Scale object](images/editor/scale.png) +![Scale tool](images/editor/icon_scale.png){.left} - Nad wybranym obiektem wyświetla się zestaw wizualnych, kwadratowych manipulatorów. Środkowy kwadrat skaluje obiekt jednakowo wzdłuż każdej z osi (włącznie z osią Z), a pozostałe odpowiednio wokół osi X, Y i Z. Oprócz tego pokazane są wtedy również kwadraty pozwalające na skalowanie wzdłuż dwóch osi jednocześnie, parami: X-Y, X-Z i Y-Z. +Aby skalować obiekty, użyj *Scale Tool*, wybierając je na pasku narzędzi albo naciskając R. -## Tworzenie nowego pliku +![Scale object](images/editor/scale.png){.inline}![Scale object 3D](images/editor/scale_3d.png){.inline} -Żeby utworzyć nowy plik kliknij z górnego menu File ▸ New... i wybierz typ pliku z menu lub użyj menu kontekstowego: +To narzędzie składa się z zestawu kwadratowych i sześciennych manipulatorów, które możesz Drag, aby skalować obiekty. Zaznaczony manipulator zmienia kolor na pomarańczowy: -Kliknij prawy przycisk myszki na docelowej lokalizacji w panelu *Assets* po lewej stronie i wybierz New... ▸ [file type]: +- środkowy cyjanowy sześcian skaluje obiekt równomiernie we wszystkich osiach, także w osi Z +- trzy czerwone, niebieskie i zielone manipulatory składające się z sześcianów skalują obiekt osobno wzdłuż osi X, Y i Z +- trzy czerwone, niebieskie i zielone manipulatory składające się z sześcianów skalują obiekt osobno w płaszczyznach X-Y, X-Z i Y-Z + +### Filtry widoczności + +Kliknij ikonę oka `👁` na pasku narzędzi, aby przełączać widoczność różnych typów komponentów oraz obwiedni i linii pomocniczych. `Component Guides` ma też skrót Ctrl + H w Windows/Linux lub ^ Ctrl + ⌘ Cmd + H na Macu. + +![Visibility filters](images/editor/visibilityfilters.png) + +## Tworzenie nowych plików projektu + +Aby utworzyć nowy plik zasobu, wybierz `File ▸ New…`, a następnie typ pliku z menu albo użyj menu kontekstowego: + +Right Mouse Click w docelowym miejscu w przeglądarce `Assets`, a następnie wybierz `New… ▸ [file type]`: ![create file](images/editor/create_file.png) -Podaj odpowiednią nazwę dla pliku. Pełna nazwa pliku uwzględniająca końcówkę znajduję się w polu *Path* (ścieżka) w oknie dialogowym: +Wpisz odpowiednią *Name* dla nowego pliku, a w razie potrzeby zmień *Location*. Pełna nazwa pliku wraz z rozszerzeniem jest pokazywana w polu *Preview* w oknie dialogowym: ![create file name](images/editor/create_file_name.png) +## Szablony + +Możesz zdefiniować własne szablony dla każdego projektu. W tym celu utwórz w katalogu głównym projektu folder `templates` i dodaj do niego pliki `default.*` z odpowiednimi rozszerzeniami, na przykład `/templates/default.gui` albo `/templates/default.script`. Dodatkowo, jeśli w tych plikach użyjesz znacznika `{{NAME}}`, zostanie on zastąpiony nazwą pliku podaną w oknie tworzenia pliku. + +Jeśli dla danego typu pliku istnieje szablon, każdy nowo tworzony plik tego typu zostanie zainicjalizowany zawartością odpowiedniego pliku z katalogu `templates`. + +![Templates](images/editor/templates.png) + ## Importowanie plików do projektu -Aby dodać pliki (obrazki, dźwięki, modele, itp.) do Twojego projektu, po prostu przeciągnij i upuść je w odpowiednim miejscu w panelu *Assets* po lewej stronie. Utworzysz w ten sposób _kopię_ danego pliku w docelowej lokalizacji projektu. Przeczytaj więcej na temat [importowania plików w tej instrukcji](/manuals/importing-assets/). +Aby dodać do projektu pliki zasobów, takie jak obrazy, dźwięki czy modele, po prostu przeciągnij je i upuść we właściwe miejsce w przeglądarce `Assets`. Spowoduje to utworzenie _kopii_ plików w wybranej lokalizacji w strukturze projektu. Więcej informacji znajdziesz w [instrukcji importowania zasobów](/manuals/importing-assets/). ![Import files](images/editor/import.png) -## Aktualizowanie Edytora +## Aktualizowanie edytora -Edytor automatycznie wyszukuje aktualizacje, jeśli ma dostęp do internetu. Kiedy aktualizacja jest dostępna, informacja o możliwości zaktualizowania pojawi się w prawym dolnym rogu Edytora i na stronie startowej z wyborem projektu. Naciśnięcie przycisku `Update Available` spowoduje pobranie aktualizacji i zainstalowanie jej. +Edytor automatycznie sprawdza aktualizacje, gdy ma połączenie z internetem. Gdy wykryje nową wersję, w lewym dolnym rogu ekranu wyboru projektu albo w prawym dolnym rogu okna edytora pojawi się niebieski klikalny odnośnik `Update Available`. -![Update from project selection](images/editor/update-project-selection.png) +![Update from project selection](images/editor/update_start.png) +![Update from Editor](images/editor/update_available.png) -![Update from editor](images/editor/update-main.png) +Kliknij odnośnik `Update Available`, aby pobrać i zainstalować aktualizację. Pojawi się okno potwierdzenia z dodatkowymi informacjami. Kliknij `Download Update`, aby kontynuować. -## Skróty klawiszowe +![Update Editor popup](images/editor/update.png) -Skróty opisane są w [instrukcji o skrótach klawiszowych](/manuals/editor-keyboard-shortcuts). +Postęp pobierania będzie widoczny na dolnym pasku stanu: -## Logi Edytora -Jeśli napotkasz jakiekolwiek problemy z Edytorem Defold warto [to zaraportować](/manuals/getting-help/#getting-help). Dobrą pkratyką jest dodanie plików z logami z Edytora. Można je znaleźć tutaj: +![Download progress](images/editor/download_status.png) - * Windows: `C:\Użytkownicy\ **Twoja nazwa użytkownika** \AppData\Local\Defold` (ang: `C:\Users\ **Your Username** \AppData\Local\Defold`) - * macOS: `/Users/ **Your Username** /Library/Application Support/` or `~/Library/Application Support/Defold` - * Linux: `~/.Defold` +Po pobraniu aktualizacji niebieski odnośnik zmieni się na `Restart to Update`. Kliknij go, aby ponownie uruchomić i otworzyć zaktualizowany edytor. -Można też dostać się do logów, kiedy Edytor jest uruchomiony z linii poleceń lub terminalu. Aby uruchomić Edytor z terminalu w systemie macOS użyj komendy: +![Restart to update](images/editor/restart_to_update.png) +## Preferences + +Ustawienia edytora możesz zmieniać w oknie `Preferences`. Aby je otworzyć, kliknij `File ▸ Preferences…` albo użyj skrótu Ctrl/⌘ Cmd + ,. + +Więcej szczegółów znajdziesz w [instrukcji Preferences](/manuals/editor-preferences). + +![Preferences](images/editor/preferences.png) + +## Logi edytora + +Jeśli napotkasz problem z edytorem i chcesz zgłosić błąd przez `Help ▸ Report Issue`, warto dołączyć pliki logów samego edytora. Aby otworzyć ich lokalizację w systemowej przeglądarce plików, kliknij `Help ▸ Show Logs`. + +Więcej informacji znajdziesz w [instrukcji uzyskiwania pomocy](/manuals/getting-help/#getting-help). + +![Show Logs](images/editor/show_logs.png) + +Pliki logów edytora można znaleźć tutaj: + + * Windows: `C:\Users\ **Your Username** \AppData\Local\Defold` + * macOS: `/Users/ **Your Username** /Library/Application Support/` albo `~/Library/Application Support/Defold` + * Linux: `$XDG_STATE_HOME/Defold` albo `~/.local/state/Defold` + +Możesz też uzyskać dostęp do logów edytora, gdy jest uruchomiony z terminala lub wiersza poleceń. Aby uruchomić edytor, użyj polecenia: + +```shell +# Linux: +$ ./path/to/Defold/Defold + +# macOS: +$ ./path/to/Defold.app/Contents/MacOS/Defold ``` -$ > ./path/to/Defold.app/Contents/MacOS/Defold + +## Editor Server + +Gdy edytor otwiera projekt, uruchamia serwer WWW na losowym porcie. Serwer może służyć do komunikacji z edytorem z poziomu innych aplikacji. Od wersji 1.11.0 numer portu jest zapisywany w pliku `.internal/editor.port`. + +Dodatkowo od wersji 1.11.0 plik wykonywalny edytora obsługuje opcję wiersza poleceń `--port` lub `-p`, która pozwala wskazać port przy uruchamianiu. Na przykład: + +```shell +# Windows +.\path\to\Defold\Defold.exe --port 8181 + +# Linux: +./path/to/Defold/Defold --port 8181 + +# macOS: +./path/to/Defold/Defold.app/Contents/MacOS/Defold --port 8181 ``` +## Stylizacja edytora + +Wygląd edytora można zmieniać za pomocą własnej stylizacji. Więcej informacji znajdziesz w [instrukcji stylizacji edytora](/manuals/editor-styling.md). ## FAQ :[Editor FAQ](../shared/editor-faq.md) diff --git a/docs/pl/manuals/font.md b/docs/pl/manuals/font.md index 4aee5f96..277f6cca 100644 --- a/docs/pl/manuals/font.md +++ b/docs/pl/manuals/font.md @@ -1,164 +1,268 @@ --- -title: Fonty w Defoldzie -brief: Ta instrukcja opisuje jak używać fontów w Twoich grach. +title: Fonty w silniku Defold +brief: Ta instrukcja opisuje, jak silnik Defold obsługuje fonty i jak wyświetlać tekst w grach. --- # Pliki fontów -Fonty (w odróżnieniu od czcionki będącej jedynie określeniem materiału zecerskiego) są używane do wyświetlania tekstu w kompoentach typu Label (etykieta) i węzłów tekstowych GUI. Defold wspiera poniższe formaty plików określających fonty: +Fonty służą do renderowania tekstu w komponentach Label (Etykieta) oraz węzłach tekstowych GUI. Defold obsługuje kilka formatów plików fontów: - TrueType - OpenType - BMFont -Fonty dodane do projektu są automatycznie konwertowane na format tekstury, który może być renderowany przez Defolda. Dostępne są dwie techniki renderowania czcionek, z własnymi korzyściami i wadami: +Fonty dodane do projektu są automatycznie konwertowane do formatu tekstury, który Defold potrafi renderować. Dostępne są dwie techniki renderowania fontów, a każda ma własne zalety i ograniczenia: - Bitmap -- Distance field (Pole odległości) +- Distance field -## Tworzenie fontów +## Fonty offline i runtime fonts -Aby stworzyć czcionkę do użycia w Defold, utwórz nowy plik fontu, wybierając opcję File ▸ New... z menu, a następnie wybierz Font. Możesz również kliknąć prawy przycisk myszy w lokalizacji w panelu *Assets* i wybrać New... ▸ Font. +Domyślnie konwersja do zrasteryzowanych obrazów glifów odbywa się podczas budowania projektu, czyli offline. Wadą tego podejścia jest to, że każdy font musi wyrasteryzować wszystkie możliwe glify już na etapie buildu, co może prowadzić do powstawania bardzo dużych tekstur zużywających pamięć i zwiększających rozmiar bundla. + +Jeśli używasz runtime fonts, pliki `.ttf` są dołączane do bundla bez zmian, a rasteryzacja odbywa się na żądanie podczas działania aplikacji. Dzięki temu zmniejsza się zarówno zużycie pamięci w runtime, jak i rozmiar bundla. + +## Obsługa układu tekstu, na przykład right-to-left + +Runtime fonts mają też tę zaletę, że obsługują pełny układ tekstu, na przykład right-to-left. +Obecnie wykorzystywane są biblioteki [HarfBuzz](https://github.com/harfbuzz/harfbuzz), [SheenBidi](https://github.com/Tehreer/SheenBidi), [libunibreak](https://github.com/adah1972/libunibreak) oraz [SkriBidi](https://github.com/memononen/Skribidi). + +Zobacz [włączanie runtime fonts](/manuals/font#enabling-runtime-fonts). + +## Kolekcja fontów + +Format pliku `.fontc` jest też nazywany font collection (kolekcją fontów). W trybie offline powiązany jest z nim tylko jeden font. +Przy użyciu runtime fonts z kolekcją fontów możesz powiązać więcej niż jeden plik fontu `.ttf`. + +Dzięki temu możesz używać kolekcji fontów podczas renderowania wielu tekstów w różnych językach i jednocześnie utrzymywać niskie zużycie pamięci. +Przykładowo możesz załadować kolekcję z japońskim fontem, skojarzyć ten font z bieżącym głównym fontem, a następnie zwolnić japońską kolekcję fontów. + +## Tworzenie fontu + +Aby utworzyć font do użycia w Defold, wybierz z menu File ▸ New..., a następnie Font. Możesz też kliknąć prawym przyciskiem myszy w wybranym miejscu panelu *Assets* i wybrać New... ▸ Font. ![New font name](images/font/new_font_name.png) -Nadaj nowemu plikowi fontu nazwę i kliknij OK. Nowy plik fontu otworzy się teraz w edytorze. +Nadaj nowemu plikowi nazwę i kliknij Ok. Nowy plik otworzy się teraz w edytorze. ![New font](images/font/new_font.png) -Przeciągnij font, który chcesz użyć do panelu *Assets* i upuść ją we właściwym miejscu. +Przeciągnij font, którego chcesz użyć, do panelu *Assets* i upuść go w odpowiednim miejscu. -Ustaw właściwość *Font* na plik fontu i dostosuj właściwości czcionki, jak to konieczne. +Ustaw właściwość *Font* na plik fontu i dostosuj pozostałe właściwości według potrzeb. -## Właściwości (Properties) +## Właściwości *Font* -: Plik TTF, OTF lub *.fnt*, który ma zostać użyty do generowania danych czcionki. +: Plik TTF, OTF albo *`.fnt`* używany do wygenerowania danych fontu. *Material* -: Materiał, który ma zostać użyty podczas renderowania fontu. Upewnij się, że zmieniasz to dla czcionek Distance Field i BMFonts (patrz poniżej, aby uzyskać szczegóły). +: Materiał używany do renderowania tego fontu. Pamiętaj, aby zmienić go dla Distance field i BMFonts. Szczegóły znajdziesz poniżej. *Output Format* -: Rodzaj danych czcionki, który jest generowany. +: Typ generowanych danych fontu. - - `TYPE_BITMAP` konwertuje importowany plik OTF lub TTF na teksturę arkusza fontu, gdzie dane bitmapy są używane do renderowania tekstu. Kanały koloru służą do kodowania kształtu twarzy (face shape), obrysu (outline) i cienia (shadow). Dla plików *.fnt* używana jest oryginalna bitmapa źródłowa. - - `TYPE_DISTANCE_FIELD` importowany font jest konwertowana na teksturę arkusza fontu, gdzie dane pikseli reprezentują nie piksele ekranu, ale odległości do krawędzi czcionki. Patrz poniżej po szczegóły. + - `TYPE_BITMAP` konwertuje zaimportowany plik OTF albo TTF na teksturę atlasu fontu, w której dane bitmapowe służą do renderowania tekstu. Kanały kolorów służą do kodowania kształtu znaku, obrysu i cienia. Dla plików *`.fnt`* źródłowa tekstura bitmapowa jest używana bez zmian. + - `TYPE_DISTANCE_FIELD` konwertuje zaimportowany font do tekstury atlasu fontu, w której dane pikseli reprezentują nie piksele ekranu, lecz odległości od krawędzi glifu. Szczegóły znajdziesz poniżej. *Render Mode* -: Tryb renderowania dla glifów. +: Tryb renderowania używany do renderowania glifów. - - `MODE_SINGLE_LAYER` generuje pojedynczy kwadrat (quad) dla każdego znaku. - - `MODE_MULTI_LAYER` generuje osobne kwadraty (quady) dla kształtu glifu, obrysu i cieni, odpowiednio. Warstwy są renderowane od tyłu do przodu, co zapobiega zasłanianiu wcześniej renderowanych znaków, jeśli obrys jest szerszy niż odległość między glifami. Ten tryb renderowania umożliwia również prawidłowe przesunięcie cienia, zgodnie z właściwościami cienia X/Y w zasobie fontu. + - `MODE_SINGLE_LAYER` tworzy pojedynczy quad dla każdego znaku. + - `MODE_MULTI_LAYER` tworzy osobne quady odpowiednio dla kształtu glifu, obrysu i cienia. Warstwy są renderowane od tyłu do przodu, co zapobiega zasłanianiu wcześniej wyrenderowanych znaków, jeśli obrys jest szerszy niż odstęp między glifami. Ten tryb renderowania umożliwia też poprawne przesuwanie cienia zgodnie z właściwościami Shadow X/Y w zasobie fontu. *Size* : Docelowy rozmiar glifów w pikselach. *Antialias* -: Określa, czy czcionka ma być wygładzana (antyaliasing), gdy jest wypalana na docelowej bitmapie. Ustaw na 0, jeśli chcesz uzyskać dokładne renderowanie czcionki piksel po pikselu. +: Określa, czy font ma być wygładzany podczas wypalania na docelowej bitmapie. Ustaw 0, jeśli chcesz uzyskać pikselowo idealne renderowanie. *Alpha* -: Przezroczystość glifu. Od 0,0 do 1,0, gdzie 0,0 oznacza przezroczystość, a 1,0 nieprzezroczystość. +: Przezroczystość glifu. Zakres 0.0-1.0, gdzie 0.0 oznacza pełną przezroczystość, a 1.0 pełną nieprzezroczystość. *Outline Alpha* -: Przezroczystość generowanego obrysu. Od 0,0 do 1,0. +: Przezroczystość wygenerowanego obrysu. Zakres 0.0-1.0. *Outline Width* -: Szerokość generowanego obrysu w pikselach. Ustaw na 0, jeśli nie chcesz obrysu. +: Szerokość wygenerowanego obrysu w pikselach. Ustaw 0, jeśli obrys nie jest potrzebny. *Shadow Alpha* -: Przezroczystość generowanego cienia. Od 0,0 do 1,0. +: Przezroczystość wygenerowanego cienia. Zakres 0.0-1.0. ::: sidenote -Wsparcie dla cieni jest aktywowane przez wbudowane shadery materiałów czcionek i obsługuje zarówno tryb renderowania warstwowego, jak i jednowarstwowego. Jeśli nie potrzebujesz warstwowego renderowania czcionek ani obsługi cieni, lepiej jest użyć prostszego shadera, takiego jak wbudowany shader `builtins/font-singlelayer.fp`. +Obsługa cienia jest włączona we wbudowanych shaderach materiałów fontów i działa zarówno w trybie renderowania jedno-, jak i wielowarstwowego. Jeśli nie potrzebujesz warstwowego renderowania fontów ani obsługi cienia, najlepiej użyć prostszego shadera, takiego jak *`builtins/font-singlelayer.fp`*. ::: *Shadow Blur* -: Dla czcionek bitmapowych to ustawienie określa liczbę razy, jaka ma być zastosowane małe jądro rozmazywania do każdego glifu czcionki. Dla czcionek pola odległości (distance field) to ustawienie odpowiada rzeczywistej szerokości w pikselach rozmycia. +: Dla fontów bitmapowych to ustawienie określa, ile razy ma zostać zastosowane małe jądro rozmycia do każdego glifu. Dla Distance field ta wartość odpowiada rzeczywistej szerokości rozmycia w pikselach. *Shadow X/Y* -: Poziome i pionowe przesunięcie w pikselach generowanego cienia. To ustawienie wpłynie tylko na cień glifu, gdy tryb renderowania jest ustawiony na `MODE_MULTI_LAYER`. +: Poziome i pionowe przesunięcie wygenerowanego cienia w pikselach. To ustawienie wpływa na cień glifu tylko wtedy, gdy *Render Mode* ma wartość `MODE_MULTI_LAYER`. + +*Characters* +: Określa, które znaki mają zostać uwzględnione w foncie. Domyślnie pole to zawiera drukowalne znaki ASCII o kodach 32-126. Możesz dodawać lub usuwać znaki, aby uwzględnić ich więcej albo mniej. -*Extra Characters* -: Domyślnie font będzie zawierać drukowalne znaki ASCII (kody znaków 32-126). Aby ręcznie dodać dodatkowe znaki, wymień je w polu właściwości. + Dla runtime fonts ten tekst działa też jako wstępne podgrzewanie pamięci podręcznej właściwymi glifami. Dzieje się to podczas ładowania. Zobacz `font.prewarm_text()`. ::: sidenote -Znaki ASCII do druku: +Drukowalne znaki ASCII to: space ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ \` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ ::: *All Chars* -: Jeśli zaznaczysz tę właściwość, wszystkie glify dostępne w pliku źródłowym zostaną uwzględnione w wyniku. +: Po zaznaczeniu tej właściwości wszystkie glify dostępne w pliku źródłowym zostaną uwzględnione w wyniku. *Cache Width/Height* -: Ogranicza rozmiar mapy bitowej pamięci podręcznej glifów. Kiedy silnik renderuje tekst, przeszukuje mapę bitową, aby znaleźć glif z pamięci podręcznej. Jeśli glifu tam nie ma, zostanie on dodany do pamięci podręcznej przed renderowaniem. Jeśli mapa bitowa pamięci podręcznej jest zbyt mała, aby pomieścić wszystkie glify, które silnik ma zrenderować, zostanie wygenerowany błąd (`ERROR:RENDER: Out of available cache cells! Consider increasing cache_width or cache_height for the font.`), czyli "Brak dostępnych komórek w pamięci podręcznej! Rozważ zwiększenie `cache_width` lub `cache_height` dla fontu". +: Ogranicza rozmiar bitmapy pamięci podręcznej glifów. Gdy silnik renderuje tekst, wyszukuje glif w bitmapie cache. Jeśli go tam nie ma, glif zostaje dodany do cache przed renderowaniem. Jeśli bitmapa cache jest zbyt mała, aby pomieścić wszystkie glify, które silnik ma wyrenderować, zostanie zgłoszony błąd (`ERROR:RENDER: Out of available cache cells! Consider increasing cache_width or cache_height for the font.`). - Jeśli ustawisz to na 0, rozmiar pamięci podręcznej będzie ustawiany automatycznie. + Jeśli ustawisz tę właściwość na 0, rozmiar cache jest dobierany automatycznie i może urosnąć maksymalnie do 2048x4096. -## Fonty pola odległości (Distance field) +## Fonty typu Distance field -Fonty pola odległości przechowują odległość od krawędzi glifu w teksturze zamiast danych w postaci mapy bitowej. Gdy silnik renderuje font, wymagany jest specjalny shader do interpretowania danych odległości i ich wykorzystania do rysowania glifu. Fonty pola odległości są bardziej wymagające pod względem zasobów niż fonty bitmapowe, ale pozwalają na większą elastyczność skalowania. +Fonty typu Distance field przechowują w teksturze odległość do krawędzi glifu zamiast danych bitmapowych. Gdy silnik renderuje taki font, potrzebny jest specjalny shader interpretujący dane odległości i wykorzystujący je do rysowania glifu. Fonty typu Distance field są bardziej zasobożerne niż fonty bitmapowe, ale zapewniają większą elastyczność skalowania. ![Distance field font](images/font/df_font.png) -Upewnij się, że zmieniasz właściwość *Material* czcionki na *builtins/fonts/font-df.material* (lub inny materiał, który może obsługiwać dane pola odległości) podczas tworzenia fontu, w przeciwnym razie czcionka nie będzie używać odpowiedniego shadera podczas renderowania na ekranie. +Pamiętaj, aby przy tworzeniu fontu zmienić właściwość *Material* na *`builtins/fonts/font-df.material`* lub inny materiał obsługujący dane Distance field. W przeciwnym razie font nie będzie używał poprawnego shadera podczas renderowania na ekranie. -## Fonty bitmapowe BMFonts +## Bitmap BMFonts -Oprócz generowanych map bitowych, Defold obsługuje fonty w formacie bitmapowym "BMFont". Te fonty składają się z arkusza fontu PNG z glifami. Ponadto plik *.fnt* zawiera informacje o tym, gdzie na arkuszu znajduje się każdy glif, a także informacje o rozmiarze i kerningu. (Należy pamiętać, że Defold nie obsługuje wersji XML pliku *.fnt*, która jest używana przez Phaser i niektóre inne narzędzia). +Oprócz generowanych bitmap Defold obsługuje także wstępnie przygotowane fonty bitmapowe w formacie BMFont. Taki font składa się z arkusza fontu PNG zawierającego wszystkie glify. Dodatkowo plik *`.fnt`* zawiera informacje o położeniu każdego glifu na arkuszu, a także o jego rozmiarze i kerningu. Pamiętaj, że Defold nie obsługuje wersji XML formatu *`.fnt`*, używanej przez Phaser i niektóre inne narzędzia. -Te rodzaje fontów nie przynoszą żadnej poprawy wydajności w porównaniu do fontów bitmapowych generowanych z plików czcionek TrueType lub OpenType, ale pozwalają na dowolne grafiki, kolorowanie i cienie bezpośrednio w obrazie. +Takie fonty nie przynoszą poprawy wydajności względem fontów bitmapowych generowanych z plików TrueType albo OpenType, ale mogą zawierać dowolną grafikę, kolorowanie i cienie bezpośrednio w obrazie. -Dodaj wygenerowane pliki *.fnt* i *.png* do swojego projektu Defold. Te pliki powinny znajdować się w tym samym folderze. Utwórz nowy plik fontu i ustaw właściwość *font* na plik *.fnt*. Upewnij się, że *output_format* jest ustawiony na `TYPE_BITMAP`. Defold nie wygeneruje mapy bitowej, ale użyje tej dostarczonej w formacie PNG. +Dodaj wygenerowane pliki *`.fnt`* i *`.png`* do projektu Defold. Pliki te muszą znajdować się w tym samym katalogu. Utwórz nowy plik fontu i ustaw właściwość *Font* na plik *`.fnt`*. Upewnij się, że *Output Format* ma wartość `TYPE_BITMAP`. Defold nie wygeneruje wtedy bitmapy, tylko użyje tej dostarczonej w PNG. ::: sidenote -Aby stworzyć font BMFont, musisz użyć narzędzia, które może generować odpowiednie pliki. Istnieje kilka opcji: +Aby utworzyć BMFont, potrzebujesz narzędzia generującego odpowiednie pliki. Możesz użyć między innymi: -* [Bitmap Font Generator](http://www.angelcode.com/products/bmfont/), narzędzie dostępne tylko na platformę Windows, dostarczone przez AngelCode. -* [Shoebox](http://renderhjs.net/shoebox/), darmowa aplikacja oparta na Adobe Air dla platformy Windows i macOS. -* [Hiero](https://github.com/libgdx/libgdx/wiki/Hiero), narzędzie typu open source oparte na Java. -* [Glyph Designer](https://71squared.com/glyphdesigner), komercyjne narzędzie dla platformy macOS od 71 Squared. -* [bmGlyph](https://www.bmglyph.com), komercyjne narzędzie dla platformy macOS od Sovapps. +* [Bitmap Font Generator](http://www.angelcode.com/products/bmfont/), narzędzia tylko dla Windows od AngelCode. +* [Shoebox](http://renderhjs.net/shoebox/), darmowej aplikacji opartej na Adobe Air dla Windows i macOS. +* [Hiero](https://libgdx.com/wiki/tools/hiero), narzędzia open source opartego na Java. +* [Glyph Designer](https://71squared.com/glyphdesigner), komercyjnego narzędzia dla macOS od 71 Squared. +* [bmGlyph](https://www.bmglyph.com), komercyjnego narzędzia dla macOS od Sovapps. ::: ![BMfont](images/font/bm_font.png) -Aby font renderował się poprawnie, nie zapomnij ustawić właściwości materiału na *builtins/fonts/font-fnt.material* podczas tworzenia czcionki. +Aby font renderował się poprawnie, pamiętaj o ustawieniu właściwości materiału na *`builtins/fonts/font-fnt.material`* podczas tworzenia fontu. ## Artefakty i najlepsze praktyki -Ogólnie rzecz biorąc, fonty bitmapowe są najlepsze, gdy font jest renderowany bez skalowania. Są szybsze do renderowania na ekranie niż fonty pola odległości (Distance Field). +Ogólnie fonty bitmapowe sprawdzają się najlepiej wtedy, gdy są renderowane bez skalowania. Są też szybsze w renderowaniu na ekranie niż fonty typu Distance field. -Fonty pola odległości bardzo dobrze reagują na skalowanie w górę. Z kolei fonty bitmapowe, będąc jedynie pikselowymi obrazami, zwiększają swoją wielkość wraz ze skalowaniem czcionki, co prowadzi do efektów blokowych artefaktów. Oto przykład fontu o rozmiarze 48 pikseli, powiększonej 4-krotnie. +Fonty typu Distance field bardzo dobrze znoszą powiększanie. Fonty bitmapowe natomiast są po prostu obrazami pikselowymi, więc przy zwiększaniu rozmiaru piksele rosną razem z fontem, powodując widoczne blokowe artefakty. Poniżej znajduje się przykład fontu o rozmiarze 48 pikseli, powiększonego 4 razy. ![Fonts scaled up](images/font/scale_up.png) -Podczas zmniejszania rozmiaru, tekstury fontów bitmapowych mogą być ładnie i efektywnie zmniejszone i wygładzone przez GPU. Font bitmapowy lepiej utrzymuje swoją kolorystykę niż font pola odległości. Oto przybliżenie tej samej próbki fontu o rozmiarze 48 pikseli, zmniejszonego do 1/5 rozmiaru: +Przy zmniejszaniu rozmiaru tekstury bitmapowe mogą być skutecznie i estetycznie skalowane w dół oraz wygładzane przez GPU. Font bitmapowy zachowuje też kolor lepiej niż font typu Distance field. Poniżej znajdziesz powiększenie tego samego przykładowego fontu o rozmiarze 48 pikseli, zmniejszonego do 1/5 oryginalnego rozmiaru: ![Fonts scaled down](images/font/scale_down.png) -Fonty pola odległości muszą być renderowane w celu uzyskania docelowego rozmiaru, który jest wystarczająco duży, aby pomieścić informacje o odległości, które mogą wyrazić krzywizny glifów fontu. To ta sama czcionka, co powyżej, ale o rozmiarze 18 pikseli i powiększona 10-krotnie. Wyraźnie widać, że jest to zbyt małe, aby zakodować kształty tego fontu: +Fonty typu Distance field muszą być renderowane do rozmiaru docelowego wystarczająco dużego, aby pomieścić informacje o odległości opisujące krzywizny glifów. Poniżej użyto tego samego fontu co wyżej, ale w rozmiarze 18 pikseli i powiększono go 10 razy. Wyraźnie widać, że ten rozmiar jest zbyt mały, by poprawnie zakodować kształty tego kroju pisma: ![Distance field artifacts](images/font/df_artifacts.png) -Jeśli nie potrzebujesz obsługi cieni lub konturów, ustaw ich odpowiednie wartości alfa na zero. W przeciwnym razie dane cienia i konturu nadal zostaną generowane, zajmując zbędną pamięć. +Jeśli nie potrzebujesz cienia ani obrysu, ustaw ich wartości alfa na zero. W przeciwnym razie dane cienia i obrysu nadal będą generowane, zajmując niepotrzebnie pamięć. ## Pamięć podręczna fontu -Zasób fontu w Defoldzie składa się z dwóch elementów w czasie rzeczywistym: tekstury i danych fontu. -* Dane fontu składają się z listy wpisów glifów, z których każdy zawiera podstawowe informacje o kerningu oraz dane mapy bitowej glifu. -* Tekstura jest wewnętrznie nazywana "teksturą pamięci podręcznej glifów" i jest używana podczas renderowania tekstu dla konkretnego fontu. +Zasób fontu w Defold daje w runtime dwie rzeczy: teksturę i dane fontu. -Podczas renderowania tekstu w czasie rzeczywistym, silnik najpierw przeszukuje glify do renderowania, aby sprawdzić, które glify są dostępne w pamięci podręcznej (cache) tekstury. Każdy glif, którego brakuje w pamięci podręcznej tekstury glifów, spowoduje przekazanie tekstury z bitmapowymi danymi zapisanymi w danych fontu. +* Dane fontu składają się z listy wpisów glifów, z których każdy zawiera podstawowe informacje o kerningu oraz dane bitmapowe tego glifu. +* Tekstura jest wewnętrznie nazywana glyph cache texture (teksturą pamięci podręcznej glifów) i jest używana podczas renderowania tekstu dla konkretnego fontu. -Każdy glif jest umieszczany wewnętrznie w pamięci podręcznej zgodnie z bazą fontu, co pozwala na obliczanie lokalnych współrzędnych tekstury glifu w odpowiedniej komórce pamięci podręcznej w shaderze. Oznacza to, że można osiągnąć pewne efekty tekstowe, takie jak gradienty lub nakładki tekstury dynamicznie. Silnik udostępnia metryki dotyczące pamięci podręcznej tekstury dla shadera za pośrednictwem specjalnej stałej shadera o nazwie `texture_size_recip`, która zawiera następujące informacje w komponentach wektora: +Podczas renderowania tekstu w runtime silnik najpierw przechodzi po glifach, które mają zostać wyrenderowane, i sprawdza, które z nich są dostępne w pamięci podręcznej tekstury. Każdy brakujący glif powoduje przesłanie do tekstury danych bitmapowych przechowywanych w danych fontu. -* `texture_size_recip.x` to odwrotność szerokości pamięci podręcznej -* `texture_size_recip.y` to odwrotność wysokości pamięci podręcznej -* `texture_size_recip.z` to stosunek szerokości komórki pamięci podręcznej do szerokości pamięci podręcznej -* `texture_size_recip.w` to stosunek wysokości komórki pamięci podręcznej do wysokości pamięci podręcznej +Każdy glif jest wewnętrznie umieszczany w cache zgodnie z linią bazową fontu, co umożliwia obliczanie lokalnych współrzędnych tekstury glifu w odpowiadającej mu komórce cache bezpośrednio w shaderze. Dzięki temu można uzyskać dynamiczne efekty tekstowe, takie jak gradienty albo nakładki tekstur. Silnik udostępnia shaderowi metryki cache przez specjalną stałą shadera `texture_size_recip`, która zawiera następujące informacje w komponentach wektora: -Na przykład, aby wygenerować gradient w fragmencie shadera, wystarczy napisać: +* `texture_size_recip.x` to odwrotność szerokości cache +* `texture_size_recip.y` to odwrotność wysokości cache +* `texture_size_recip.z` to stosunek szerokości komórki cache do szerokości całego cache +* `texture_size_recip.w` to stosunek wysokości komórki cache do wysokości całego cache + +Na przykład, aby wygenerować gradient w shaderze fragmentu, wystarczy zapisać: `float horizontal_gradient = fract(var_texcoord0.y / texture_size_recip.w);` -Aby uzyskać więcej informacji na temat jednolitych shaderów, zobacz [instrukcje do shaderów](/manuals/shader). +Więcej informacji o uniformach shaderów znajdziesz w [instrukcji do shaderów](/manuals/shader). + +## Włączanie runtime fonts + +Można używać generowania w runtime dla fontów typu SDF, gdy korzystasz z fontów TrueType (`.ttf`). +Takie podejście może znacząco zmniejszyć rozmiar pobieranych danych i zużycie pamięci w runtime w grze Defold. +Niewielką wadą jest asynchroniczny charakter generowania każdego glifu. + +* Włącz tę funkcję, ustawiając `font.runtime_generation` w `game.project`. + +* Dodaj [App Manifest](/manuals/app-manifest) i włącz opcję `Use full text layout system`. + Spowoduje to zbudowanie niestandardowego silnika z włączoną obsługą tej funkcji. + +::: sidenote +Ta funkcja jest obecnie eksperymentalna, ale docelowo ma stać się domyślnym sposobem pracy. +::: + +::: important +Ustawienie `font.runtime_generation` wpływa na wszystkie fonty `.ttf` w projekcie. +::: + +### Skryptowanie fontów + +#### Wstępne podgrzewanie cache glifów + +Aby ułatwić pracę z runtime fonts, obsługują one wstępne podgrzewanie cache glifów. +Oznacza to, że font wygeneruje glify wypisane w polu *Characters*. + +::: sidenote +Jeśli zaznaczone jest `All Chars`, podgrzewanie wstępne nie zostanie wykonane, ponieważ niweczyłoby to korzyść z niewymuszania generowania wszystkich glifów naraz. +::: + +Jeśli pole `Characters` w pliku `.fontc` jest ustawione, jego zawartość służy jako tekst do ustalenia, które glify trzeba dodać do cache. + +Możesz też ręcznie zaktualizować cache glifów, wywołując `font.prewarm_text(font_collection, text, callback)`. Funkcja przyjmuje callback informujący, że wszystkie brakujące glify zostały dodane do cache i można bezpiecznie wyświetlić tekst na ekranie. + +### Dodawanie i usuwanie fontów z kolekcji fontów + +Dla runtime fonts można dodawać lub usuwać fonty (`.ttf`) z font collection. +Jest to przydatne, gdy duży font został podzielony na kilka plików dla różnych zestawów znaków, na przykład CJK. + +::: important +Dodanie fontu do font collection nie powoduje automatycznego załadowania ani wyrenderowania wszystkich glifów. +::: + +```lua +-- pobierz główny font +local font_collection = go.get("#label", "font") +font.add_font(font_collection, self.language_ttf_hash) + +-- pobierz font wybranego języka +local font_collection_language = go.get("localization_japanese#label", "font") +local font_info = font.get_info(font_collection_language) +self.language_ttf_hash = font_info.fonts[1].path_hash -- pobierz pierwszy font (ten wskazany w edytorze) +font.add_font(self.font_collection, self.language_ttf_hash) -- zwiększa licznik referencji fontu +``` + +```lua +-- usuń referencję do fontu +font.add_font(self.font_collection, self.language_ttf_hash) +``` + +### Wstępne podgrzewanie glifów + +Aby poprawnie wyświetlić tekst przy użyciu runtime font, glify muszą zostać rozwiązane. `font.prewarm_text()` robi to za ciebie. +Jest to operacja asynchroniczna. Gdy się zakończy i otrzymasz callback, możesz bezpiecznie przejść do wyświetlenia dowolnej wiadomości zawierającej te glify. + +::: important +Jeśli cache glifów się zapełni, najstarszy glif zostanie z niego usunięty. +::: + +```lua +font.prewarm_text(self.font_collection, info.text, function (self, request_id, result, err) + if result then + print("PREWARMING OK!") + label.set_text(self.label, info.text) + else + print("Error prewarming text:", err) + end + end) +``` diff --git a/docs/pl/manuals/gui-layouts.md b/docs/pl/manuals/gui-layouts.md index 87da2cbc..fea44558 100644 --- a/docs/pl/manuals/gui-layouts.md +++ b/docs/pl/manuals/gui-layouts.md @@ -1,21 +1,19 @@ --- -title: Układy interfejsu w Defoldzie -brief: Defold supports GUIs that automatically adapt to screen orientation changes on mobile devices. This document explains how the feature works. +title: Układy GUI w silniku Defold +brief: Defold obsługuje GUI, które automatycznie dostosowuje się do zmian orientacji ekranu na urządzeniach mobilnych. Ten dokument wyjaśnia, jak działa ta funkcja. --- -# Układy interfejsu +# Układy -Układy interfejsu (ang. layouts) to wspierana przez Defold opcja automatycznego dostosowywania się do zmian orientacji ekranu na urządzeniach mobilnych. W tym dokumencie wyjaśniono, jak działa ta funkcjonalność. - -Defold supports GUIs that automatically adapt to screen orientation changes on mobile devices. By using this feature you can design GUIs that adapt to the orientation and aspect ratio of a range of screen sizes. It is also possible to create layouts that match particular device models. +Defold obsługuje GUI, które automatycznie dostosowuje się do zmian orientacji ekranu na urządzeniach mobilnych. Dzięki tej funkcji możesz projektować GUI dopasowujące się do orientacji i proporcji obrazu na ekranach o różnych rozmiarach. Możliwe jest też tworzenie układów dopasowanych do konkretnych modeli urządzeń. ## Tworzenie profili wyświetlania -Domyślnie, w ustawieniach *game.project*, używa się wbudowanego pliku z ustawieniami profili wyświetlania (ang. display profiles) ("builtins/render/default.display_profiles"). Domyślne profile to `"Landscape"` (1280 pikseli szerokości i 720 pikseli wysokości) i `"Portrait"` (720 pikseli szerokości i 1280 pikseli wysokości). W profilach tych nie ustawiono modeli urządzeń, dlatego pasują one do dowolnego urządzenia. +Domyślnie ustawienia w pliku *game.project* wskazują wbudowany plik profili wyświetlania: `builtins/render/default.display_profiles`. Domyślne profile to `Landscape` (1280 pikseli szerokości i 720 pikseli wysokości) oraz `Portrait` (720 pikseli szerokości i 1280 pikseli wysokości). W tych profilach nie ustawiono modeli urządzeń, więc będą pasować do dowolnego urządzenia. -Aby utworzyć nowy plik z ustawieniami profili, skopiuj istniejący z folderu "builtins" lub kliknij prawym przyciskiem myszy w odpowiednim miejscu w widoku *Assets* i wybierz New... -> Display Profiles". Nadaj nowemu plikowi odpowiednią nazwę i kliknij OK. +Aby utworzyć nowy plik profili, skopiuj istniejący z folderu `builtins` albo kliknij prawym przyciskiem myszy odpowiednie miejsce w widoku *Assets* i wybierz New... ▸ Display Profiles. Nadaj nowemu plikowi odpowiednią nazwę i kliknij Ok. -Edytor otworzy teraz nowy plik do edycji. Dodaj nowe profile, klikając + na liście *Profiles*. Dla każdego profilu dodaj zestaw "kwalifikatorów" (*qualifiers*) dla profilu: +Edytor otworzy teraz nowy plik do edycji. Dodaj nowe profile, klikając + na liście *Profiles*. Dla każdego profilu dodaj zestaw *qualifiers*: Width : Szerokość kwalifikatora w pikselach. @@ -24,77 +22,118 @@ Height : Wysokość kwalifikatora w pikselach. Device Models -: Lista modeli urządzeń oddzielonych przecinkami. Nazwa modelu urządzenia pasuje do początku nazwy modelu urządzenia. Przykład: `iPhone10` pasuje do modeli "iPhone10,\*". Nazwy modeli z przecinkami powinny być umieszczone w cudzysłowie, np. `"iPhone10,3", "iPhone10,6"` pasuje do modeli iPhone X (https://www.theiphonewiki.com/wiki/Models). Należy zauważyć, że tylko platformy Android i iOS raportują nazwę modelu urządzenia podczas wywoływania funkcji `sys.get_sys_info`. Inne platformy zwracają pusty ciąg znaków i dlatego nigdy nie wybiorą profilu wyświetlania z kwalifikatorem modelu urządzenia. +: Lista modeli urządzeń oddzielonych przecinkami. Nazwa modelu dopasowuje początek nazwy modelu urządzenia, na przykład `iPhone10` dopasuje modele `iPhone10,*`. Nazwy modeli zawierające przecinki powinny być ujęte w cudzysłów, czyli `"iPhone10,3", "iPhone10,6"` dopasuje modele iPhone X (zobacz [iPhone wiki](https://www.theiphonewiki.com/wiki/Models)). Pamiętaj, że tylko platformy Android i iOS zwracają model urządzenia przy wywołaniu `sys.get_sys_info()`. Inne platformy zwracają pusty ciąg znaków, więc nigdy nie wybiorą profilu wyświetlania, który ma kwalifikator `Device Models`. ![New display profiles](images/gui-layouts/new_profiles.png) -Należy również określić, że silnik powinien używać nowych profili. Otwórz *game.project* i wybierz plik z profilami wyświetlania w ustawieniach *Display Profiles* w sekcji *display*. - +Musisz też wskazać, że silnik ma używać nowego pliku profili. Otwórz *game.project* i ustaw plik profili wyświetlania w opcji *Display Profiles* w sekcji *display*: ![Settings](images/gui-layouts/settings.png) -Jeśli chcesz, aby silnik automatycznie przełączał się między układami w orientacji pionowej i poziomej po obróceniu urządzenia, zaznacz opcję *Dynamic Orientation*. Silnik będzie dynamicznie wybierać pasujący układ i zmieniać wybór w razie zmiany orientacji urządzenia. +Jeśli chcesz, aby silnik automatycznie przełączał się między układami pionowymi i poziomymi po obróceniu urządzenia, zaznacz pole *Dynamic Orientation*. Silnik będzie wtedy dynamicznie wybierał pasujący układ i zmieniał go przy zmianie orientacji urządzenia. + +### Automatyczny wybór układu (Display Profiles) -## Układy interfejsu +Zasób Display Profiles ma opcję `Auto Layout Selection` (domyślnie włączoną). Gdy jest włączona, silnik automatycznie wybiera najlepiej pasujący układ GUI zarówno podczas tworzenia sceny, jak i przy zmianie rozmiaru okna lub ekranu. Gdy jest wyłączona, silnik nie zmienia układów automatycznie. Wtedy do ręcznego przełączania układów z poziomu skryptu GUI używa się `gui.set_layout()`. To ustawienie jest zapisane w pliku Display Profiles i wpływa na wszystkie sceny GUI. -Obecny zestaw profili wyświetlania można wykorzystać do tworzenia wariantów układów (layouts) węzłów interfejsu. Aby dodać nowy układ do sceny interfejsu, kliknij prawym przyciskiem myszy na ikonie *Layouts* w widoku *Outline* i wybierz Add ▸ Layout ▸ .... +## Układy GUI + +Aktualny zestaw profili wyświetlania można wykorzystać do tworzenia wariantów układów dla zestawu węzłów GUI. Aby dodać nowy układ do sceny GUI, kliknij prawym przyciskiem myszy ikonę *Layouts* w widoku *Outline* i wybierz Add ▸ Layout ▸ ...: ![Add layout to scene](images/gui-layouts/add_layout.png) -Podczas edycji sceny interfejsu wszystkie węzły są edytowane w określonym układzie. Obecnie wybrany układ jest widoczny w rozwijanym menu układu sceny interfejsu w pasku narzędziowym. Jeśli nie wybrano żadnego układu, węzły są edytowane w układzie *Default*. +Podczas edycji sceny GUI wszystkie węzły są edytowane w ramach konkretnego układu. Aktualnie wybrany układ jest widoczny na liście rozwijanej układów sceny GUI na pasku narzędzi. Jeśli nie wybierzesz żadnego układu, węzły są edytowane w układzie *Default*. ![Layouts toolbar](images/gui-layouts/toolbar.png) ![portrait edit](images/gui-layouts/portrait.png) -Każda zmiana właściwości węzła dokonana z wybranym układem, nadpisuje właściwość w odniesieniu do układu *Default*. Właściwości, które zostały nadpisane, są oznaczone kolorem niebieskim. Węzły z nadpisanymi właściwościami również są oznaczone kolorem niebieskim. Możesz kliknąć przycisk resetowania obok dowolnej nadpisanej właściwości, aby przywrócić ją do pierwotnej wartości. +Każda zmiana właściwości węzła, którą wykonasz przy wybranym układzie, *nadpisuje* tę właściwość względem układu *Default*. Nadpisane właściwości są oznaczane na niebiesko. Węzły z nadpisanymi właściwościami również są oznaczane na niebiesko. Możesz kliknąć przycisk resetowania obok dowolnej nadpisanej właściwości, aby przywrócić jej pierwotną wartość. ![landscape edit](images/gui-layouts/landscape.png) -Układ nie może usuwać ani tworzyć nowych węzłów, może jedynie nadpisywać właściwości. Jeśli chcesz usunąć węzeł z układu, możesz albo przenieść węzeł poza obszar ekranu, albo usunąć go za pomocą logiki skryptu. Należy także zwrócić uwagę na obecnie wybrany układ. Jeśli dodasz układ do projektu, nowy układ będzie konfigurowany zgodnie z aktualnie wybranym układem. Kopiowanie i wklejanie węzłów uwzględnia obecnie wybrany układ zarówno podczas kopiowania, jak i podczas wklejania. +Układ nie może usuwać ani tworzyć nowych węzłów, może jedynie nadpisywać właściwości. Jeśli chcesz usunąć węzeł z układu, możesz przenieść go poza ekran albo usunąć go w logice skryptu. Zwracaj też uwagę na aktualnie wybrany układ. Jeśli dodasz nowy układ do projektu, zostanie on skonfigurowany według układu wybranego w danej chwili. Kopiowanie i wklejanie węzłów również uwzględnia aktualnie wybrany układ, zarówno przy kopiowaniu, jak i przy wklejaniu. ## Dynamiczny wybór profilu -Dynamiczny dopasowywacz układu ocenia każdy kwalifikator profilu wyświetlania według następujących reguł: +Gdy `Auto Layout Selection` jest włączone, silnik automatycznie wybiera najlepiej pasujący układ. Mechanizm dynamicznego dopasowania ocenia każdy kwalifikator profilu wyświetlania według następujących reguł: -1. Jeśli nie jest ustawiony model urządzenia albo model urządzenia jest i pasuje do profilu, obliczana jest ocena (S) dla kwalifikatora. +1. Jeśli nie ustawiono modelu urządzenia albo model urządzenia pasuje, dla kwalifikatora obliczana jest ocena (S). -2. Ocena (S) jest obliczana na podstawie powierzchni ekranu (`A`), powierzchni z kwalifikatora (`A_Q`), proporcji obrazu ekranu (`R`) i proporcji obrazu z kwalifikatora (`R_Q`). +2. Ocena (S) jest obliczana na podstawie powierzchni ekranu (`A`), powierzchni z kwalifikatora (`A_Q`), proporcji obrazu ekranu (`R`) i proporcji obrazu kwalifikatora (`R_Q`): -3. Profil z najniższą oceną jest wybierany, jeśli orientacja (landscape lub portrait) kwalifikatora pasuje do orientacji ekranu. +3. Wybierany jest profil z kwalifikatorem o najniższej ocenie, jeśli orientacja kwalifikatora (landscape lub portrait) pasuje do orientacji ekranu. -4. Jeśli nie znaleziono profilu z kwalifikatorem o tej samej orientacji, wybierany jest profil z najlepszą oceną kwalifikatora o innej orientacji. +4. Jeśli nie znaleziono profilu z kwalifikatorem o tej samej orientacji, wybierany jest profil z najlepiej ocenionym kwalifikatorem o przeciwnej orientacji. -5. Jeśli nie można wybrać żadnego profilu, stosowany jest profil awaryjny *Default*. +5. Jeśli nie da się wybrać żadnego profilu, używany jest zapasowy profil *Default*. -Ponieważ układ *Default* jest stosowany jako profil awaryjny w czasie rzeczywistym, jeśli nie ma lepszego pasującego układu, oznacza to, że jeśli dodasz układ *Landscape*, będzie to najlepsze dopasowanie dla wszystkich orientacji, dopóki nie dodasz także układu *Portrait*. +Ponieważ układ *Default* jest używany w runtime jako fallback, gdy nie ma lepiej dopasowanego układu, oznacza to, że jeśli dodasz układ `Landscape`, będzie on najlepszym dopasowaniem dla *wszystkich* orientacji, dopóki nie dodasz także układu `Portrait`. ## Komunikaty o zmianie układu -Kiedy silnik zmienia układ w wyniku obracania urządzenia, wysyłana jest wiadomość `layout_changed` do skryptów komponentów GUI, które są dotknięte zmianą. Komunikat zawiera zahaszowany identyfikator (hashed id) układu, dzięki czemu skrypt może wykonywać logikę zależnie od wybranego układu. - -When the engine switches layout as a result of device rotation, a `layout_changed` message is posted to the GUI components' scripts that are affected by the change. The message contains the hashed id of the layout so the script can perform logic depending on which layout is selected: +Gdy układ się zmienia, do skryptu komponentu GUI wysyłana jest wiadomość `layout_changed`. Dzieje się tak, gdy silnik zmienia układ automatycznie (`Auto Layout Selection` jest włączone) albo gdy skrypt wywoła `gui.set_layout()` i układ rzeczywiście się zmieni. Wiadomość zawiera zahaszowane id układu, dzięki czemu skrypt może wykonać logikę zależnie od wybranego układu: ```lua function on_message(self, message_id, message, sender) if message_id == hash("layout_changed") and message.id == hash("My Landscape") then - --- zmieniono układ na landscape + -- zmiana układu na poziomy elseif message_id == hash("layout_changed") and message.id == hash("My Portrait") then - -- zmieniono układ na portrait + -- zmiana układu na pionowy end end ``` -Ponadto, bieżący skrypt renderowania otrzymuje komunikat za każdym razem, gdy zmienia się okno (widok gry), a to obejmuje zmiany orientacji. +Dodatkowo aktualny skrypt renderowania otrzymuje wiadomość za każdym razem, gdy zmienia się okno (widok gry), a obejmuje to także zmiany orientacji. ```lua function on_message(self, message_id, message) if message_id == hash("window_resized") then - -- Okno zostało zmienione. message.width i message.height zawierają nowe wymiary okna. + -- Rozmiar okna się zmienił. message.width i message.height zawierają + -- nowe wymiary okna. end end ``` -Przy zmianie orientacji menedżer układu interfejsu automatycznie przeskalowuje i przemieszcza węzły GUI zgodnie z układem i właściwościami węzłów. Jednak treść gry jest renderowana w osobnym przebiegu (domyślnie) z projekcją rozciągania do bieżącego okna. Aby zmienić to zachowanie, należy dostarczyć własny zmodyfikowany skrypt renderowania lub skorzystać z [biblioteki kamer](/assets/). +Przy zmianie orientacji menedżer układów GUI automatycznie przeskaluje i przemieści węzły GUI zgodnie z układem oraz właściwościami węzłów. Zawartość gry jest jednak domyślnie renderowana w osobnym przebiegu z projekcją stretch-fit do bieżącego okna. Aby zmienić to zachowanie, dostarcz własny zmodyfikowany skrypt renderowania albo skorzystaj z [biblioteki kamer](/assets/). + +## Ręczny wybór układu (Lua) + +Gdy `Auto Layout Selection` jest wyłączone dla używanych Display Profiles, silnik nie będzie przełączać układów automatycznie. W takim przypadku układami zarządza się ręcznie z poziomu skryptu GUI za pomocą następujących funkcji: + +### gui.set_layout(layout) + +- Przyjmuje `string` albo `hash` (id układu). +- Zwraca wartość logiczną: `true`, jeśli układ istnieje w scenie i został zastosowany; w przeciwnym razie `false`. +- Jeśli układ istnieje w Display Profiles, aktualizuje rozdzielczość sceny do szerokości i wysokości z profilu. +- Wysyła `layout_changed`, gdy układ rzeczywiście się zmieni. + +Przykład: + +```lua +function init(self) + -- Ręcznie zastosuj układ "Portrait" + local ok = gui.set_layout("Portrait") + if not ok then + print("Układ Portrait nie został znaleziony w tej scenie") + end +end +``` + +### gui.get_layouts() + +- Zwraca tabelę mapującą każdy hash id układu na `vmath.vector3(width, height, 0)`. +- Dla układu domyślnego zwraca bieżącą rozdzielczość sceny. + +Przykład: + +```lua +local layouts = gui.get_layouts() +for id, size in pairs(layouts) do + print(id, size.x, size.y) +end +``` + +Uwaga: jeśli układ GUI istnieje w scenie, ale nie występuje w Display Profiles, `gui.set_layout()` nadal zastosuje nadpisania właściwości węzłów dla danego układu, ale nie zmieni rozdzielczości sceny. diff --git a/docs/pl/manuals/live-update.md b/docs/pl/manuals/live-update.md index e6efc68c..606f8484 100644 --- a/docs/pl/manuals/live-update.md +++ b/docs/pl/manuals/live-update.md @@ -1,364 +1,146 @@ --- -title: Aktualizacja na żywo (Live update) w Defoldzie -brief: Ta instrukcja opisuje i wyjaśnia funkcjonalność Live update umożliwiającą aplikacjom pobieranie i przetrzymywanie danych, które początkowo były celowo nie dołączone do zbudowanej paczki. +title: Zawartość Live update w silniku Defold +brief: Funkcja Live update pozwala środowisku uruchomieniowemu pobierać i przechowywać zasoby, które zostały celowo pominięte w bundlu podczas budowania aplikacji. Ta instrukcja wyjaśnia, jak to działa. --- -# Aktualizacja na żywo (Live Update) +# Live update -Podczas pakowania gry, Defold pakuje wszystkie zasoby gry do końcowego pakietu specyficznego dla platformy. W większości przypadków jest to preferowane rozwiązanie, ponieważ działający silnik ma natychmiastowy dostęp do wszystkich zasobów i może szybko je ładować. Jednak istnieją sytuacje, w których chcielibyśmy odłożyć ładowanie zasobów na późniejszy etap. Na przykład: +Podczas bundlowania gry Defold pakuje wszystkie zasoby do końcowej paczki specyficznej dla danej platformy. W większości przypadków jest to korzystne, ponieważ działający silnik ma natychmiastowy dostęp do wszystkich zasobów i może szybko ładować je z nośnika. Czasem jednak warto odłożyć ładowanie części zasobów na później. Na przykład wtedy, gdy: -- Twoja gra zawiera serię odcinków/części, a chcesz uwzględnić tylko pierwszy, aby gracze mogli go wypróbować, zanim zdecydują, czy chcą kontynuować resztę gry. -- Twoja gra jest przeznaczona na HTML5. W przeglądarce ładowanie aplikacji z pamięci oznacza, że cały pakiet aplikacji musi zostać pobrany przed uruchomieniem. Na takiej platformie możesz chcieć wysłać minimalny pakiet startowy i uruchomić aplikację szybko, zanim pobierzesz pozostałe zasoby gry, dzięki czemu gracze wypróbują grę, a gdy będzie wymagane pobranie dodatkowej zawartości może to być wykonane na późniejszym etapie. -- Twoja gra zawiera bardzo duże zasoby (obrazy, filmy itp.), których pobieranie chciałbyś odłożyć do momentu, gdy są gotowe do wyświetlenia w grze. Jest to celem utrzymania rozmiaru instalacji na niskim poziomie. +- gra składa się z odcinków i chcesz dołączyć tylko pierwszy, aby gracz mógł go wypróbować przed odblokowaniem reszty +- gra jest przeznaczona na HTML5, gdzie przeglądarka musi pobrać całą paczkę aplikacji przed uruchomieniem, więc chcesz dostarczyć mały pakiet startowy i doładować resztę zawartości później +- gra zawiera bardzo duże zasoby, takie jak obrazy czy filmy, których pobieranie chcesz odłożyć do momentu, gdy faktycznie będą potrzebne -Funkcja Aktualizacji na żywo Live Update) rozszerza koncepcję pełnomocnika kolekcji (collection proxy), oferując mechanizm, który pozwala na pobieranie i przechowywanie zasobów w pakiecie aplikacji, które celowo zostały pominięte podczas tworzenia pakietu na etapie kompilacji. +Funkcja Live update rozszerza koncepcję Collection proxy (pełnomocnika kolekcji) o mechanizm, który pozwala środowisku uruchomieniowemu pobierać i przechowywać w bundlu aplikacji zasoby celowo pominięte podczas budowania. -## Przygotowanie treści do Aktualizacji na żywo +Pozwala to podzielić zawartość na wiele archiwów: -Załóżmy, że tworzymy grę zawierającą duże zasoby graficzne o wysokiej rozdzielczości. Gra przechowuje te obrazy w kolekcjach z obiektami gry i sprite'ami wykorzystującymi te obrazy: +* _Archiwum bazowe_ +* Wspólne pliki poziomów +* Pakiet poziomów 1 +* Pakiet poziomów 2 +* ... -![Mona Lisa collection](images/live-update/mona-lisa.png) - -Aby silnik mógł dynamicznie ładować taką kolekcję, możemy po prostu dodać komponent pełnomocnika kolekcji, będącego pełnomocnikiem właśnie kolekcji `monalisa.collection`. Teraz gra może wybrać, kiedy załadować zawartość kolekcji do pamięci, wysyłając komunikat `load` do pełnomocnika kolekcji. Jeśli chcielibyśmy pójść dalej i kontrolować ładowanie zasobów zawartych w kolekcji samodzielnie możemy to zrobić, zaznaczając opcję *Exclude* w właściwościach pełnomocnika kolekcji, informując kompilator, że zawartość w `monalisa.collection` powinna być pominięta podczas tworzenia pakietu aplikacji. - -![Collection proxy excluded](images/live-update/proxy-excluded.png) - -## Ustawienia Aktualizacji na żywo - -Kiedy kompilator tworzy pakiet aplikacji, musi gdzieś przechować te wykluczone zasoby. Ustawienia projektu dla Aktualizacji na żywo (Live update settings) określają lokalizację tych zasobów. Ustawienia te znajdują się w Project ▸ Live update Settings.... Kliknięcie w tę opcję spowoduje utworzenie pliku ustawień, jeśli jeszcze nie istnieje. W pliku `game.project` wybierz, które ustawienia Aktualizacji na żywo chcesz użyć podczas kompilacji. Dzięki temu można używać różnych ustawień Aktualizacji na żywo w różnych środowiskach, na przykład na żywo, w QA, w trybie deweloperskim itp. - -When Defold creates an application bundle it needs to store any excluded resources somewhere. The project settings for Live update govern the location for those resources. The settings are found under Project ▸ Live update Settings.... This will create a settings file if none exists. In *game.project*, select which liveupdate settings file to use when bundling. This allows for using different liveupdate settings for different environments, for example for live, QA, dev etc. - -![Live update settings](images/live-update/aws-settings.png) - -Obecnie istnieją dwie metody, które Defold może wykorzystać do przechowywania zasobów. Wybierz metodę z rozwijanego menu *Mode* w oknie ustawień: - -`Amazon` -: Ta opcja mówi Defoldowi, aby automatycznie przesyłał wykluczone zasoby do Amazon Web Service (AWS) S3 bucket. Wprowadź nazwę swojego *Credential profile* (profilu uwierzytelnienia) AWS, wybierz odpowiedni *Bucket* (Kubełek) i podaj *Prefix*. Zobacz [szczegóły dotyczące](#setting_up_amazon_web_service). +## Przygotowanie zawartości do Live update -`Zip` -: Ta opcja mówi Defoldowi, aby utworzyć plik archiwum Zip z wykluczonymi zasobami. Archiwum jest zapisywane w lokalizacji określonej w ustawieniu *Export path* (ścieżka eksportu). - -## Programowanie z wykluczonymi pełnomocnikami kolekcji - -Pełnomocnik kolekcji (collection proxy), które zostały wykluczone z kompilacji, działają jak zwykłe proksy kolekcji, z jedną ważną różnicą. Wysłanie im komunikatu `load`, podczas gdy wciąż mają zasoby, które nie są dostępne w składzie pakietu, spowoduje ich niepowodzenie. - -Dlatego zanim wyślemy komunikat `load`, musimy sprawdzić, czy brakuje jakichkolwiek zasobów. Jeśli tak, musimy je pobrać, a następnie przechować. Poniższy, przykładowy kod zakłada, że zasoby są przechowywane w Amazon S3, w kubełku o nazwie `"my-game-bucket"` z prefiksem `my-resources`. - -```lua -function init(self) - self.resources_pending = 0 -- <1> - msg.post("#", "attempt_load_resources") -end - --- This function is called whenever we have tried to store a downloaded resource --- necessary for our collection proxy to load. -local function resource_store_response(self, hexdigest, status) - if status == true then - -- Successfully loaded resource - print("Resource data stored: " .. hexdigest) - - -- One less resource to go... - self.resources_pending = self.resources_pending - 1 - - -- That was all of them, time to load the proxied collection. - if self.resources_pending == 0 then - msg.post("#proxy", "load") -- <8> - end - else - -- ERROR! Failed to store the data! - print("Failed to store resource data: " .. hexdigest) - end -end - -function on_message(self, message_id, message, sender) - if message_id == hash("attempt_load_resources") then - local missing_resources = collectionproxy.missing_resources("#proxy") -- <2> - - -- initiate a download request for each of the missing resources that has not yet been tried. - for _,resource_hash in ipairs(missing_resources) do - msg.post("#", "attempt_download", { resource_hash = resource_hash}) - end - - self.resources_pending = #missing_resources -- <3> - - -- if we're running from editor all resources are there from the start. - if self.resources_pending == 0 then - msg.post("#proxy", "load") - end - elseif message_id == hash("attempt_download") then - local manifest = resource.get_current_manifest() -- <4> - local base_url = "https://my-game-bucket.s3.amazonaws.com/my-resources/" -- <5> - http.request(base_url .. message.resource_hash, "GET", function(self, id, response) - if response.status == 200 or response.status == 304 then -- <6> - -- We got the response ok. - print("storing " .. message.resource_hash) - resource.store_resource(manifest, response.response, message.resource_hash, resource_store_response) -- <7> - else - -- ERROR! Failed to download resource! - print("Failed to download resource: " .. message.resource_hash) - end - end) - elseif message_id == hash("proxy_loaded") then - msg.post(sender, "init") - msg.post(sender, "enable") - end -end -``` -1. Prosty licznik mówiący nam, ile zasobów musimy jeszcze pobrać i przechować, zanim będziemy mogli załadować kolekcję proxy. Należy zauważyć, że ten kod w ogóle nie zajmuje się obsługą błędów, więc w kodzie produkcyjnym należy śledzić operacje pobierania i przechowywania. -2. Pobierz wszelkie zasoby, które musimy pobrać i przechować. -3. Przechowaj liczbę brakujących zasobów, abyśmy mogli je zliczyć. -4. Potrzebujemy bieżącego manifestu, ponieważ zawiera on listę wszystkich zasobów w bundlu oraz informacje, czy są dostępne, czy nie. -5. Przechowujemy nasze zasoby na Amazon S3. Jeśli tworzysz archiwum Zip z zasobami, musisz hostować pliki w określonym miejscu i odnosić się do ich lokalizacji podczas pobierania ich za pomocą `http.request()`. -6. Amazon zwraca status 304, gdy pliki są w pamięci podręcznej. -7. Mamy dane w tym punkcie. Spróbujmy je przechować. -8. Przechowywanie było udane, a liczba brakujących zasobów spadła do zera. Teraz bezpiecznie możemy wysłać komunikat `"load"` do kolekcji proxy. Należy zauważyć, że jeśli pobieranie lub przechowywanie zawiedzie w którymś momencie, licznik nigdy nie osiągnie zera. - -Z kodem ładowania możemy przetestować aplikację. Jednak uruchamianie jej z edytora nie spowoduje pobierania niczego. Dzieje się tak, ponieważ funkcja Live update to funkcja paczki. W środowisku edytora nie wyklucza się żadnych zasobów. Aby upewnić się, że wszystko działa prawidłowo, trzeba utworzyć paczkę (bundle). +Załóżmy, że tworzymy grę z dużymi obrazami o wysokiej rozdzielczości. Gra przechowuje te obrazy w kolekcjach zawierających obiekt gry i sprite korzystający z obrazu: -## Pakowanie z funkcją Live update - -Pakowanie (bundle) z funkcją aktualizacji na żywo jest proste. Wybierz Project ▸ Bundle ▸ ..., a następnie platformę, dla której chcesz utworzyć pakiet aplikacji. Otwiera to okno dialogowe do pakowania: - -![Bundle Live application](images/live-update/bundle-app.png) - -Podczas pakowania wszelkie wykluczone zasoby zostaną pominięte w pakiecie aplikacji. Zaznaczając pole wyboru *Publish Live update content* (Opublikuj zawartość aktualizacji na żywo), informujesz Defolda, żeby albo przesyłał wykluczone zasoby na Amazon, albo tworzył archiwum Zip, w zależności od tego, jak skonfigurowałeś ustawienia aktualizacji na żywo (patrz wyżej). Plik manifestu dla paczki zostanie również uwzględniony w wykluczonych zasobach. +![Mona Lisa collection](images/live-update/mona-lisa.png) -Kliknij *Package* i wybierz lokalizację pakietu aplikacji. Teraz możesz uruchomić aplikację i sprawdzić, czy wszystko działa zgodnie z oczekiwaniami. +Aby silnik ładował taką kolekcję dynamicznie, wystarczy dodać komponent Collection proxy i wskazać w nim plik *`monalisa.collection`*. Gra może wtedy zdecydować, kiedy załadować zawartość tej kolekcji z nośnika do pamięci, wysyłając do Collection proxy wiadomość `load`. My jednak chcemy pójść krok dalej i samodzielnie sterować ładowaniem zasobów zawartych w kolekcji. -## Manifest +W tym celu zaznaczamy pole *Exclude* we właściwościach Collection proxy. Informuje to Defold, aby podczas tworzenia bundla aplikacji pominął całą zawartość z *`monalisa.collection`*. -Manifest to wewnętrzna struktura danych zawierająca listę wszystkich zasobów zawartych w buildzie oraz wartość skrótu każdego zasobu. Funkcjonalność Live update wykorzystuje manifest do śledzenia, co jest częścią zbudowanej gry, co można załadować z zewnętrznych źródeł i, jeśli tak się stanie, sprawdzenie, czy załadowane dane są nietknięte. +::: important +Żadne zasoby, do których odwołuje się bazowa paczka gry, nie zostaną wykluczone. +::: -Z perspektywy użytkownika manifest to liczbowy uchwyt, ukrywający detale, jak jest zarządzany, w silniku. +![Collection proxy excluded](images/live-update/proxy-excluded.png) -## Aktualizacja manifestu w funkcji Live update +## Ustawienia Live update -Z funkcją aktualizacji na żywo nowy manifest można przechowywać lokalnie w trakcie działania programu. Manifest lokalny zostanie użyty podczas uruchamiania aplikacji zamiast tego, który jest dołączony w pakiecie aplikacji. Jest to przydatne do modyfikowania lub dodawania zasobów aktualizacji na żywo do opublikowanej gry, które nie były znane podczas budowy, bez konieczności publikowania pełnej wersji. +Kiedy Defold tworzy bundle aplikacji, musi gdzieś zapisać wykluczone zasoby. Lokalizacją tych zasobów sterują ustawienia projektu dla Live update. Znajdziesz je pod Project ▸ Live update Settings.... Jeśli plik ustawień jeszcze nie istnieje, zostanie utworzony. W pliku *game.project* wybierasz, którego pliku ustawień Live update użyć podczas bundlowania. Dzięki temu możesz mieć różne ustawienia Live update dla różnych środowisk, na przykład produkcyjnego, QA albo deweloperskiego. -Podczas publikowania zasobów aktualizacji na żywo na Amazon Web Service lub do archiwum ZIP, manifest będzie uwzględniony w pakiecie obok zasobów. Nazwa pliku manifestu to `liveupdate.game.dmanifest`. +![Live update settings](images/live-update/05-liveupdate-settings-zip.png) -Rozpoczęcie pracy z silnikiem Defold po raz pierwszy po przechowywaniu manifestu spowoduje utworzenie pliku identyfikatora paczki `bundle.ver` obok manifestu. Służy to do wykrywania, czy paczka uległa zmianie od czasu przechowywania manifestu, na przykład po pełnej aktualizacji sklepu z aplikacjami. Jeśli tak się stanie, przechowany manifest zostanie usunięty z systemu plików, a nowszy manifest z paczki zastąpi go. Oznacza to, że pełna aktualizacja sklepu z aplikacjami usunie wcześniej przechowywany manifest. Wszystkie istniejące zasoby aktualizacji na żywo pozostaną jednak nietknięte. +Obecnie Defold może przechowywać zasoby na dwa sposoby. Metodę wybierasz z listy *Mode* w oknie ustawień: -### Weryfikacja manifestu +`Zip` +: Ta opcja każe Defold utworzyć archiwum Zip zawierające wszystkie wykluczone zasoby. Archiwum zostanie zapisane w lokalizacji wskazanej w ustawieniu *Export path*. -Podczas przechowywania nowego manifestu jego dane zostaną zweryfikowane, zanim zostaną faktycznie zapisane na dysku. Weryfikacja składa się z kilku sprawdzeń: +`Folder` +: Ta opcja każe Defold utworzyć katalog zawierający wszystkie wykluczone zasoby. Działa tak samo jak tryb Zip, ale zapisuje pliki w katalogu zamiast w archiwum. Przydaje się to wtedy, gdy chcesz dodatkowo przetwarzać pliki przed wysłaniem i samodzielnie spakować je później do archiwum. -* Poprawny format pliku binarnego. -* Obsługuje obecną wersję silnika lub jakąkolwiek inną obsługiwaną wersję z ustawień. -* Sygnatura kryptograficzna. -* Podpisany przy użyciu tej samej pary kluczy publicznych i prywatnych co załączony manifest. -* Zweryfikowanie, że wszystkie zasoby, których manifest oczekuje w paczce, rzeczywiście znajdują się w niej. +`Amazon` +: Ta opcja każe Defold automatycznie wysłać wykluczone zasoby do bucketa S3 w Amazon Web Services (AWS). Podaj nazwę swojego profilu AWS w polu *Credential profile*, wybierz odpowiedni *Bucket* i wpisz *Prefix*. Więcej informacji o konfiguracji konta AWS znajdziesz w [instrukcji AWS](/manuals/live-update-aws). -Z perspektywy użytkownika proces weryfikacji jest zupełnie niewidoczny, ale ważne jest zrozumienie kroków, które są zaangażowane, aby uniknąć najczęstszych problemów. +## Bundlowanie z Live update ::: important -Jeśli widzisz błąd `"ERROR:RESOURCE: Byte mismatch in decrypted manifest signature. Different keys used for signing?"` w konsoli w trakcie budowania gry na HTML5, to prawdopodobnie oznacza, że Twój serwer WWW nie serwuje wykluczonych zasobów, ani zaktualizowanego pliku manifestu z właściwym typem MIME. Upewnij się, że typ MIME to `application/octet-stream`. Możesz dodać plik `.htaccess` z pojedynczą linią `AddType application/octet-stream .` do folderu, z którego pobierane są zasoby aktualizacji na żywo. +Budowanie i uruchamianie projektu z poziomu edytora (Project ▸ Build) nie obsługuje Live Update. Aby testować Live Update, musisz zbudować bundle. ::: -### Obsługiwane wersje silnika Defold +Aby zbudować bundle z Live update, wybierz Project ▸ Bundle ▸ ..., a następnie platformę, dla której chcesz utworzyć paczkę aplikacji. Otworzy się okno bundlowania: -Manifest zawsze będzie obsługiwać wersję Defolda używaną do jego generowania. Jeśli chcesz obsługiwać dodatkowe wersje silnika, dodaj je do listy w ustawieniach aktualizacji na żywo. Jest to przydatne, jeśli Twoja gra na żywo używa innej wersji Defolda niż ta, którą używasz do generowania manifestu. +![Bundle Live application](images/live-update/bundle-app.png) -![Manifest supported engine versions](images/live-update/engine-versions-settings.png) +Podczas bundlowania wszystkie wykluczone zasoby zostaną pominięte w bundlu aplikacji. Zaznaczając pole *Publish Live update content*, każesz Defold albo wysłać wykluczone zasoby do Amazon, albo utworzyć archiwum Zip, zależnie od konfiguracji ustawień Live update. Plik manifestu bundla również zostanie dołączony do wykluczonych zasobów. -### Generowanie kluczy do podpisu +Kliknij *Package* i wybierz lokalizację dla bundla aplikacji. Następnie możesz uruchomić aplikację i sprawdzić, czy wszystko działa zgodnie z oczekiwaniami. -Sygnatura manifestu służy do weryfikowania, że nikt ze złymi zamiarami nie będzie mógł grzebać w jego treści, i że załączony manifest i nowy manifest były podpisane tymi samymi kluczami. Podpisanie jest wykonywane w procesie budowania paczki (bundlowania). +## Archiwa `.zip` -Do kryptograficznego podpisywania manifestu używa się pary kluczy publicznych/prywatnych. Podpisanie jest realizowane przy użyciu kluczy RSA o długości 512/1024/2048 bitów w formacie `.der`, które użytkownik musi dostarczyć. Możesz wygenerować je przykładowo za pomocą narzędzia `openssl`: +Plik `.zip` dla Live update zawiera pliki wykluczone z bazowej paczki gry. -```sh -$ openssl genrsa -out private_raw.key 1024 -$ openssl pkcs8 -topk8 -inform pem -in private_raw.key -outform der -nocrypt -out private.der -$ openssl rsa -in private_raw.key -outform DER -RSAPublicKey_out -pubout -out public.der -``` +Obecny pipeline potrafi utworzyć tylko jeden plik `.zip`, ale w praktyce można go podzielić na kilka mniejszych archiwów `.zip`. Dzięki temu możesz przygotować mniejsze pobrania dla gry, na przykład pakiety poziomów albo sezonową zawartość. Każdy plik `.zip` zawiera również manifest opisujący metadane wszystkich zasobów znajdujących się w tym archiwum. -To spowoduje wygenerowanie plików `private_raw.key` (można go bezpiecznie usunąć), `private.der` i `public.der`. Aby użyć kluczy do podpisywania, otwórz widok ustawień aktualizacji na żywo (live update settings) i wskaz odpowiednie pola na wygenerowane klucze. +## Dzielenie archiwów `.zip` -![Manifest signature key-pair](images/live-update/manifest-keys.png) +Często warto podzielić wykluczoną zawartość na kilka mniejszych archiwów, aby precyzyjniej sterować użyciem zasobów. Typowym przykładem jest gra podzielona na kilka pakietów poziomów. Innym przykładem jest umieszczenie różnych sezonowych dekoracji interfejsu w osobnych archiwach i ładowanie tylko tego motywu, który jest aktualnie aktywny. -### Programowanie z manifestem aktualizacji na żywo -Dodając do powyższego przykładu skryptu, dodajmy poniższą funkcję zwrotną: +Graf zasobów jest zapisywany w pliku `build/default/game.graph.json`, generowanym automatycznie przy każdym bundlowaniu projektu. Plik ten zawiera listę wszystkich zasobów projektu oraz zależności każdego z nich. Przykładowy wpis: -```lua -local function store_manifest_cb(self, status) - if status == resource.LIVEUPDATE_OK then - print("Successfully stored manifest!") - else - print("Failed to store manifest, status: ", status) - end -end -``` -i następujący kod do funkcji `on_message`, aby obsłużyć wiadomość `attempt_download_manifest`: - -```lua -... -elseif message_id == hash("attempt_download_manifest") then - local base_url = "https://my-game-bucket.s3.amazonaws.com/my-resources/" -- <1> - http.request(base_url .. MANIFEST_FILENAME, "GET", function(self, id, response) - if response.status == 200 or response.status == 304 then - -- We got the response ok. - print("verifying and storing manifest " .. MANIFEST_FILENAME) - resource.store_manifest(response.response, store_manifest_cb) -- <2> - else - -- ERROR! Failed to download manifest! - print("Failed to download manifest: " .. MANIFEST_FILENAME) - end - end) -end +```json +{ + "path" : "/game/player.goc", + "hexDigest" : "caa342ec99794de45b63735b203e83ba60d7e5a1", + "children" : [ "/game/ship.spritec", "/game/player.scriptc" ] +} ``` -1. Manifest zostanie przechowywany na Amazon S3 obok reszty zasobów aktualizacji na żywo. Tak, jak poprzedniu, jeśli tworzysz archiwum Zip z zasobami, musisz hostować je gdzieś i podać referencję do ich lokalizacji podczas pobierania przy użyciu `http.request()`. -2. Podobnie jak w przypadku pobierania i przechowywania zasobów, wywołanie `resource.store_manifest` przyjmuje dane manifestu do pobrania i funkcję zwrotną jako argumenty. Funkcja zwrotna zweryfikuje manifest i zapisze go w pamięci lokalnej. - -Jeśli `resource.store_manifest` zakończy się powodzeniem, nowy manifest będzie teraz w pamięci lokalnej. Następnym razem, gdy silnik zostanie uruchomiony, używany będzie ten nowy manifest zamiast tego, który był dołączony do gry. - -### Uwagi - -Istnieją pewne rzeczy, o których warto wiedzieć, jeśli planujesz użyć tej funkcji do przechowywania nowego manifestu z aktualizacją na żywo. - -* Możliwe jest tylko dodawanie lub modyfikowanie zasobów używanych przez kolekcje proxy oznaczone jako `Exclude` w nowym manifeście. Nie można dokonywać zmian w już dodanych zasobach lub zasobach, które nie znajdują się w wykluczonych pełnomocnikach kolekcji. Na przykład, wprowadzenie zmian w skrypcie używanym przez dołączoną kolekcję spowoduje, że system zasobów będzie szukał tego zasobu w archiwum danych paczki. Jednak ponieważ paczka gry nie zmieniła się (zmienił się tylko manifest), zmienionego skryptu nie można odnaleźć i w konsekwencji nie można go załadować. - -* Nawet jeśli funkcjonalność ta pozwala na bardzo szybkie wprowadzanie zmian lub łatanie błędów bez pełnego, nowego release aplikacji w sklepie, live update należy używać z zachowaniem szczególnej ostrożności. Dołączenie nowego manifestu powinno poprzedzać wszystko, co jest potrzebne przy faktycznym wydaniu nowej wersji gry (testowanie, QA, itd.). - -## Konfiguracja Amazon Web Service +Każdy wpis zawiera pole `path`, które reprezentuje unikalną ścieżkę zasobu w projekcie. Pole `hexDigest` to kryptograficzny odcisk zasobu i jednocześnie nazwa pliku używana w archiwum `.zip` dla Live update. Pole `children` zawiera listę zależności, od których dany zasób zależy. W powyższym przykładzie `/game/player.goc` zależy od komponentu sprite i komponentu script. -Aby korzystać z funkcji Defold Live Update razem z usługami Amazon, potrzebujesz konta Amazon Web Services. Jeśli jeszcze nie masz konta, możesz je utworzyć [tutaj](https://aws.amazon.com/). +Możesz sparsować plik `game.graph.json` i użyć tych informacji do znalezienia grup wpisów w grafie zasobów, a następnie zapisać odpowiadające im zasoby w osobnych archiwach razem z oryginalnym plikiem manifestu. Manifest zostanie później przycięty w runtime tak, aby zawierał tylko pliki obecne w danym archiwum. -W tej sekcji wyjaśnimy, jak utworzyć nowego użytkownika z ograniczonym dostępem w usługach Amazon Web Services, który może być wykorzystywany razem z edytorem Defold do automatycznego przesyłania zasobów aktualizacji na żywo podczas pakowania gry oraz jak skonfigurować Amazon S3, aby umożliwić klientom gier pobieranie zasobów. Dodatkowe informacje na temat konfigurowania Amazon S3 znajdziesz w [dokumentacji Amazon S3](http://docs.aws.amazon.com/AmazonS3/latest/dev/Welcome.html). +## Live Update na Androidzie -1. Utwórz bucket (kubełek) na zasoby aktualizacji na żywo +Możesz używać Play Asset Delivery do pobierania i montowania zawartości Live Update. Więcej informacji znajdziesz [w oficjalnej instrukcji](https://defold.com/extension-pad/). - Otwórz menu `Services` i wybierz `S3`, które znajduje się w kategorii _Storage_ ([Amazon S3 Console](https://console.aws.amazon.com/s3)). Zobaczysz swoje istniejące kubełki wraz z opcją utworzenia nowego kubełka. Choć możliwe jest użycie istniejącego kubełka, zalecamy utworzenie nowego kubełka na zasoby aktualizacji na żywo, aby łatwo ograniczyć dostęp. +## Weryfikacja zawartości - ![Create a bucket](images/live-update/01-create-bucket.png) +Jedną z ważniejszych cech systemu Live update jest możliwość używania wielu archiwów zawartości, potencjalnie pochodzących z wielu różnych wersji Defold. -2. Dodaj politykę kubełka (bucket policy) do swojego kubełka +Domyślne zachowanie `liveupdate.add_mount()` polega na dodaniu kontroli wersji silnika podczas dołączania mounta. Oznacza to, że zarówno bazowe archiwum gry, jak i archiwa Live update muszą zostać utworzone w tym samym czasie, tą samą wersją silnika i z użyciem opcji bundlowania. W przeciwnym razie klient unieważni wcześniej pobrane archiwa i wymusi ponowne pobranie zawartości. - Wybierz kubełek, który chcesz użyć, otwórz panel *Properties* i rozwiń opcje *Permissions* w panelu. Otwórz politykę kubełka, klikając przycisk *Add bucket policy*. Polityka kubełka w tym przykładzie umożliwi anonimowemu użytkownikowi pobieranie plików z kubełka, co umożliwi graczowi pobieranie zasobów aktualizacji na żywo wymaganych przez grę. Dodatkowe informacje na temat polityk kubełka znajdziesz w [dokumentacji Amazon o polityce](https://docs.aws.amazon.com/AmazonS3/latest/dev/using-iam-policies.html). +To zachowanie można wyłączyć odpowiednią flagą opcji. Po wyłączeniu pełna odpowiedzialność za weryfikację zgodności zawartości spoczywa na programiście, który musi zagwarantować, że każde archiwum Live update będzie działało z uruchomionym silnikiem. - ```json - { - "Version": "2012-10-17", - "Statement": [ - { - "Sid": "AddPerm", - "Effect": "Allow", - "Principal": "*", - "Action": "s3:GetObject", - "Resource": "arn:aws:s3:::defold-liveupdate-example/*" - } - ] - } - ``` +Zalecamy przechowywanie pewnych metadanych dla każdego mounta, aby _bezpośrednio po uruchomieniu_ zdecydować, czy dany mount lub archiwum należy usunąć. Jednym ze sposobów jest dodanie dodatkowego pliku do archiwum zip po zbudowaniu gry, na przykład `metadata.json` zawierającego potrzebne informacje. Następnie przy starcie gry można go odczytać przez `sys.load_resource("/metadata.json")`. _Pamiętaj, że dane niestandardowe każdego mounta muszą mieć unikalną nazwę. W przeciwnym razie silnik zwróci plik z mounta o najwyższym priorytecie._ - ![Bucket policy](images/live-update/02-bucket-policy.png) +Jeśli tego nie zrobisz, możesz doprowadzić do sytuacji, w której zawartość okaże się całkowicie niezgodna z silnikiem i wymusi zamknięcie aplikacji. -3. Dodaj konfigurację CORS do swojego kubełka (opcjonalnie) +## Mounty - Udostępnianie zasobów z różnych domen ([Cross-Origin Resource Sharing - CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing)) to mechanizm, który umożliwia witrynie pobieranie zasobu z innej domeny za pomocą JavaScript. Jeśli planujesz opublikować swoją grę jako klienta HTML5, będziesz musiał dodać konfigurację CORS do swojego kubełka. +System Live update może używać jednocześnie wielu archiwów zawartości. Każde archiwum jest „montowane” do systemu zasobów silnika z własną nazwą i priorytetem. - Wybierz kubełek, który chcesz użyć, otwórz panel *Properties* i rozwiń opcje *Permissions*. Otwórz konfigurację CORS klikając przycisk *Add CORS Configuration*. Konfiguracja w tym przykładzie umożliwi dostęp z dowolnej witryny, określając domenę wieloznaczną, choć możliwe jest bardziej restrykcyjne ograniczenie dostępu, jeśli wiesz, na jakich domenach zamierzasz udostępnić swoją grę. Dodatkowe informacje na temat konfiguracji CORS w Amazonie znajdziesz w [dokumentacji Amazono CORS](https://docs.aws.amazon.com/AmazonS3/latest/dev/cors.html). +Jeśli dwa archiwa zawierają ten sam plik `sprite.texturec`, silnik załaduje go z mounta o wyższym priorytecie. - ```xml - - - - * - GET - - - ``` +Silnik nie utrzymuje referencji do zasobów znajdujących się w mouncie. Gdy zasób zostanie już załadowany do pamięci, archiwum może zostać odmontowane. Sam zasób pozostanie w pamięci do momentu jego zwolnienia. - ![CORS configuration](images/live-update/03-cors-configuration.png) +Mounty są automatycznie dodawane ponownie po restarcie silnika. -4. Utwórz politykę IAM - - Otwórz menu *Services* i wybierz *IAM*, które znajduje się w kategorii _Security, Identity & Compliance_ category ([Amazon IAM Console](https://console.aws.amazon.com/iam)). Wybierz *Policies* w menu po lewej stronie i zobaczysz swoje istniejące polityki, wraz z opcją utworzenia nowej polityki. - - Kliknij przycisk *Create Policy* i wybierz _Create Your Own Policy_. Polityka w tym przykładzie umożliwi użytkownikowi wyświetlenie wszystkich kubełków, co jest wymagane tylko podczas konfigurowania projektu Defold dla aktualizacji na żywo. Będzie również umożliwiać użytkownikowi uzyskanie listy kontroli dostępu (Access Control List - ACL) i przesyłanie zasobów do konkretnej nazwy kubełka używanej do zasobów aktualizacji na żywo. Dodatkowe informacje na temat Amazon Identity and Access Management (IAM) znajdziesz w [dokumentacji Amazon](http://docs.aws.amazon.com/IAM/latest/UserGuide/access.html). - - ```json - { - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": [ - "s3:ListAllMyBuckets" - ], - "Resource": "arn:aws:s3:::*" - }, - { - "Effect": "Allow", - "Action": [ - "s3:GetBucketAcl" - ], - "Resource": "arn:aws:s3:::defold-liveupdate-example" - }, - { - "Effect": "Allow", - "Action": [ - "s3:PutObject" - ], - "Resource": "arn:aws:s3:::defold-liveupdate-example/*" - } - ] - } - ``` - - ![IAM policy](images/live-update/04-create-policy.png) - -5. Utwórz użytkownika do dostępu programistycznego - - Otwórz menu *Services* i wybierz *IAM*, które znajduje się w kategorii _Security, Identity & Compliance_ category ([Amazon IAM Console](https://console.aws.amazon.com/iam)). Wybierz *Users* w menu po lewej stronie i zobaczysz swoich istniejących użytkowników wraz z opcją dodania nowego użytkownika. Choć możliwe jest użycie istniejącego użytkownika, zalecamy dodanie nowego użytkownika do zasobów aktualizacji na żywo, aby łatwo ograniczyć dostęp. - - Kliknij przycisk *Add User*, podaj nazwę użytkownika i wybierz *Programmatic access* jako *Access type*, a następnie kliknij *Next: Permissions*. Wybierz *Attach existing policies directly* i wybierz politykę, którą utworzyłeś w kroku 4. - - Po zakończeniu procesu zostaniesz dostarczony z *Access key ID* i *Secret access key*. - - ::: important - *Bardzo ważne* jest, aby zachować te klucze, ponieważ nie będziesz w stanie ich odzyskać z Amazon po opuszczeniu strony. - ::: - -6. Utwórz plik profilu poświadczeń +::: sidenote +Zamontowanie archiwum nie kopiuje go ani nie przenosi. Silnik przechowuje jedynie ścieżkę do archiwum. Oznacza to, że programista może usunąć archiwum w dowolnym momencie, a mount zostanie usunięty przy następnym uruchomieniu. +::: - W tym momencie powinieneś już mieć kubełek (bucket), skonfigurowaną politykę kubełka, dodaną konfigurację CORS, utworzoną politykę użytkownika i utworzonego nowego użytkownika. Jedyną rzeczą, która pozostała, jest utworzenie [pliku profilu poświadczeń](https://aws.amazon.com/blogs/security/a-new-and-standardized-way-to-manage-credentials-in-the-aws-sdks), aby Defold mógł uzyskać dostęp do kubełka w twoim imieniu. +## Skryptowanie z Live Update -Utwórz nowy katalog `~/.aws` w folderze domowym i utwórz w nim plik o nazwie `credentials`. +Aby faktycznie korzystać z zawartości Live update, musisz pobrać dane i zamontować je w swojej grze. +Więcej informacji znajdziesz w [instrukcji skryptowania Live update](/manuals/live-update-scripting). - ```bash - $ mkdir ~/.aws - $ touch ~/.aws/credentials - ``` - Plik `~/.aws/credentials` zawiera twoje poświadczenia dostępu do Amazon Web Services poprzez dostęp programistyczny i jest standaryzowany sposób na zarządzanie poświadczeniami AWS. Otwórz plik w edytorze tekstowym i wprowadź swoje *Access key ID* i *Secret access key* w formacie pokazanym poniżej. - - ```ini - [defold-liveupdate-example] - aws_access_key_id = - aws_secret_access_key = - ``` - Identyfikator określony w nawiasach kwadratowych, w tym przykładzie `_defold-liveupdate-example_`, jest taki sam jak identyfikator, który powinieneś podać podczas konfigurowania ustawień aktualizacji na żywo projektu w edytorze Defold. - - ![Live update settings](images/live-update/05-liveupdate-settings.png) - -## Uwagi dotyczące rozwoju oprogramowania +## Uwagi deweloperskie Debugowanie -: Podczas uruchamiania spakowanej wersji swojej gry nie masz bezpośredniego dostępu do konsoli. To może sprawić problemy z debugowaniem. Niemniej jednak, możesz uruchomić aplikację z wiersza poleceń lub podwójnie klikając na plik wykonywalny w paczce: +: Gdy uruchamiasz zbundlowaną wersję gry, nie masz bezpośredniego dostępu do konsoli, co utrudnia debugowanie. Możesz jednak uruchomić aplikację z wiersza poleceń albo klikając bezpośrednio plik wykonywalny znajdujący się w bundlu: ![Running a bundle application](images/live-update/run-bundle.png) - Teraz gra zaczyna się z oknem konsoli, które będzie wyświetlać wszystkie instrukcje `print()`: + Gra uruchomi się wtedy z oknem powłoki, w którym będą widoczne wszystkie wywołania `print()`: ![Console output](images/live-update/run-bundle-console.png) -Wymuszanie ponownego pobierania zasobów -: Gdy aplikacja przechowuje zasoby, trafiają one na dysk lokalny komputera lub urządzenia przenośnego. Gdy zrestartujesz aplikację, zasoby są dostępne i gotowe do użycia. Podczas pracy nad projektem gry może być potrzeba usunięcia zasobów i wymuszenia na aplikacji ich ponownego pobrania. +Wymuszenie ponownego pobrania zasobów +: Programista może pobrać zawartość do dowolnego pliku lub katalogu, ale często trafia ona do ścieżki aplikacji. Lokalizacja katalogu wsparcia aplikacji zależy od systemu operacyjnego. Możesz ją sprawdzić przez `print(sys.get_save_file("", ""))`. - Defold tworzy folder o nazwie hasha stworzonej paczki na urządzeniu w folderze obsługi aplikacji. Jeśli usuniesz pliki z tego folderu, aplikacja unieważni zasoby z manifestu, dzięki czemu będziesz mógł je pobrać i ponownie przechować. + Plik `liveupdate.mounts` znajduje się w pamięci lokalnej, a jego ścieżka jest wypisywana do konsoli przy starcie jako `"INFO:LIVEUPDATE: Live update folder located at: ..."` ![Local storage](images/live-update/local-storage.png) - - Lokalizacja folderu obsługi aplikacji zależy od systemu operacyjnego. Możesz ją znaleźć, używając polecenia `print(sys.get_save_file("", ""))`. diff --git a/docs/pl/manuals/physics-shapes.md b/docs/pl/manuals/physics-shapes.md index a51805cc..53d6ff9b 100644 --- a/docs/pl/manuals/physics-shapes.md +++ b/docs/pl/manuals/physics-shapes.md @@ -1,74 +1,159 @@ --- -title: Kształty Kolizji -brief: Ta instrukcja opisuje szczegóły działania kształtów kolizji silnika fizyki. +title: Kształty kolizji +brief: Komponent obiektu kolizji może używać kilku kształtów podstawowych albo jednego kształtu złożonego. --- -# Kształty Kolizji +# Kształty kolizji -Komponent Obiektu Kolizji (Collision Object) może używać kilku kształtów podstawowych (ang. primitive shapes) lub pojedynczego kształtu złożonego. +Komponent obiektu kolizji może używać kilku kształtów podstawowych albo jednego kształtu złożonego. ### Kształty podstawowe -Podstawowe kształty to *box* - prostokąt, *sphere* - sfera i *capsule* - kapsuła. Aby dodać kształt podstawowy, kliknij prawym przyciskiem myszy obiekt kolizji, a następnie wybierz Add Shape: +Kształty podstawowe to *box*, *sphere* i *capsule*. Aby dodać kształt podstawowy, kliknij prawym przyciskiem myszy obiekt kolizji i wybierz Add Shape: ![Add a primitive shape](images/physics/add_shape.png) -## Kształt prostokątny -Kształt prostokątny (box) posiada pozycję, rotację i wymiary (szerokość, wysokość i głębokość): +## Kształt prostokątny (box) -![Kształt prostokątny](images/physics/box.png) +Kształt prostokątny (box) ma pozycję, obrót i wymiary: szerokość, wysokość oraz głębokość: -## Kształt sfery -Sfera (sphere) posiada pozycję, rotację i średnicę: +![Box shape](images/physics/box.png) -![Kształt sfery](images/physics/sphere.png) +## Kształt sfery (sphere) -## Kształt kapsuły -Kapsuła posiada pozycję, rotację, średnicę i wysokość: +Kształt sfery (sphere) ma pozycję, obrót i średnicę: -![Kształt kapsuły](images/physics/capsule.png) +![Sphere shape](images/physics/sphere.png) + +## Kształt kapsuły (capsule) + +Kształt kapsuły (capsule) ma pozycję, obrót, średnicę i wysokość: + +![Sphere shape](images/physics/capsule.png) ::: important -Kształty kapsuły są obsługiwane tylko w przypadku korzystania z fizyki 3D (skonfigurowanej w sekcji *Physics* w pliku *game.project*). +Kształty capsule są obsługiwane tylko przy korzystaniu z fizyki 3D, skonfigurowanej w sekcji *Physics* pliku *game.project*. ::: ### Kształty złożone -Kształty złożone (ang. complex shapes) można utworzyć z komponentu mapy kafelków lub z kształtu wypukłego (convex hull shape). -## Kształt kolizji mapy kafelków -Defold zawiera funkcję, która umożliwia łatwe generowanie kształtów fizyki dla Źródła Kafelków (Tile Source) używanego przez mapę kafelków. W [instrukcji Źródła Kafelków](/manuals/tilesource/#tile-source-collision-shapes) wyjaśniono, jak dodać grupy kolizji do źródła kafelków i przypisać kafelki do grup kolizji ([przykład](/examples/tilemap/collisions/)). +Kształt złożony można utworzyć albo z komponentu Tile map (mapy kafelków), albo z kształtu convex hull. + +## Kształt kolizji Tile map -Aby dodać kolizję do mapy kafelków: +Defold zawiera funkcję, która pozwala łatwo generować kształty fizyki dla Tile source używanego przez Tile map. W [instrukcji Tile source](/manuals/tilesource/#tile-source-collision-shapes) wyjaśniono, jak dodawać grupy kolizji do Tile source i przypisywać kafelki do grup kolizji ([przykład](/examples/tilemap/collisions/)). -1. Dodaj mapę kafelków do obiektu gry, klikając go prawym przyciskiem myszy i wybierając Add Component File. Wybierz plik mapy kafelków. -2. Dodaj komponent obiektu kolizji do obiektu gry, klikając go prawym przyciskiem myszy i wybierając Add Component ▸ Collision Object. -3. Zamiast dodawać kształty do komponentu, ustaw właściwość Kształt kolizji na plik mapa kafelków (*tilemap*). -4. Skonfiguruj *Properties* komponentu obiektu kolizji. +Aby dodać kolizję do Tile map: -![Kształt kolizji mapy kafelków](images/physics/collision_tilemap.png) +1. Dodaj Tile map do obiektu gry, klikając prawym przyciskiem myszy obiekt gry i wybierając Add Component File. Następnie wybierz plik Tile map. +2. Dodaj komponent obiektu kolizji do obiektu gry, klikając prawym przyciskiem myszy obiekt gry i wybierając Add Component ▸ Collision Object. +3. Zamiast dodawać kształty do komponentu, ustaw właściwość *Collision Shape* na plik *tilemap*. +4. Skonfiguruj *Properties* komponentu obiektu kolizji jak zwykle. + +![Tilesource collision](images/physics/collision_tilemap.png) ::: important -Należy zauważyć, że właściwość *Group* **nie** jest tutaj używana, ponieważ grupy kolizji są definiowane w źródle kafelków (tile source) mapy kafelków. +Zwróć uwagę, że właściwość *Group* **nie** jest tutaj używana, ponieważ grupy kolizji są definiowane w Tile source mapy kafelków. ::: -## Kształt kolizji wypukłej -Defold zawiera funkcję, która umożliwia tworzenie kształtu wypukłego (convex hull shape) z trzech lub więcej punktów. Możesz użyć zewnętrznego narzędzia, takiego jak [Defold Polygon Editor](/assets/defoldpolygoneditor/) lub [Physics Body Editor](https://selimanac.github.io/physics-body-editor/), aby utworzyć kształt wypukły. +## Kształt wypukły (convex hull) -1. Utwórz plik kształtu wypukłego (o rozszerzeniu pliku .`.convexshape`) za pomocą zewnętrznego edytora. -2. Zamiast dodawać kształty do komponentu obiektu kolizji, ustaw właściwość *Collision Shape* na plik *convex shape*. +Defold zawiera funkcję pozwalającą tworzyć kształt wypukły (convex hull) z trzech lub większej liczby punktów. + +1. Utwórz plik kształtu convex hull o rozszerzeniu `.convexshape` przy użyciu zewnętrznego edytora. +2. Edytuj plik ręcznie w edytorze tekstu albo przy użyciu zewnętrznego narzędzia, opisanego poniżej. +3. Zamiast dodawać kształty do komponentu obiektu kolizji, ustaw właściwość *Collision Shape* na plik *convex shape*. + +### Format pliku + +Format pliku convex hull używa tego samego formatu danych co pozostałe pliki Defold, czyli tekstowego formatu protobuf. Kształt convex hull definiuje punkty bryły. W fizyce 2D punkty powinny być podane w kolejności przeciwnej do ruchu wskazówek zegara. W trybie fizyki 3D używana jest abstrakcyjna chmura punktów. Przykład dla 2D: + +``` +shape_type: TYPE_HULL +data: 200.000 +data: 100.000 +data: 0.0 +data: 400.000 +data: 100.000 +data: 0.0 +data: 400.000 +data: 300.000 +data: 0.0 +data: 200.000 +data: 300.000 +data: 0.0 +``` + +Powyższy przykład definiuje cztery narożniki prostokąta: + +``` + 200x300 400x300 + 4---------3 + | | + | | + | | + | | + 1---------2 + 200x100 400x100 +``` + +## Narzędzia zewnętrzne + +Istnieje kilka narzędzi zewnętrznych, których można użyć do tworzenia kształtów kolizji: + +* [Physics Editor](https://www.codeandweb.com/physicseditor/tutorials/how-to-create-physics-shapes-for-defold) od CodeAndWeb pozwala tworzyć obiekty gry ze sprite’ami i pasującymi do nich kształtami kolizji. +* [Defold Polygon Editor](https://rossgrams.itch.io/defold-polygon-editor) można użyć do tworzenia kształtów convex hull. +* [Physics Body Editor](https://selimanac.github.io/physics-body-editor/) również można użyć do tworzenia kształtów convex hull. -::: sidenote -Kształt taki nie będzie rysowany w Edytorze. Możesz włączyć [debugowanie fizyki](/manuals/debugging/#debugging-problems-with-physics) podczas działania programu, aby zobaczyć kształt. -::: # Skalowanie kształtów kolizji -Obiekt kolizji i jego kształty dziedziczą skalę obiektu gry. Aby wyłączyć to zachowanie, odznacz pole wyboru "[Allow Dynamic Transforms](/manuals/project-settings/#allow-dynamic-transforms)", czyli Zezwalaj na dynamiczne transformacje w sekcji *Physics* pliku *game.project*. Należy pamiętać, że obsługiwane jest tylko skalowanie jednolite (uniform), a jeśli skala nie jest jednolita, zostanie użyta najmniejsza wartość skali. +Obiekt kolizji i jego kształty dziedziczą skalę obiektu gry. Aby wyłączyć to zachowanie, odznacz pole [Allow Dynamic Transforms](/manuals/project-settings/#allow-dynamic-transforms) w sekcji *Physics* pliku *game.project*. Zwróć uwagę, że obsługiwane jest tylko skalowanie jednolite, a jeśli skala nie jest jednolita, użyta zostanie najmniejsza wartość skali. + +# Zmienianie rozmiaru kształtów kolizji + +Rozmiar kształtów obiektu kolizji można zmieniać w czasie działania przy użyciu `physics.set_shape()`. Przykład: + +```lua +-- ustaw dane kształtu capsule +local capsule_data = { + type = physics.SHAPE_TYPE_CAPSULE, + diameter = 10, + height = 20, +} +physics.set_shape("#collisionobject", "my_capsule_shape", capsule_data) + +-- ustaw dane kształtu sphere +local sphere_data = { + type = physics.SHAPE_TYPE_SPHERE, + diameter = 10, +} +physics.set_shape("#collisionobject", "my_sphere_shape", sphere_data) + +-- ustaw dane kształtu box +local box_data = { + type = physics.SHAPE_TYPE_BOX, + dimensions = vmath.vector3(10, 10, 5), +} +physics.set_shape("#collisionobject", "my_box_shape", box_data) +``` + +::: sidenote +Na obiekcie kolizji musi już istnieć kształt właściwego typu o podanym id. +::: # Obracanie kształtów kolizji ## Obracanie kształtów kolizji w fizyce 3D + Kształty kolizji w fizyce 3D można obracać wokół wszystkich osi. + ## Obracanie kształtów kolizji w fizyce 2D -Kształty kolizji w fizyce 2D można obracać tylko wokół osi Z. Obrót wokół osi X lub Y spowoduje nieprawidłowe wyniki i powinno się go unikać, nawet przy obracaniu o 180 stopni, aby efektywnie odwrócić kształt wzdłuż osi x lub y. Aby odwrócić kształt fizyczny, zaleca się korzystanie z [`physics.set_hlip(url, flip)`](/ref/stable/physics/?#physics.set_hflip:url-flip) i [`physics.set_vlip(url, flip)`](/ref/stable/physics/?#physics.set_vflip:url-flip). + +Kształty kolizji w fizyce 2D można obracać tylko wokół osi Z. Obracanie wokół osi X albo Y daje nieprawidłowe wyniki i należy go unikać, nawet przy obrocie o 180 stopni, który pozornie miałby tylko odwrócić kształt wzdłuż osi X albo Y. Do odwracania kształtu fizyki zaleca się używać [`physics.set_hlip(url, flip)`](/ref/stable/physics/?#physics.set_hflip:url-flip) oraz [`physics.set_vlip(url, flip)`](/ref/stable/physics/?#physics.set_vflip:url-flip). + + +# Debugowanie + +Możesz [włączyć debugowanie fizyki](/manuals/debugging/#debugging-problems-with-physics), aby zobaczyć kształty kolizji w czasie działania. diff --git a/docs/pl/manuals/project-settings.md b/docs/pl/manuals/project-settings.md index da7e9572..0e17d7f7 100644 --- a/docs/pl/manuals/project-settings.md +++ b/docs/pl/manuals/project-settings.md @@ -1,530 +1,840 @@ --- -title: Ustawienie projektu -brief: Instrukcja opisuje poszczególne ustawienia projektu w Defoldzie. +title: Ustawienia projektu +brief: Ta instrukcja opisuje, jak działają ustawienia specyficzne dla projektu w silniku Defold. --- -# Ustawienie projektu +# Ustawienia projektu -Plik *game.project* zawiera wszystkie ustawienia wykorzystywane w projekcie. Jest to specjalny plik i musi pozostać w głównej lokalizacji Twojego projektu, a nazwa musi pozostać niezmieniona - *game.project*. Pierwsza rzeczą jaką zajmuje się silnik Defold zaraz po starcie Twojej gry jest właśnie wyszukanie tego pliku. (W systemie Windows można przypisać plik .project do domyślnego otwierania za pomocą aplikacji Defold) +Plik *game.project* zawiera wszystkie ustawienia obowiązujące w całym projekcie. Musi znajdować się w katalogu głównym projektu i musi mieć nazwę *game.project*. Jedną z pierwszych czynności wykonywanych przez silnik podczas uruchamiania gry jest odnalezienie właśnie tego pliku. -Każde ustawienie w tym pliku przynależy do konkretnej kategorii. Defold wyświetla ustawienia z tego pliku podzielone właśnie na te kategorie. +Każde ustawienie w tym pliku należy do określonej kategorii. Po otwarciu pliku Defold wyświetla ustawienia pogrupowane według kategorii. ![Project settings](images/project-settings/settings.jpg) -Poniżej przedstawiono wszystkie dostępne ustawienia, poukładane w sekcje. Niektóre z nich nie są pokazywane po otwarciu w Edytorze Defold (oznaczono je "hidden setting" (z ang. ukryte ustawienie))), ale wciąż można je zmienić ręcznie otwierając plik *game.project* w edytorze tekstu: Open With ▸ Text Editor. +## File format -## Project +Ustawienia w *game.project* najczęściej zmienia się bezpośrednio w Defold, ale sam plik można też edytować w dowolnym zwykłym edytorze tekstu. Plik używa formatu INI i wygląda następująco: + +```ini +[category1] +setting1 = value +setting2 = value +[category2] +... +``` + +Rzeczywisty przykład: + +```ini +[bootstrap] +main_collection = /main/main.collectionc +``` + +oznacza, że ustawienie *main_collection* należy do kategorii *bootstrap*. Gdy używasz odwołania do pliku, jak w powyższym przykładzie, ścieżka musi kończyć się literą `c`, co oznacza odwołanie do skompilowanej wersji pliku. Zwróć też uwagę, że katalog zawierający *game.project* jest katalogiem głównym projektu, dlatego ścieżka ustawienia zaczyna się od `/`. + +## Runtime access + +Każdą wartość z *game.project* można odczytać w czasie działania za pomocą funkcji [`sys.get_config_string(key)`](/ref/sys/#sys.get_config_string), [`sys.get_config_number(key)`](/ref/sys/#sys.get_config_number) i [`sys.get_config_int(key)`](/ref/sys/#sys.get_config_int). Przykład: + +```lua +local title = sys.get_config_string("project.title") +local gravity_y = sys.get_config_number("physics.gravity_y") +``` + +::: sidenote +Klucz składa się z nazwy kategorii i nazwy ustawienia, oddzielonych kropką, zapisanych małymi literami, a spacje zastępuje się znakami podkreślenia. Przykładowo pole `Title` z kategorii `Project` staje się `project.title`, a `Gravity Y` z kategorii `Physics` staje się `physics.gravity_y`. +::: + +## Sections and settings + +Poniżej znajdują się wszystkie dostępne ustawienia, uporządkowane według kategorii. + +### Project #### Title -Tytuł aplikacji +Tytuł aplikacji. #### Version -Wersja aplikacji +Wersja aplikacji. + +#### Publisher +Nazwa wydawcy. + +#### Developer +Nazwa dewelopera. #### Write Log File -Określa, kiedy silnik zapisuje log do pliku. Opcje: +Określa, kiedy silnik zapisuje plik logu. Dostępne opcje: -- "Never": nie zapisuj pliku logu. -- "Debug": zapisuj plik logu tylko dla buildów Debug. -- "Always": zapisuj plik logu zarówno dla buildów Debug, jak i Release. +- `Never`: nie zapisuj pliku logu +- `Debug`: zapisuj plik logu tylko dla buildów Debug +- `Always`: zapisuj plik logu zarówno dla buildów Debug, jak i Release -Jeśli uruchamiasz więcej niż jedną instancję z edytora, plik będzie nazwany *instance_2_log.txt*, gdzie `2` to indeks instancji. Jeśli uruchamiasz pojedynczą instancję lub paczkę, plik będzie nazwany *log.txt*. Lokalizacja pliku logu będzie jedną z poniższych (sprawdzane w tej kolejności): +Jeśli uruchamiasz z edytora więcej niż jedną instancję, plik będzie miał nazwę *instance_2_log.txt*, gdzie `2` oznacza indeks instancji. Przy pojedynczej instancji lub uruchomieniu z bundla plik będzie miał nazwę *log.txt*. Lokalizacja pliku logu będzie jedną z poniższych ścieżek, sprawdzanych w tej kolejności: 1. Ścieżka określona w *project.log_dir* (ukryte ustawienie) 2. Systemowa ścieżka logów: - * macOS/iOS: `NSDocumentDirectory` - * Android: `Context.getExternalFilesDir()` - * Inne: katalog aplikacji -3. Ścieżka wsparcia aplikacji: - * macOS/iOS: `NSApplicationSupportDirectory` - * Windows: `CSIDL_APPDATA` (np. `C:\Users\\AppData\Roaming`) - * Android: `Context.getFilesDir()` - * Linux: zmienna środowiskowa `HOME` + * macOS/iOS: `NSDocumentDirectory` + * Android: `Context.getExternalFilesDir()` + * Pozostałe platformy: katalog główny aplikacji +3. Ścieżka danych wsparcia aplikacji: + * macOS/iOS: `NSApplicationSupportDirectory` + * Windows: `CSIDL_APPDATA` (na przykład `C:\Users\\AppData\Roaming`) + * Android: `Context.getFilesDir()` + * Linux: zmienna środowiskowa `HOME` + +#### Minimum Log Level +Określa minimalny poziom logowania. Wyświetlane będą tylko komunikaty na tym poziomie lub wyższym. #### Compress Archive -Umożliwia kompresowanie archiwów podczas budowania paczki. Zauważ, że dotyczy to wszystkich platform oprócz systemu Android, gdzie plik apk zawiera od razy skompresowane dane. +Włącza kompresję archiwów podczas bundlowania. Obecnie dotyczy to wszystkich platform poza Androidem, gdzie plik APK i tak zawiera już skompresowane dane. #### Dependencies -Zależoności - lista adresów URL do projektów bibliotek (*Library URL*s). Więcej szczegółów znajdziesz w [instrukcji do Bibliotek](/manuals/libraries/). +Lista adresów URL do projektów będących *Library URL*. Więcej informacji znajdziesz w [instrukcji Libraries](/manuals/libraries/). #### Custom Resources -Własne zasoby - lista oddzielonych przecinkami zasobów, które będą dołączone do projektu. Jeśli określone są lokalizacje, wszystkie pliki i katalogi w danej lokalizacji są rekursywnie załączane. Zasoby te można załadować w trakcie działania programu używając [`sys.load_resource()`](/ref/sys/#sys.load_resource). +`custom_resources` +: Zasoby dołączane do głównego archiwum gry przez pole *Custom Resources* w *game.project*. Więcej o ich ładowaniu znajdziesz w [instrukcji File Access](/manuals/file-access/#how-to-access-files-bundled-with-the-application). #### Bundle Resources -Zasoby paczki - lista oddzielonych przecinkami lokalizacji zasobów zawierających pliki i katalogi, które można skopiować w obecnym stanie do paczki wynikowej podczas budowania. Lokalizacje muszą być opisane ścieżkami bezwzględnymi od poziomu głównego katalogu Twojego projektu, np. `/res`. Taka lokalizacja z zasobami musi zawierać podfoldery nazwane zgodnie z platformą (`platform` lub `architecure-platform`). - - Wspierane platformy to: `ios`, `android`, `osx`, `win32`, `linux`, `web`. - - Dozwolony jest również podfolder `common` zawierający zasoby wspólne dla wszystkich platform. +`bundle_resources` +: Dodatkowe pliki i katalogi dołączane bezpośrednio do bundla aplikacji przez pole *Bundle Resources* w *game.project*. Więcej o ich użyciu znajdziesz w [instrukcji File Access](/manuals/file-access/#how-to-access-files-bundled-with-the-application). #### Bundle Exclude Resources -Zasoby, które należy usunąć z paczki - lista oddzielonych przecinkami zasobów, które nie będą dołączane do paczki. +`bundle_exclude_resources` +Lista zasobów rozdzielonych przecinkami, które nie powinny zostać dołączone do bundla. Są usuwane z wyniku kroku zbierania zasobów `bundle_resources`. + +--- -## Bootstrap (Ustawienia początkowe) +### Bootstrap #### Main Collection -Główna kolekcja - referencja do pliku kolekcji używanej w aplikacji jako startowa, domyślnie: `/logic/main.collection`. +Odwołanie do pliku kolekcji używanej przy uruchamianiu aplikacji. Domyślnie `/logic/main.collection`. #### Render -Referencja do pliku render określającego sposób renderowania, domyślnie: `/builtins/render/default.render`. +Plik konfiguracji renderowania definiujący pipeline renderowania. Domyślnie `/builtins/render/default.render`. -## Library (Biblioteki) +--- + +### Library #### Include Dirs -Dołączane lokalizacje - lista oddzielonych spacjami lokalizacji, które będą współdzielone z Twojego projektu poprzez udostępnianie bibliotek. +Lista katalogów rozdzielonych spacjami, które mają być współdzielone z projektu przez mechanizm bibliotek. Więcej informacji znajdziesz w [instrukcji Libraries](/manuals/libraries/). -## Script (Skrypy) +--- + +### Script #### Shared State -Stan współdzielony - Gdy opcja ta jest zaznaczona, projekt dzieli wspólny, pojedynczy stan Lua pomiędzy wszystkimi skryptami. Domyślnie odznaczone. +Zaznacz, aby współdzielić pojedynczy stan Lua między wszystkimi typami skryptów. + +--- -## Engine (silnik) +### Engine #### Run While Iconified -Kontynuuj po zminimalizowaniu okna - pozwól silnikowi na kontynuację pracy, gdy okno aplikacji jest zminimalizowane (dotyczy tylko komputerów), domyślnie odznaczone - `false`. +Pozwala silnikowi działać dalej, gdy okno aplikacji jest zminimalizowane lub zredukowane do ikony. Dotyczy tylko platform desktopowych. + +#### Fixed Update Frequency +Częstotliwość aktualizacji funkcji cyklu życia `fixed_update(self, dt)`, wyrażona w hercach. + +#### Max Time Step +Jeśli krok czasu w pojedynczej klatce stanie się zbyt duży, zostanie ograniczony do tej maksymalnej wartości. Jednostką są sekundy. + +--- -## Display (Wyświetlanie) +### Display #### Width -Szerokość okna aplikacji w pikselach, domyślnie: `960`. +Szerokość okna aplikacji w pikselach. #### Height -Wysokość okna aplikacji w pikselach, domyślnie: `640`. +Wysokość okna aplikacji w pikselach. #### High Dpi -Tworzy bufor High Dpi na wyświetlaczach, które to wspierają. Gra zostanie wyrenderowana w rozdzielczości dwukrotnie większej niż podana w ustawieniach *Width* i *Height*, ale podana rozdzielczość będzie nadal rozdzielczością dla logiki gry. +Tworzy bufor o wysokim DPI na wyświetlaczach, które to wspierają. Zwykle gra będzie renderowana w rozdzielczości dwukrotnie wyższej od ustawień *Width* i *Height*, ale wartości te nadal pozostaną logiczną rozdzielczością używaną w skryptach i właściwościach. #### Samples -Określa jak wiele próbek aplikacja ma używać przy anty-aliasingu. Ustawia wartość GLFW_FSAA_SAMPLES dla okna. Domyślnie: `0`, co oznacza, że anty-aliasing jest wyłączony. +Liczba próbek używanych do supersamplingu antyaliasingu. Ustawia wartość podpowiedzi okna `GLFW_FSAA_SAMPLES`. Wartość `0` wyłącza antyaliasing. #### Fullscreen -Zaznacz, żeby aplikacja startowała w trybie pełnego ekranu. Odznacz, żeby startowała w oknie. +Zaznacz, jeśli aplikacja ma startować w trybie pełnoekranowym. Gdy pole nie jest zaznaczone, aplikacja uruchomi się w oknie. + +#### Update Frequency +Docelowa liczba klatek na sekundę, wyrażona w hercach. Ustaw `0`, aby używać zmiennej liczby klatek. Wartość większa od `0` powoduje użycie stałej liczby klatek ograniczanej w czasie działania do rzeczywistej częstotliwości, co oznacza, że pętla gry nie może zostać wykonana dwa razy w ramach jednej klatki silnika. Wartość można zmieniać w czasie działania funkcją [`sys.set_update_frequency(hz)`](https://defold.com/ref/stable/sys/?q=set_update_frequency#sys.set_update_frequency:frequency). To ustawienie działa także w buildach headless. -#### Frame Cap -Jeśli opcja `Vsync` jest zaznaczona, przybliż do najbliższego pasującego przedziału wymiany dla ustawionego limiu ramki, jeśli monitor jest wykryty. W przeciwnym przypadku używaj timer'ów w celu zgodności z ustawioną wartością. 0 oznacza, że nie ma limitu. Ustawienie to dotyczy `display.update_frequency`. +#### Swap interval +Ta liczba całkowita steruje sposobem obsługi vsync. `0` wyłącza vsync, a wartością domyślną jest `1`. Przy adapterze OpenGL wartość określa liczbę klatek pomiędzy [zamianami buforów](https://www.khronos.org/opengl/wiki/Swap_Interval). W przypadku Vulkana nie istnieje wbudowane pojęcie swap interval, więc wartość określa po prostu, czy vsync ma być włączony. #### Vsync -Vertical sync, czyli pionowa synchronizacja - polegaj na sprzętowej synchronizacji do określania czasu ramki. Może być nadpisane w zależności od sterownika karty graficznej i specyfiki platformy. +Polegaj na sprzętowym vsync przy wyznaczaniu czasu klatki. To ustawienie może zostać nadpisane przez sterownik graficzny lub specyfikę platformy. Aby uzyskać przestarzałe zachowanie `variable_dt`, odznacz tę opcję i ustaw limit liczby klatek na `0`. #### Display Profiles -Profile wyświetlania - określa, których profili używać, domyślnie: `/builtins/render/default.display_profilesc`. Więce szczegółów znajdziesz w [instrukcji do layout'ów GUI](/manuals/gui-layouts/#creating-display-profiles). +Określa plik profili wyświetlania, którego należy użyć. Domyślnie `/builtins/render/default.display_profilesc`. Więcej informacji znajdziesz w [instrukcji GUI Layouts](/manuals/gui-layouts/#creating-display-profiles). #### Dynamic Orientation -Dynamiczna orientacja - zaznacz, żeby pozwolić aplikacji dynamicznie zmieniać między ustawieniem horyzontalnym i portretowym w zależności od orientacji urządzenia. Aplikacja deweloperska dmegine obecnie nie respektuje tego ustawienia. +Zaznacz, jeśli aplikacja ma dynamicznie przełączać się między orientacją pionową i poziomą po obróceniu urządzenia. Aplikacja deweloperska obecnie nie respektuje tego ustawienia. -## Render (Renderowanie) +#### Display Device Info +Wypisuje informacje o GPU do konsoli podczas uruchamiania. + +--- + +### Render #### Clear Color Red -Czerwona składowa koloru czyszczenia ekranu, używana przez skrypt renderowania, kiedy okno jest tworzone. Dodano w 1.2.167. +Składowa czerwona koloru czyszczenia, używana przez skrypt renderujący i przy tworzeniu okna. #### Clear Color Green -Zielona składowa koloru czyszczenia ekranu, używana przez skrypt renderowania, kiedy okno jest tworzone. Dodano w 1.2.167. +Składowa zielona koloru czyszczenia, używana przez skrypt renderujący i przy tworzeniu okna. #### Clear Color Blue -Niebieska składowa koloru czyszczenia ekranu, używana przez skrypt renderowania, kiedy okno jest tworzone. Dodano w 1.2.167. +Składowa niebieska koloru czyszczenia, używana przez skrypt renderujący i przy tworzeniu okna. #### Clear Color Alpha -Składowa koloru czyszczenia ekranu odpowiedzialna za transparentność, używana przez skrypt renderowania, kiedy okno jest tworzone. Dodano w 1.2.167. +Składowa alfa koloru czyszczenia, używana przez skrypt renderujący i przy tworzeniu okna. + +--- -## Physics (Fizyka) +### Font + +#### Runtime Generation +Włącz generowanie fontów w czasie działania. + +--- + +### Physics + +#### Max Collision Object Count +Maksymalna liczba obiektów kolizji. #### Type -Jaki typ fizyki jest używany: `2D` (domyślnie) albo `3D`. +Typ fizyki, którego należy użyć: `2D` albo `3D`. + +#### Gravity X +Grawitacja świata wzdłuż osi X, w metrach na sekundę. #### Gravity Y -Składowa Y wektora siły grawitacji, domyślnie `-10` (ziemska grawitacja). +Grawitacja świata wzdłuż osi Y, w metrach na sekundę. + +#### Gravity Z +Grawitacja świata wzdłuż osi Z, w metrach na sekundę. #### Debug -Zaznacz, żeby wizualizować fizykę do celów debugowania. +Zaznacz, aby wizualizować fizykę do celów debugowania. #### Debug Alpha -Składowa koloru wizualizacji fizyki odpowiedzialna za transparentność z przedziału `0`--`1`. Domyślnie: `0.9`. +Wartość składowej alfa dla wizualizacji fizyki, z zakresu `0`--`1`. #### World Count -Maksymalna liczba oddzielnych światów z fizyką, domyślnie: `4`. Jeśli wczytujesz więcej niż 4 światy poprzez pełnomocników kolekcji (collection proxies) musisz zwiększyć tę wartość. Pamiętaj, że każdy osobny świat fizyki zajmuje odpowiednią ilość pamięci. - -#### Gravity X -Składowa X wektora siły grawitacji, domyślnie `0`. - -#### Gravity Z -Składowa Z wektora siły grawitacji, domyślnie `0`. +Maksymalna liczba jednoczesnych światów fizyki. Domyślnie `4`. Jeśli przez pełnomocników kolekcji wczytujesz więcej niż 4 światy jednocześnie, musisz zwiększyć tę wartość. Pamiętaj, że każdy świat fizyki zużywa sporą ilość pamięci. #### Scale -Skala fizyki - pomaga silnikowi określić w jaki sposób skalować wartości świata fizyki, aby zachować precyzję numeryczną, z przedziału `0.01`--`1.0`. Jeśli ustawisz wartość `0.02`, oznacza to, że świat fizyki będzie postrzegał 50 jednostek jako jeden metr.($1 / 0.02$). Domyślnie: `1.0`. +Informuje silnik fizyki, jak skalować świat fizyczny względem świata gry dla zachowania precyzji numerycznej, w zakresie `0.01`--`1.0`. Jeśli wartość wynosi `0.02`, oznacza to, że silnik fizyki traktuje 50 jednostek jako 1 metr ($1 / 0.02$). #### Allow Dynamic Transforms -Zaznacz, aby silnik fizyki skalował obiekty kolizji używając skali obiektów gry, do których należą. +Zaznacz, jeśli silnik fizyki ma stosować transformację obiektu gry do dołączonych komponentów obiektu kolizji. Umożliwia to przesuwanie, skalowanie i obracanie kształtów kolizji, także tych dynamicznych. + +#### Use Fixed Timestep +Zaznacz, jeśli silnik fizyki ma używać stałych, niezależnych od liczby klatek aktualizacji. Tego ustawienia należy używać razem z funkcją cyklu życia `fixed_update(self, dt)` oraz ustawieniem projektu `engine.fixed_update_frequency`, aby wchodzić w interakcję z fizyką w regularnych odstępach. Dla nowych projektów zalecaną wartością jest `true`. #### Debug Scale -Określa jak duże rysować obiekty służące do debugowania fizyki - np. wektory normalne, domyślnie `30`. +Określa rozmiar obiektów jednostkowych rysowanych w debugowaniu fizyki, takich jak osie lokalne i normalne. #### Max Collisions -Określa jak wiele kolizji będzie obsługiwanych przez skrypty, domyślnie `64`. +Określa, ile kolizji zostanie przekazanych do skryptów. #### Max Contacts -Określa jak wiele punktów styku będzie obsługiwanych przez skrypty, domyślnie `128`. +Określa, ile punktów kontaktu zostanie przekazanych do skryptów. #### Contact Impulse Limit -Silnik zignoruje zderzenia z impulsem mniejszym niż ta wartość, domyślnie `0.0`. +Ignoruje impulsy kontaktu o wartościach mniejszych niż to ustawienie. #### Ray Cast Limit 2d -Maksymalna liczba promieni 2D rzucanych w czasie jednej ramki, domyślnie `64`. +Maksymalna liczba zapytań ray cast 2D na klatkę. #### Ray Cast Limit 3d -Maksymalna liczba promieni 3D rzucanych w czasie jednej ramki, domyślnie `128`. +Maksymalna liczba zapytań ray cast 3D na klatkę. #### Trigger Overlap Capacity -Maksymalna liczba pokrywających się przełączników (triggers), domyślnie `16`. +Maksymalna liczba nakładających się triggerów fizyki. + +#### Velocity Threshold +Minimalna prędkość powodująca zderzenia sprężyste. + +#### Max Fixed Timesteps +Maksymalna liczba kroków symulacji przy użyciu stałego kroku czasu. Dotyczy tylko 3D. -## Graphics (Grafika) +--- + +### Graphics #### Default Texture Min Filter -Określa jakiego filtra używać podczas pomniejszającego filtrowania tekstur, `linear` (domyślnie) lub `nearest`. +Określa filtr używany przy minifikacji tekstur. #### Default Texture Mag Filter -Określa jakiego filtra używać podczas powiększającego filtrowania tekstur, `linear` (domyślnie) lub `nearest`. +Określa filtr używany przy magnifikacji tekstur. #### Max Draw Calls -Maksymalna liczba wywołań rysowania grafiki (renderowania, ang. render calls), domyślnie `1024`. +Maksymalna liczba wywołań renderowania. #### Max Characters: -Maksymalna liczba znaków zaalokowanych wcześniej w buforze renderowania tekstu, czyli liczba znaków, które można wyświetlić w każdej ramce, domyślnie `8192`. +Liczba znaków prealokowanych w buforze renderowania tekstu, czyli liczba znaków możliwych do wyświetlenia w każdej klatce. + +#### Max Font Batches +Maksymalna liczba partii tekstu, które można wyświetlić w każdej klatce. #### Max Debug Vertices -Maksymalna liczba punktów służących do debugowania, między innymi do rysowania kształtów silnika fizyki, domyślnie `10000`. +Maksymalna liczba wierzchołków debugowania. Używana między innymi do renderowania kształtów fizyki. #### Texture Profiles -Określa jakiego profilu teksturowania należy używać do tego projektu, domyślnie `/builtins/graphics/default.texture_profiles`. +Plik profili teksturowania używany przez projekt. Domyślnie `/builtins/graphics/default.texture_profiles`. -## Input (Wejścia) +#### Verify Graphics Calls +Sprawdza wartość zwrotną po każdym wywołaniu grafiki i raportuje błędy w logu. + +#### OpenGL Version Hint +Podpowiedź dotycząca wersji kontekstu OpenGL. Jeśli wybierzesz konkretną wersję, będzie ona używana jako minimalnie wymagana wersja. Nie dotyczy OpenGL ES. + +#### OpenGL Core Profile Hint +Ustawia podpowiedź profilu `core` podczas tworzenia kontekstu. Profil core usuwa wszystkie przestarzałe funkcje OpenGL, takie jak renderowanie w trybie immediate. Nie dotyczy OpenGL ES. + +--- + +### Shader + +#### Exclude GLES 2.0 +Nie kompiluj shaderów dla urządzeń używających OpenGLES 2.0 / WebGL 1.0. + +--- + +### Input #### Repeat Delay -Czas w sekundach, który należy odczekać po odczytaniu danego wejścia, zanim to samo wejście może zostać powtórzone, domyślnie `0.5`. +Liczba sekund oczekiwania, zanim przytrzymane wejście zacznie się powtarzać. #### Repeat Interval -Czas w sekundach, który należy odczekać po odczytaniu danego wejścia, które jest ciągle wciskane, zanim to samo wejście może zostać odczytane jako powtórzone, domyślnie `0.2`. +Liczba sekund pomiędzy kolejnymi powtórzeniami przytrzymanego wejścia. #### Gamepads -Określa jakiego pliku należy używać do konfiguracji kontrolerów, który mapuje wejścia kontrolera do systemu operacyjnego, domyślnie `/builtins/input/default.gamepads`. +Odwołanie do pliku konfiguracji gamepadów mapującego sygnały gamepada na system operacyjny. Domyślnie `/builtins/input/default.gamepads`. #### Game Binding -Określa jakiego pliku należy używać do konfiguracji wejść, który mapuje wejścia sprzętowe do podanych akcji, domyślnie `/input/game.input_binding`. +Odwołanie do pliku konfiguracji wejść mapującego sprzętowe wejścia na akcje. Domyślnie `/input/game.input_binding`. #### Use Accelerometer -Zaznacz, żeby silnik mógł otrzymywać dane z akceleratora jako wejście dla każdej ramki. Wyłączenie akcelerometra może dawać korzyści pod względem wydajności. Domyślnie zaznaczone. +Zaznacz, aby silnik otrzymywał zdarzenia z akcelerometru w każdej klatce. Wyłączenie akcelerometru może przynieść pewne korzyści wydajnościowe. + +--- -## Resource (Źródła) +### Resource #### Http Cache -Kiedy zaznaczone, pamięć podręczna (cache) HTTP jest aktywowana, aby szybciej ładować zasoby przez sieć do działającego na urządzeniu silnika. Domyślnie odznaczone. +Po zaznaczeniu włącza pamięć podręczną HTTP, aby szybciej ładować przez sieć zasoby do silnika uruchomionego na urządzeniu. #### Uri -Wskazuje gdzie szukać danych do budowania projektu, w formacie URI. +Określa lokalizację danych builda projektu w formacie URI. #### Max Resources -Maksymalna liczba zasobów, które mogą być załadowane jednocześnie, domyślnie `1024`. +Maksymalna liczba zasobów, które mogą być załadowane jednocześnie. + +--- -## Network (Sieć) +### Network #### Http Timeout -Czas w sekundach do zaniechania czekania na odpowiedź HTTP. Ustaw na `0`, żeby wyłączyć timeout, domyślnie właśnie wyłączony, czyli czeka na odpowiedź nieskończenie długo. +Limit czasu HTTP w sekundach. Ustaw `0`, aby wyłączyć limit czasu. -## Collection (Kolekcje) +#### Http Thread Count +Liczba wątków roboczych używanych przez usługę HTTP. + +#### Http Cache Enabled +Zaznacz, aby włączyć pamięć podręczną HTTP dla żądań sieciowych wykonywanych przez `http.request()`. Cache HTTP przechowuje odpowiedź skojarzoną z żądaniem i ponownie używa jej przy kolejnych żądaniach. Obsługiwane są nagłówki odpowiedzi `ETag` i `Cache-Control: max-age`. + +#### SSL Certificates +Plik zawierający główne certyfikaty SSL używane przy weryfikacji łańcucha certyfikatów podczas handshake SSL. + +--- + +### Collection #### Max Instances -Maksymalna liczba instancji obiektów gry w jednej kolekcji, domyślnie `1024`. +Maksymalna liczba instancji obiektów gry w kolekcji. Domyślnie `1024`. Zobacz też informacje o [optymalizacji liczników maksymalnych komponentów](#component-max-count-optimizations). + +#### Max Input Stack Entries +Maksymalna liczba obiektów gry na stosie wejścia. -## Sound (Dźwięk) +--- + +### Sound #### Gain -Globalne wzmocnienie dźwięku (volume), `0`--`1`, domyślnie `1`. +Globalne wzmocnienie dźwięku (głośność), `0`--`1`. + +#### Use Linear Gain +Po włączeniu wzmocnienie jest liniowe. Po wyłączeniu używana jest krzywa wykładnicza. #### Max Sound Data -Maksymalna liczba źródeł dźwięku, czyli liczba unikalnych plików dźwiękowych, które można otworzyć jednocześnie, domyślnie `128`. +Maksymalna liczba zasobów dźwiękowych, czyli unikalnych plików dźwiękowych dostępnych w czasie działania. #### Max Sound Buffers -(Obecnie nie używane) Maksymalna liczba jednocześnie istniejących buforów dźwiękowych, domyślnie `32`. +(Obecnie nieużywane) Maksymalna liczba jednoczesnych buforów dźwięku. #### Max Sound Sources -(Obecnie nie używane) Maksymalna liczba jednocześnie istniejących źródeł dźwięku, domyślnie `16`. +(Obecnie nieużywane) Maksymalna liczba jednocześnie odtwarzanych dźwięków. #### Max Sound Instances -Maksymalna liczba jednocześnie istniejących instancji dźwięku, czyli liczba aktualnych dźwięków odtwarzanych w tym samym momencie, domyślnie `256`. +Maksymalna liczba jednoczesnych instancji dźwięku, czyli rzeczywistych dźwięków odtwarzanych w tym samym momencie. + +#### Max Component Count +Maksymalna liczba komponentów dźwięku w jednej kolekcji. + +#### Sample Frame Count +Liczba próbek używanych przy każdej aktualizacji audio. `0` oznacza tryb automatyczny (`1024` dla 48 kHz, `768` dla 44.1 kHz). + +#### Use Thread +Po zaznaczeniu system dźwięku używa wątków do odtwarzania audio, aby zmniejszyć ryzyko zacięć, gdy główny wątek jest mocno obciążony. + +#### Stream Enabled +Po zaznaczeniu system dźwięku używa streamingu do ładowania plików źródłowych. -## Sprite (Obrazy) +#### Stream Cache Size +Maksymalny rozmiar cache fragmentów dźwięku zawierającego *wszystkie* fragmenty. Domyślnie `2097152` bajty. Ta wartość powinna być większa niż liczba załadowanych plików dźwiękowych pomnożona przez rozmiar fragmentu streamingu, w przeciwnym razie nowe fragmenty mogą być usuwane z cache w każdej klatce. + +#### Stream Chunk Size +Rozmiar w bajtach każdego fragmentu ładowanego strumieniowo. + +#### Stream Preload Size +Określa rozmiar w bajtach początkowego fragmentu plików dźwiękowych wczytywanych z archiwum. + +--- + +### Sprite #### Max Count -Maksymalna liczba sprite'ów w jednej kolekcji, domyślnie `128`. +Maksymalna liczba sprite'ów w jednej kolekcji. Zobacz też informacje o [optymalizacji liczników maksymalnych komponentów](#component-max-count-optimizations). #### Subpixels -Zaznacz, aby pozwolić sprite'om pojawiać się nieprzylegając do pełnych pikseli, domyślnie zaznaczone. +Zaznacz, aby pozwolić sprite'om pojawiać się poza siatką pełnych pikseli. + +--- -## Tilemap (Mapy kafelków) +### Tilemap #### Max Count -Maksymalna liczba map kafelków w jednej kolekcji, domyślnie `16`. +Maksymalna liczba map kafelków w jednej kolekcji. Zobacz też informacje o [optymalizacji liczników maksymalnych komponentów](#component-max-count-optimizations). #### Max Tile Count -Maksymalna liczba jednocześnie widocznych kafelków w jednej kolekcji, domyślnie `2048`. +Maksymalna liczba jednocześnie widocznych kafelków w jednej kolekcji. + +--- -## Spine +### Spine #### Max Count -Maksymalna liczba modeli szkieletowych Spine, domyślnie `128`. +Maksymalna liczba komponentów modelu Spine. Zobacz też informacje o [optymalizacji liczników maksymalnych komponentów](#component-max-count-optimizations). -## GUI +--- + +### Mesh #### Max Count -Maksymalna liczba komponentów GUI, domyślnie `64`. +Maksymalna liczba komponentów Mesh w jednej kolekcji. Zobacz też informacje o [optymalizacji liczników maksymalnych komponentów](#component-max-count-optimizations). -#### Max Particlefx Count -Maksymalna liczba jednocześnie istniejących emiterów cząsteczek w GUI, domyślnie `64`. +--- + +### Model + +#### Max Count +Maksymalna liczba komponentów Model w jednej kolekcji. Zobacz też informacje o [optymalizacji liczników maksymalnych komponentów](#component-max-count-optimizations). + +#### Split Meshes +Podziel siatki mające więcej niż 65536 wierzchołków na nowe siatki. + +#### Max Bone Matrix Texture Width +Maksymalna szerokość tekstury macierzy kości. Używany jest tylko rozmiar potrzebny animacjom, zaokrąglany w górę do najbliższej potęgi dwójki. + +#### Max Bone Matrix Texture Height +Maksymalna wysokość tekstury macierzy kości. Używany jest tylko rozmiar potrzebny animacjom, zaokrąglany w górę do najbliższej potęgi dwójki. + +--- + +### GUI + +#### Max Count +Maksymalna liczba komponentów GUI. Zobacz też informacje o [optymalizacji liczników maksymalnych komponentów](#component-max-count-optimizations). #### Max Particle Count -Maksymalna liczba jednocześnie istniejących cząsteczek w GUI, domyślnie `1024`. +Maksymalna liczba jednoczesnych cząsteczek w GUI. + +#### Max Animation Count +Maksymalna liczba aktywnych animacji w GUI. + +--- -## Label (Etykieta) +### Label #### Max Count -Maksymalna liczba etykiet z tekstem, domyślnie `64`. +Maksymalna liczba etykiet. Zobacz też informacje o [optymalizacji liczników maksymalnych komponentów](#component-max-count-optimizations). #### Subpixels -Zaznacz, aby pozwolić etykietom pojawiać się nieprzylegając do pełnych pikseli, domyślnie zaznaczone. +Zaznacz, aby pozwolić etykietom pojawiać się poza siatką pełnych pikseli. + +--- -## Particle FX (Efekty cząsteczkowe) +### Particle FX #### Max Count -Maksymalna liczba jednocześnie istniejących emiterów cząsteczek, domyślnie `64`. +Maksymalna liczba jednoczesnych emiterów. Zobacz też informacje o [optymalizacji liczników maksymalnych komponentów](#component-max-count-optimizations). #### Max Particle Count -Maksymalna liczba jednocześnie istniejących cząsteczek, domyślnie `1024`. +Maksymalna liczba jednoczesnych cząsteczek. + +--- + +### Box2D + +#### Velocity Iterations +Liczba iteracji prędkości dla solvera fizyki Box2D 2.2. -## Collection proxy (Pełnomocnicy kolekcji) +#### Position Iterations +Liczba iteracji pozycji dla solvera fizyki Box2D 2.2. + +#### Sub Step Count +Liczba podkroków dla solvera fizyki Box2D 3.x. + +--- + +### Collection proxy #### Max Count -Maksymalna liczba pełnomocników kolekcji, domyślnie `8`. +Maksymalna liczba pełnomocników kolekcji. Zobacz też informacje o [optymalizacji liczników maksymalnych komponentów](#component-max-count-optimizations). + +--- -## Collection factory (Fabryki kolekcji) +### Collection factory #### Max Count -Maksymalna liczba fabryk kolekcji, domyślnie `128`. +Maksymalna liczba fabryk kolekcji. Zobacz też informacje o [optymalizacji liczników maksymalnych komponentów](#component-max-count-optimizations). -## Factory (Fabryki) +--- + +### Factory #### Max Count -Maksymalna liczba fabryk, domyślnie `128`. +Maksymalna liczba fabryk obiektów gry. Zobacz też informacje o [optymalizacji liczników maksymalnych komponentów](#component-max-count-optimizations). + +--- -## iOS +### iOS #### App Icon 57x57--180x180 -Plik graficzny (.png) używany jako ikona aplikacji o podanych wymiarach `W` × `H`. +Plik obrazu `.png` używany jako ikona aplikacji dla podanych wymiarów `W` × `H`. #### Launch Screen -Plik Storyboard (.storyboard). Więcej szczegółów znajdziesz w [instrukcji do systemu iOS](/manuals/ios/#creating-a-storyboard). +Plik storyboard `.storyboard`. Więcej informacji o jego tworzeniu znajdziesz w [instrukcji iOS](/manuals/ios/#creating-a-storyboard). -#### Pre Rendered Icons -(Dotyczy iOS 6 i wcześniejszych wersji) Zaznacz, żeby ikony były pre-renderowane. Jeśli ta opcja nie jest zaznaczona ikony będą miały automatycznie dodany świetlistą poświatę. +#### Icons Asset +Plik zasobu ikon `.car` zawierający ikony aplikacji. + +#### Prerendered Icons +(iOS 6 i starsze) Zaznacz, jeśli ikony są prerenderowane. Gdy to pole nie jest zaznaczone, system automatycznie doda błyszczące podświetlenie. #### Bundle Identifier -Identyfikator paczki - pozwala systemowi iOS rozpoznawać Twoją aplikację przy aktualizacjach. ID Twojej paczki musi być zarejestrowane przez Apple i być dla niej unikalne. Nie można używać tego samego identyfikatora dla aplikacji iOS i macOS. +Identyfikator bundla pozwalający iOS rozpoznawać aktualizacje aplikacji. Musi być zarejestrowany w Apple i unikalny dla aplikacji. Nie można używać tego samego identyfikatora dla aplikacji iOS i macOS. Musi składać się z co najmniej dwóch segmentów oddzielonych kropką. Każdy segment musi zaczynać się literą i może zawierać tylko litery alfanumeryczne, znak podkreślenia lub myślnik (`-`). Zobacz [`CFBundleIdentifier`](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-130430). + +#### Bundle Name +Krótka nazwa bundla, maksymalnie 15 znaków. Zobacz [`CFBundleName`](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-130430). + +#### Bundle Version +Wersja bundla zapisana jako liczba albo `x.y.z`. Zobacz [`CFBundleVersion`](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-130430). #### Info.plist -Jeśli podany - używany będzie określony plik info.plist podczas budowania paczki aplikacji. +Jeśli ustawiono, podczas bundlowania aplikacji zostanie użyty wskazany plik *`info.plist`*. -#### Entitlements -Uprawnienia - jeśli podane, mogą nadpisać domyślne uprawnienia określone w profilach nadzorujących (`.entitlements`, `.xcent`, `.plist`). +#### Privacy Manifest +Apple Privacy Manifest dla aplikacji. Domyślną wartością pola jest `/builtins/manifests/ios/PrivacyInfo.xcprivacy`. + +#### Custom Entitlements +Jeśli ustawiono, uprawnienia z dostarczonego profilu provisioning (`.entitlements`, `.xcent`, `.plist`) zostaną połączone z uprawnieniami z profilu provisioning podanego podczas bundlowania aplikacji. #### Default Language -Domyślny jeżyk aplikacji - używany, jeśli użytkownik nie posiada wybranego preferowanego języka domyślnego w liście `Localizations` (zobacz: [CFBundleDevelopmentRegion](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-130430)). Należy tutaj użyć dwuznakowego symbolu kraju zgodnego ze standardem ISO 639-1, jeśli preferowany język znajduje się w standardzie, w przeciwnym przypadku - trójznakowego symbolu ze standardu ISO 639-2. +Język używany, jeśli aplikacja nie zawiera preferowanego języka użytkownika na liście `Localizations`. Zobacz [`CFBundleDevelopmentRegion`](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-130430). Użyj dwuliterowego standardu ISO 639-1, jeśli język jest tam dostępny, w przeciwnym razie trzy-literowego ISO 639-2. #### Localizations -Ustawienia regionalne - pole zawiera oddzielone przecinkami słowa (strings) identyfikujące nazwę języka lub oznaczenie języka ISO wspieranych lokalizacji (zobacz: [CFBundleLocalizations](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-109552)). +Pole zawierające oddzielone przecinkami ciągi identyfikujące nazwę języka lub oznaczenie ISO dla obsługiwanych lokalizacji. Zobacz [`CFBundleLocalizations`](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-109552). + +--- -## Android +### Android #### App Icon 36x36--192x192 -Plik graficzny (.png) używany jako ikona aplikacji o podanych wymiarach `W` × `H`. +Plik obrazu `.png` używany jako ikona aplikacji dla podanych wymiarów `W` × `H`. #### Push Icon Small--LargeXxxhdpi -Plik graficzny (.png) używany jako ikona aplikacji w powiadomieniach *push* systemu Android. Ikony będą używane automatycznie zarówno do lokalnych i zdalnych powiadomień. Jeśli nie podano ikony, domyślna ikona aplikacji będzie używana. +Pliki obrazów `.png` używane jako własne ikony powiadomień push na Androidzie. Ikony będą automatycznie używane zarówno dla powiadomień lokalnych, jak i zdalnych. Jeśli nie są ustawione, domyślnie używana będzie ikona aplikacji. #### Push Field Title -Określa jakie pole z pliku JSON (payload) ma być użyte jako tytuł powiadomienia. Pozostawienie tego pola pustego sprawia, że domyślnie używana jest nazwa aplikacji. +Określa, które pole JSON z payloadu ma zostać użyte jako tytuł powiadomienia. Jeśli pole jest puste, jako tytuł używana jest nazwa aplikacji. #### Push Field Text -Określa jakie pole z pliku JSON (payload) ma być użyte jako treść powiadomienia. Pozostawienie tego pola pustego sprawia, że domyślnie używany jest tekst `alert`, tak jak dla iOS. +Określa, które pole JSON z payloadu ma zostać użyte jako treść powiadomienia. Jeśli pole jest puste, używana jest wartość z pola `alert`, tak jak na iOS. #### Version Code -Kod wersji - wartość numeryczna całkowita (integer) określająca wersję aplikacji. Zwiększaj tę wartość przy każdej aktualizacji. +Całkowita wartość liczbowa oznaczająca wersję aplikacji. Należy ją zwiększać przy każdej kolejnej aktualizacji. + +#### Minimum SDK Version +Minimalny poziom API wymagany do uruchomienia aplikacji (`android:minSdkVersion`). + +#### Target SDK Version +Poziom API, na który aplikacja jest targetowana (`android:targetSdkVersion`). #### Package -Identyfikator paczki. +Identyfikator pakietu. Musi składać się z co najmniej dwóch segmentów oddzielonych kropką. Każdy segment musi zaczynać się literą i może zawierać tylko litery alfanumeryczne oraz znak podkreślenia. + +#### GCM Sender Id +Google Cloud Messaging Sender Id. Ustaw tutaj ciąg znaków przypisany przez Google, aby włączyć powiadomienia push. -#### Gcm Sender Id -Google Cloud Messaging Sender Id. Podaj tutaj string przypisany przez Google, aby aktywować powiadomienia *push*. +#### FCM Application Id +Identyfikator aplikacji Firebase Cloud Messaging. #### Manifest -Plik XML - jeśli podany, będzie używany podczas budowania paczki. +Jeśli ustawiono, podczas bundlowania zostanie użyty wskazany plik Android Manifest XML. #### Iap Provider -Określa jakiego sklepu używać do zakupów wewnątrz aplikacji (ang. In App Purchases). Możliwe opcje to `Amazon` i `GooglePlay` (domyślnie). +Określa, którego sklepu używać. Poprawne wartości to `Amazon` i `GooglePlay`. Więcej informacji znajdziesz w [extension-iap](/extension-iap/). #### Input Method -Określa jakich sposobów obsługi klawiatury na urządzeniach z Androidem używać. Możliwe opcje to `KeyEvent` (stara metoda, domyślna) i `HiddenInputField` (nowa). +Określa metodę pobierania wejścia z klawiatury na urządzeniach z Androidem. Poprawne wartości to `KeyEvent` (stara metoda) oraz `HiddenInputField` (nowa). #### Immersive Mode -Tryb imersyjny. Jeśli ustawiony, ukrywa przyciski nawigacji i górny pasek statusu systemu Android oraz pozwala aplikacji na wykrywanie i przechwytywanie dotyku na powierzchni całego ekranu. +Po włączeniu ukrywa pasek nawigacji i pasek statusu oraz pozwala aplikacji przechwytywać wszystkie zdarzenia dotyku na ekranie. + +#### Display Cutout +Pozwala rozszerzyć obraz na obszar wycięcia ekranu. #### Debuggable -Określa czy aplikacja może być debugowana używając takich narzędzi jak [GAPID](https://github.com/google/gapid) lub [Android Studio](https://developer.android.com/studio/profile/android-profiler). Ustawia flagę `android:debuggable` w manifeście systemu Android. +Określa, czy aplikację można debugować narzędziami takimi jak [GAPID](https://github.com/google/gapid) albo [Android Studio](https://developer.android.com/studio/profile/android-profiler). Ustawia flagę `android:debuggable` w Android Manifest. Zobacz [oficjalną dokumentację](https://developer.android.com/guide/topics/manifest/application-element#debug). + +#### ProGuard config +Własny plik ProGuard pomagający usunąć zbędne klasy Java z końcowego APK. + +#### Extract Native Libraries +Określa, czy instalator pakietu ma rozpakowywać biblioteki natywne z APK do systemu plików. Jeśli ustawisz `false`, biblioteki będą przechowywane nieskompresowane wewnątrz APK. APK może być wtedy większy, ale aplikacja będzie ładować się szybciej, bo biblioteki będą ładowane bezpośrednio z APK w czasie działania. To ustawienie ustawia flagę `android:extractNativeLibs` w Android Manifest. Zobacz [oficjalną dokumentację](https://developer.android.com/guide/topics/manifest/application-element#extractNativeLibs). -## macOS +--- + +### macOS #### App Icon -Plik graficzny (.png) używany jako ikona aplikacji w systemie macOS. +Plik ikony bundla `.icns` używany jako ikona aplikacji w macOS. #### Info.plist -Jeśli podany - używany będzie określony plik info.plist podczas budowania paczki aplikacji. +Jeśli ustawiono, podczas bundlowania zostanie użyty wskazany plik `info.plist`. + +#### Privacy Manifest +Apple Privacy Manifest dla aplikacji. Domyślną wartością pola jest `/builtins/manifests/osx/PrivacyInfo.xcprivacy`. #### Bundle Identifier -Identyfikator paczki - pozwala systemowi iOS rozpoznawać Twoją aplikację przy aktualizacjach. ID Twojej paczki musi być zarejestrowane przez Apple i być dla niej unikalne. Nie można używać tego samego identyfikatora dla aplikacji iOS i macOS. +Identyfikator bundla pozwalający macOS rozpoznawać aktualizacje aplikacji. Musi być zarejestrowany w Apple i unikalny dla aplikacji. Nie można używać tego samego identyfikatora dla aplikacji iOS i macOS. Musi składać się z co najmniej dwóch segmentów oddzielonych kropką. Każdy segment musi zaczynać się literą i może zawierać tylko litery alfanumeryczne, znak podkreślenia lub myślnik (`-`). #### Default Language -Domyślny jeżyk aplikacji - używany, jeśli użytkownik nie posiada wybranego preferowanego języka domyślnego w liście `Localizations` (zobacz: [CFBundleDevelopmentRegion](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-130430)). Należy tutaj użyć dwuznakowego symbolu kraju zgodnego ze standardem ISO 639-1, jeśli preferowany język znajduje się w standardzie, w przeciwnym przypadku - trójznakowego symbolu ze standardu ISO 639-2. +Język używany, jeśli aplikacja nie zawiera preferowanego języka użytkownika na liście `Localizations`. Zobacz [`CFBundleDevelopmentRegion`](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-130430). Użyj dwuliterowego standardu ISO 639-1, jeśli język jest tam dostępny, w przeciwnym razie trzy-literowego ISO 639-2. #### Localizations -Ustawienia regionalne - pole zawiera oddzielone przecinkami słowa (strings) identyfikujące nazwę języka lub oznaczenie języka ISO wspieranych lokalizacji (zobacz: [CFBundleLocalizations](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-109552)). +Pole zawierające oddzielone przecinkami ciągi identyfikujące nazwę języka lub oznaczenie ISO dla obsługiwanych lokalizacji. Zobacz [`CFBundleLocalizations`](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-109552). -## Windows +--- + +### Windows #### App Icon -Plik graficzny (.ico) używany jako ikona aplikacji w systemie Windows. Więcej szczegółów na temat tworzenia plików .ico znajdziesz w [instrukcji do systemu Windows](/manuals/windows). +Plik obrazu `.ico` używany jako ikona aplikacji w Windows. Więcej informacji o tworzeniu plików `.ico` znajdziesz w [instrukcji Windows](/manuals/windows). -#### Iap Provider -Określa jakiego sklepu używać do zakupów wewnątrz aplikacji (ang. In App Purchases). Możliwe opcje to `None`(domyślnie) i `Gameroom`. +--- + +### HTML5 -## HTML5 +Więcej informacji o wielu z tych opcji znajdziesz w [instrukcji platformy HTML5](/manuals/html5/). #### Heap Size -Rozmiar sterty (liczba megabajtów) dla użycia przez Emscripten. Domyślnie 256MB. +Rozmiar sterty w megabajtach używanej przez Emscripten. #### .html Shell -Używaj określonego szablonu HTML podczas budowania paczki aplikacji, domyślnie: `/builtins/manifests/web/engine_template.html`. +Podczas bundlowania używaj wskazanego szablonu HTML. Domyślnie `/builtins/manifests/web/engine_template.html`. #### Custom .css -Używaj określonego pliku z motywem CSS podczas budowania paczki aplikacji, domyślnie: `/builtins/manifests/web/light_theme.css`. +Podczas bundlowania używaj wskazanego pliku motywu CSS. Domyślnie `/builtins/manifests/web/light_theme.css`. #### Splash Image -Jeśli określony, użyj podanej grafiki jako ekranu startowego podczas budowania paczki aplikacji zamiast domyślnego logo Defold. +Jeśli ustawiono, podczas bundlowania użyj wskazanego obrazu startowego zamiast logo Defold. #### Archive Location Prefix -Podczas budowania paczki aplikacji dane gry HTML5 są rozdzielane na jeden lub więcej plików archiwów. Kiedy silnik uruchamia aplikację, archiwa te są ładowane do pamięci. Użyj tego pola, aby określić lokalizację danych, domyślnie: `archive`. +Podczas bundlowania dla HTML5 dane gry są dzielone na jeden lub więcej plików archiwum. Gdy silnik uruchamia grę, pliki te są wczytywane do pamięci. To ustawienie określa lokalizację tych danych. #### Archive Location Suffix -Przyrostek dodawany do plików archiwów. Użyteczny na przykład przy wymuszaniu nie-buforowanych (non-cache) zawartości z CDN (na przykład: `?version2`). +Sufiks dodawany do plików archiwum. Przydaje się na przykład do wymuszania pobierania niebuforowanej zawartości z CDN, jak `?version2`. #### Engine Arguments -Lista argumentów, które zostaną przekazane do silnika. +Lista argumentów przekazywanych do silnika. + +#### Wasm Streaming +Włącza streaming pliku wasm. Jest szybszy i zużywa mniej pamięci, ale wymaga typu MIME `application/wasm`. #### Show Fullscreen Button -Dodaje przycisk trybu pełnoekranowego do pliku `index.html`. Domyślnie `true`. +Włącza przycisk Fullscreen w pliku `index.html`. #### Show Made With Defold -Dodaje link Made With Defold link do pliku `index.html`. Domyślnie `true`. +Włącza link Made With Defold w pliku `index.html`. + +#### Show Console Banner +Po włączeniu ta opcja wypisuje informacje o silniku i jego wersji w konsoli przeglądarki za pomocą `console.log()` podczas startu silnika. #### Scale Mode -Określa jakiego sposobu skalowania kanwy (obszaru wyświetlania) gry używać. Domyślnie `Downscale Fit`. +Określa metodę skalowania kanwy gry. + +#### Retry Count +Liczba prób pobrania pliku przy uruchamianiu silnika. Zobacz także `Retry Time`. -## IAP (Zakupy wewnątrz aplikacji) +#### Retry Time +Liczba sekund oczekiwania między kolejnymi próbami pobrania pliku po nieudanym pobraniu. Zobacz także `Retry Count`. + +#### Transparent Graphics Context +Zaznacz, jeśli kontekst grafiki ma mieć przezroczyste tło. + +--- + +### IAP #### Auto Finish Transactions -Zaznacz, żeby automatycznie kończyć proces transakcji zakupów IAP. Jeśli odznaczony, musisz jawnie wywołać `iap.finish()` po udanej transakcji, domyślnie zaznaczony. +Zaznacz, aby automatycznie finalizować transakcje IAP. Jeśli pole jest odznaczone, po udanej transakcji trzeba jawnie wywołać `iap.finish()`. -## Live update (Aktualizacje na żywo) +--- -#### Private Key -Jeśli zaznaczone, użyj podanego klucza prywatnego podczas budowania paczki aplikacji z zawartością do aktualizacji *live update*. Jeśli nie podany, zostanie automatycznie wygenerowany. +### Live update -#### Public Key -Jeśli zaznaczone, użyj podanego klucza publicznego podczas budowania paczki aplikacji z zawartością do aktualizacji *live update*. Jeśli nie podany, zostanie automatycznie wygenerowany. +#### Settings +Plik zasobu ustawień Liveupdate używany podczas bundlowania. -## Native extension (Rozszerzenia natywne) +#### Mount On Start +Włącza automatyczne montowanie wcześniej zamontowanych zasobów przy starcie aplikacji. + +--- + +### Native extension #### _App Manifest_ -Jeśli zaznaczone, użyj manifestu aplikacji do personalizacji wersji silnika (engine build). Pozwala to na usunięcie zbędnych części z silnika umożliwiając zmniejszenie ostatecznej wagi aplikacji. Funkcjonalność ta jest w wersji alpha. Odwiedź porszę [ten post na forum](https://forum.defold.com/t/native-extensions/4946/142), aby dowiedzieć się więcej. +Jeśli ustawiono, użyj manifestu aplikacji do dostosowania builda silnika. Pozwala to usunąć nieużywane części silnika i zmniejszyć rozmiar końcowego pliku binarnego. Jak wykluczać nieużywane funkcje opisano w [instrukcji Application Manifest](/manuals/app-manifest). + +--- + +### Profiler -## Profiler +#### Enabled +Włącza profiler w grze. #### Track Cpu -Jeśli zaznaczone, aktywowane będzie profilowanie CPU w wersji release. Normalnie można profilować tylko w wersji debug. +Po zaznaczeniu włącza profilowanie CPU w buildach release. Normalnie informacje profilujące są dostępne tylko w buildach debug. -## Format pliku +#### Sleep Between Server Updates +Liczba milisekund uśpienia pomiędzy aktualizacjami serwera. -Format pliku z ustawieniami jest plikiem tekstowym (INI format) i może być dowolnie modyfikowany przez każdy edytor tekstu. Format wygląda następująco: +#### Performance Timeline Enabled +Włącza przeglądarkową oś czasu wydajności. Dotyczy tylko HTML5. -```ini -[category1] -setting1 = value -setting2 = value -[category2] +--- + +## Setting config values on engine startup + +Podczas uruchamiania silnika można przekazać z linii poleceń wartości konfiguracji, które nadpiszą ustawienia z *game.project*: + +```bash +# Określ kolekcję bootstrapową +$ dmengine --config=bootstrap.main_collection=/my.collectionc + +# Ustaw dwie własne wartości konfiguracyjne +$ dmengine --config=test.my_value=4711 --config=test2.my_value2=foobar +``` + +Własne wartości można odczytywać tak samo jak każdą inną wartość konfiguracyjną, za pomocą [`sys.get_config_string()`](/ref/sys/#sys.get_config_string) albo [`sys.get_config_number()`](/ref/sys/#sys.get_config_number): + +```lua +local my_value = sys.get_config_number("test.my_value") +local my_value2 = sys.get_config_string("test.my_value2") +``` + +## Component max count optimizations + +Plik ustawień *game.project* zawiera wiele wartości określających maksymalną liczbę określonego zasobu, który może istnieć jednocześnie, najczęściej w przeliczeniu na załadowaną kolekcję, nazywaną też światem. Silnik Defold używa tych wartości maksymalnych do wstępnej alokacji pamięci, aby ograniczyć dynamiczne alokacje i fragmentację pamięci podczas działania gry. + +Struktury danych Defold używane do reprezentowania komponentów i innych zasobów są zoptymalizowane pod kątem jak najmniejszego zużycia pamięci, ale przy ustawianiu tych wartości nadal trzeba zachować ostrożność, aby nie przydzielać więcej pamięci, niż naprawdę potrzeba. + +Aby dodatkowo zoptymalizować zużycie pamięci, proces builda Defold analizuje zawartość gry i nadpisuje wartości maksymalne tam, gdzie można z całkowitą pewnością określić dokładną liczbę: + +* Jeśli kolekcja nie zawiera żadnych komponentów Factory, zostanie zaalokowana dokładna liczba każdego komponentu i obiektu gry, a wartości maksymalne zostaną zignorowane. +* Jeśli kolekcja zawiera komponent Factory, obiekty tworzone przez tę fabrykę zostaną przeanalizowane i dla komponentów możliwych do utworzenia przez Factory oraz dla obiektów gry zostaną użyte wartości max count. +* Jeśli kolekcja zawiera komponent Factory albo Collection factory z włączoną opcją `Dynamic Prototype`, ta kolekcja będzie używać liczników maksymalnych. + +## Custom project settings + +Można definiować własne ustawienia dla głównego projektu albo dla [native extension](/manuals/extensions/). Własne ustawienia dla głównego projektu należy zdefiniować w pliku `game.properties` w katalogu głównym projektu. W przypadku rozszerzenia natywnego należy je zdefiniować w pliku `ext.properties` obok pliku `ext.manifest`. + +Plik ustawień używa tego samego formatu INI co *game.project*, a atrybuty właściwości zapisuje się notacją z kropką i sufiksem: + +``` +[my_category] +my_property.private = 1 ... ``` -Przykład: +Domyślny plik meta, który jest zawsze stosowany, jest dostępny [tutaj](https://github.com/defold/defold/blob/dev/com.dynamo.cr/com.dynamo.cr.bob/src/com/dynamo/bob/meta.properties). + +Obecnie dostępne są następujące atrybuty: -```ini -[bootstrap] -main_collection = /main/main.collectionc ``` +[my_extension] +// `type` - używany przy parsowaniu łańcucha wartości +my_property.type = string // jedna z wartości: bool, string, number, integer, string_array, resource -co oznacza, że ustawienie *main_collection* należy do kategorii *bootstrap*. -Kiedy używana jest referencja do pliku, jak w powyższym przykładzie, ścieżka musi być zakończona znakiem 'c', co oznacza, że odnosisz się do skompilowanej wersji pliku. -Zauważ również, że folder zawieracjący plik *game.project* będzie folderem głównym projektu (root), stąd początkowy znak '/' w ścieżce do pliku. +// `help` - używany jako podpowiedź pomocy w edytorze (na razie nieużywany) +my_property.help = string -## Ustawianie wartości przy starcie silnika +// `default` - wartość domyślna używana, jeśli użytkownik nie ustawił wartości ręcznie +my_property.default = string -Kiedy silnik zostaje uruchomiony jest możliwe podanie wartości konfiguracji z lini wiersza poleceń, które nadpiszą wartości w pliku *game.project*: +// `private` - wartość prywatna używana podczas bundlowania, ale usuwana z samego bundla +my_property.private = 1 // wartość logiczna 1 albo 0 -```bash -# Określ kolekcę główną/bootstrapową -$ dmengine --config=bootstrap.main_collection=/my.collectionc +// `label` - etykieta pola w edytorze +my_property.label = My Awesome Property + +// `minimum` i/lub `maximum` - prawidłowy zakres dla właściwości liczbowych, walidowany w UI edytora +my_property.minimum = 0 +my_property.maximum = 255 + +// `options` - opcje listy rozwijanej w UI edytora, zapisane jako oddzielone przecinkami pary value[:label] +my_property.options = android: Android, ios: iOS -# Ustaw dwie wartości: -$ dmengine --config=test.my_value=4711 --config=test2.my_value2=1234 +// tylko dla typu `resource`: +my_property.filter = jpg,png // dozwolone rozszerzenia plików w selektorze zasobu +my_property.preserve-extension = 1 // użyj oryginalnego rozszerzenia zasobu zamiast rozszerzenia builda + +// oznaczanie jako przestarzałe +my_property.deprecated = 1 // oznacz właściwość jako przestarzałą +my_property.severity-default = warning // gdy przestarzała właściwość jest ustawiona, ale ma wartość domyślną +my_property.severity-override = error // gdy przestarzała właściwość jest ustawiona i ma wartość inną niż domyślna ``` -Twoje wartości mogą ---tak jak każde inne wartości konfiguracji--- być odczytane w trakcie działania aplikacji dzięki funkcji [`sys.get_config()`](/ref/sys/#sys.get_config): +Dodatkowo na kategorii ustawień można ustawić następujące atrybuty: -```lua -local my_value = tonumber(sys.get_config("test.my_value")) +``` +[my_extension] +// `group` - grupa kategorii w game.project, np. Main, Platforms, Components, Runtime, Distribution +group = Runtime +// `title` - wyświetlany tytuł kategorii +title = My Awesome Extension +// `help` - wyświetlana pomoc kategorii +help = Settings for My Awesome Extension ``` -## Vsync, frame cap, i swap interval -Po pierwsze na komputerach osobistych opcja `Vsync` (synchronizacja pionowa) może być kontrolowana globalnie przez ustawienia karty graficznej. Jeśli przykładowo opcja vsync jest wymuszona jako ustawiona w panelu kontrolnym karty graficznej, nie jest już możliwe zmienienie jej z poziomu użytkownika, czyli Defold nie może mieć do niej dostępu ani jej zmodyfikować. Większość urządzeń ma opcję vsync uruchomioną domyślnie. - -Kiedy opcja `Vsync` jest zaznaczona w pliku *game.project* silnik będzie polegał na sprzętowym wsparciu synchronizacji pionowej i używał stałej wartości długości ramki `dt` bazującej na wartości częstotliwości odświeżania monitora. Jest to domyślne ustawienie. Kiedy opcja `Vsync` jest zaznaczona, a `Frame cap` > 0, wartość długości będzie zmniejszona do interwału przejścia odpowiadającego częstotliwości odświeżania głównego wykrytego monitora. Kiedy opcja `Vsync` jest odznaczona, a `Frame cap` = 0, wartość długości ramki nie jest stała, tylko używa aktualnej przyblizonej wartości różnicy czasowej dla wartości `dt`. Kiedy opcja `Vsync` jest odznaczona, a `Frame cap` > 0, używane są timery, aby dostosować się do podanej wartości frame cap. Nie ma niestety gwarancji, że wartość frame cap zostanie osiągnięta na różnych platformach i w zależności od różnych ustawień sprzętowych. - -Interwał zmiany (Swap interval) jest przedziałem czasowym określającym kiedy zamienić przedni i tylni bufor podczas synchronizacji z pionowymi pustkami (vertical blanks - v-blank), sprzętowe wydarzenie, gdzie ekran jest aktualizowany danymi z przedniego bufora. Wartość 1 pozwala na zamianę buforów przy każdym v-blanku, wartość 2 zamienia bufory przy co drugim v-blanku itd. Wartość 0 wyłącza oczekiwanie na v-blank przed zamianą buforów\*. Ustawienie `swap_interval` można zmienić dzięki funkcji [```set_vsync_swap_interval```](/ref/sys/#sys.set_vsync_swap_interval:swap_interval). - -### Zastrzeżenie -Obecnie, Defold odpytuje o częstotliwość odświeżania monitora podczas inicjalizacji silnika i używa tej wartości jako bazy przy wyborze stałej wartości `dt`. Jeśli chcesz wspierać monitory ze zmienną wartością częstotliwości odświeżania (np. GSync albo FreeSync) lub w innych scenariuszach gdzie wartość częstotliwości odświeżania nie jest trywialna do ustalenia, odznacz opcję `Vsync`, żeby pozwolić silnikowi dobrać `dt` podczas każdej ramki, zamiast polegać na stałej wartości. - -### Vsync i frame cap w Defoldzie* - - - - - - - - - - - - - - - - - -
Frame cap 0 (default)Frame cap > 0
Vsync checked (default)Relies on hardware vsync. Fixed dt of 1/(detected monitor refresh rate).Fixed dt of (swap interval)/(detected monitor refresh rate) where swap interval is clamped to the closest matching monitor refresh rate frame cap multiple.
Vsync uncheckedCalculates dt each frame based on elapsed system time. Vsync might still be enabled in driver settings.Uses a fixed dt of 1 / (Frame cap). Uses timers and sleeps to respect the set frame cap.
+Obecnie właściwości meta są używane tylko w `bob.jar` podczas bundlowania aplikacji, ale w przyszłości będą też parsowane przez edytor i prezentowane w widoku *game.project*. diff --git a/docs/pl/manuals/script.md b/docs/pl/manuals/script.md index 8de3c5a6..e9525505 100644 --- a/docs/pl/manuals/script.md +++ b/docs/pl/manuals/script.md @@ -1,145 +1,155 @@ --- title: Pisanie logiki gry w skryptach -brief: Ta instrukcja opisuje szczegóły pisania logiki gry w komponentach typu skrypt. +brief: Ta instrukcja opisuje, jak dodawać logikę gry za pomocą komponentów Script. --- # Skrypty -Komponent typu skrypt (ang. script) pozwala na tworzenie logiki gry przy użyciu języka programowania Lua. Skrypty dodawane są do obiektów gry dokładnie tak samo jak każdy inny [komponent](/manuals/components), a Defold wykona kod Lua w ramach funkcji cyklu życia silnika. +Komponenty Script pozwalają tworzyć logikę gry przy użyciu [języka Lua](/manuals/lua). ## Typy skryptów -W Defoldzie występują trzy rodzaje skryptów Lua, z dostępem do różnych bibliotek Defolda. +W Defold występują trzy typy skryptów Lua. Każdy z nich ma dostęp do innego zestawu bibliotek Defold. -Skrypty logiczne (.script) -: Uruchamiane przez komponenty skryptu w obiektach gry. Skrypty logiczne są zazwyczaj używane do kontrolowania obiektów gry i logiki łączącej grę z ładowaniem poziomów, zasadami gry itp. Skrypty logiczne mają dostęp do wszystkich funkcji bibliotek Defold, z wyjątkiem funkcji [GUI](/ref/gui) i [Render](/ref/render). +Skrypty obiektów gry +: Rozszerzenie _.script_. Te skrypty dodaje się do obiektów gry dokładnie tak samo jak każdy inny [komponent](/manuals/components), a Defold wykonuje kod Lua w ramach funkcji cyklu życia silnika. Skrypty obiektów gry są zwykle używane do sterowania obiektami gry oraz logiką spajającą całą grę, taką jak ładowanie poziomów, reguły gry i podobne elementy. Skrypty obiektów gry mają dostęp do funkcji [GO](/ref/go) oraz do wszystkich bibliotek Defold poza [GUI](/ref/gui) i [Render](/ref/render). -Skrypty GUI (.gui_script) -: Uruchamiane przez komponenty GUI i zazwyczaj zawierają logikę wymaganą do wyświetlania elementów interfejsu użytkownika, takich jak wyświetlacze informacji, menu itp. Skrypty GUI mają dostęp do funkcji biblioteki [GUI](/ref/gui). +Skrypty GUI +: Rozszerzenie _.gui_script_. Są uruchamiane przez komponenty GUI i zwykle zawierają logikę potrzebną do wyświetlania elementów interfejsu, takich jak HUD-y, menu i podobne elementy. Defold wykonuje kod Lua w ramach funkcji cyklu życia silnika. Skrypty GUI mają dostęp do funkcji [GUI](/ref/gui) oraz do wszystkich bibliotek Defold poza [GO](/ref/go) i [Render](/ref/render). -Skrypty renderowania (.render_script) -: Uruchamiane przez potok renderowania (rendering pipeline) i zawierają logikę wymaganą do renderowania grafiki aplikacji/gry w każdej klatce. Skrypty renderowania mają dostęp do funkcji biblioteki [Render](/ref/render). +Skrypty renderowania +: Rozszerzenie _.render_script_. Są uruchamiane przez potok renderowania i zawierają logikę potrzebną do renderowania całej grafiki aplikacji lub gry w każdej klatce. Skrypt renderowania zajmuje szczególne miejsce w cyklu życia gry. Szczegóły znajdziesz w [dokumentacji cyklu życia aplikacji](/manuals/application-lifecycle). Skrypty renderowania mają dostęp do funkcji [Render](/ref/render) oraz do wszystkich bibliotek Defold poza [GO](/ref/go) i [GUI](/ref/gui). -## Wykonywanie skryptów, wywołania zwrotne i "self" +## Wykonywanie skryptów, callbacki i `self` -Defold wykonuje skrypty Lua jako część cyklu życia silnika i ujawnia cykl życia przez zestaw predefiniowanych funkcji wywołania zwrotnego. Gdy dodasz komponent skryptu do obiektu gry, skrypt staje się częścią cyklu życia obiektu gry i jego komponentu (lub komponentów). Skrypt jest oceniany w kontekście Lua, gdy jest wczytywany, a następnie silnik wykonuje następujące funkcje i przekazuje odniesienie do bieżącej instancji komponentu skryptu. Możesz użyć tego odniesienia "self" do przechowywania stanu w instancji komponentu. +Defold wykonuje skrypty Lua jako część cyklu życia silnika i udostępnia ten cykl przez zestaw predefiniowanych funkcji callback. Gdy dodasz komponent skryptu do obiektu gry, skrypt staje się częścią cyklu życia tego obiektu i jego komponentów. Skrypt jest interpretowany w kontekście Lua podczas wczytywania, a następnie silnik wywołuje poniższe funkcje, przekazując referencję do bieżącej instancji komponentu skryptu. Możesz używać tej referencji `self` do przechowywania stanu instancji komponentu. -::: ważne -"Self" to obiekt typu userdata, który działa jak tabela Lua, ale nie można go przeglądać za pomocą pairs() ani ipairs(), ani drukować za pomocą pprint(). +::: important +`self` jest obiektem userdata, który zachowuje się podobnie do tabeli Lua, ale nie można po nim iterować za pomocą `pairs()` ani `ipairs()` i nie można go wypisać przez `pprint()`. ::: -init(self) -: Wywoływane, gdy komponent jest inicjowany. +#### `init(self)` +Wywoływana podczas inicjalizacji komponentu. - ```lua - function init(self) - -- These variables are available through the lifetime of the component instance - self.my_var = "something" - self.age = 0 - end - ``` +```lua +function init(self) + -- Te zmienne są dostępne przez cały czas życia instancji komponentu + self.my_var = "something" + self.age = 0 +end +``` -final(self) -: Wywoływane, gdy komponent jest usuwany. Przydatne do celów sprzątania, na przykład, jeśli utworzyłeś obiekty gry, które powinny być usunięte, gdy komponent jest usuwany. +#### `final(self)` +Wywoływana podczas usuwania komponentu. Przydaje się do porządkowania zasobów, na przykład jeśli utworzono obiekty gry, które powinny zostać usunięte razem z komponentem. - ```lua - function final(self) - if self.my_var == "something" then - -- wykonaj jakiś kod - end +```lua +function final(self) + if self.my_var == "something" then + -- wykonaj czynności porządkowe end +end +``` -update(self, dt) -: Wywoływane raz w każdej klatce. dt zawiera czas delta od ostatniej klatki. +#### `fixed_update(self, dt)` +Aktualizacja niezależna od liczby klatek. Parametr `dt` zawiera czas, jaki upłynął od poprzedniej aktualizacji. Ta funkcja jest wywoływana `0-N` razy, zależnie od czasu trwania klatki i częstotliwości aktualizacji stałokrokowej. Jest wywoływana tylko wtedy, gdy w *game.project* włączone jest Physics ▸ Use Fixed Timestep, a Engine ▸ Fixed Update Frequency ma wartość większą od 0. Jest przydatna, gdy chcesz manipulować obiektami fizycznymi w regularnych odstępach, aby uzyskać stabilną symulację fizyki. - ```lua - function update(self, dt) - self.age = self.age + dt -- increase age with the timestep - end - ``` +```lua +function fixed_update(self, dt) + msg.post("#co", "apply_force", {force = vmath.vector3(1, 0, 0), position = go.get_world_position()}) +end +``` -fixed_update(self, dt) -: Aktualizacja niezależna od liczby klatek. dt zawiera czas delta od ostatniej aktualizacji. Ta funkcja jest wywoływana, gdy engine.fixed_update_frequency jest włączony (!= 0) i jest przydatna, gdy chcesz manipulować obiektami fizycznymi w regularnych odstępach czasu, aby uzyskać stabilną symulację fizyki, gdy physics.use_fixed_timestep jest włączone w *game.project*. +#### `update(self, dt)` +Wywoływana raz na każdą klatkę po callbacku `fixed_update` wszystkich skryptów, jeśli włączony jest Fixed Timestep. Parametr `dt` zawiera czas, jaki upłynął od poprzedniej klatki. - ```lua - function fixed_update(self, dt) - msg.post("#co", "apply_force", {force = vmath.vector3(1, 0, 0), position = go.get_world_position()}) - end - ``` +```lua +function update(self, dt) + self.age = self.age + dt -- zwiększ wiek o krok czasu +end +``` -on_message(self, message_id, message, sender) -: Gdy wiadomości są wysyłane do komponentu skryptu za pomocą msg.post(), silnik wywołuje tę funkcję komponentu odbiorczego. Dowiedz się więcej na temat przekazywania wiadomości. +#### `late_update(self, dt)` +Wywoływana raz na każdą klatkę po callbacku `update` wszystkich skryptów, ale tuż przed renderowaniem. Parametr `dt` zawiera czas, jaki upłynął od poprzedniej klatki. - ```lua - function on_message(self, message_id, message, sender) - if message_id == hash("increase_score") then - self.total_score = self.total_score + message.score - end - end +```lua +function late_update(self, dt) + go.set_position("/camera", self.final_camera_position) +end ``` -on_input(self, action_id, action) -: Jeśli ten komponent uzyskał fokus wejścia (zobacz acquire_input_focus), silnik wywołuje tę funkcję, gdy zostanie zarejestrowane wejście. Dowiedz się więcej na temat obsługi wejścia.' +#### `on_message(self, message_id, message, sender)` +Gdy wiadomości są wysyłane do komponentu skryptu przez [`msg.post()`](/ref/msg#msg.post), silnik wywołuje tę funkcję w komponencie odbiorcy. Więcej informacji znajdziesz w [instrukcji o przesyłaniu wiadomości](/manuals/message-passing). - ```lua - function on_input(self, action_id, action) - if action_id == hash("touch") and action.pressed then - print("Touch", action.x, action.y) - end - end - ``` +```lua +function on_message(self, message_id, message, sender) + if message_id == hash("increase_score") then + self.total_score = self.total_score + message.score + end +end +``` -on_reload(self) -: Ta funkcja jest wywoływana, gdy skrypt jest ponownie wczytywany za pomocą funkcji edytora "hot reload" (Edytuj ▸ Ponownie załaduj zasób). Jest bardzo przydatna do celów debugowania, testowania i dostrojenia. Dowiedz się więcej na temat ponownego ładowania na gorąco. +#### `on_input(self, action_id, action)` +Jeśli komponent przejął fokus wejścia, zobacz [`acquire_input_focus`](/ref/go/#acquire_input_focus), silnik wywołuje tę funkcję po zarejestrowaniu wejścia. Więcej informacji znajdziesz w [instrukcji o obsłudze wejścia](/manuals/input). - ```lua - function on_reload(self) - print(self.age) -- wyświetl wartość zmiennej self.age - end - ``` +```lua +function on_input(self, action_id, action) + if action_id == hash("touch") and action.pressed then + print("Touch", action.x, action.y) + end +end +``` + +#### `on_reload(self)` +Ta funkcja jest wywoływana, gdy skrypt zostaje przeładowany przez funkcję hot reload edytora (Edit ▸ Reload Resource). Jest bardzo przydatna podczas debugowania, testowania i strojenia. Więcej informacji znajdziesz w [instrukcji o szybkim przeładowaniu](/manuals/hot-reload). + +```lua +function on_reload(self) + print(self.age) -- wypisz wiek tego obiektu gry +end +``` ## Logika reaktywna -Obiekt gry z komponentem skryptu implementuje pewną logikę. Często zależy ona od pewnego czynnika zewnętrznego. Przykładowo sztuczna inteligencja przeciwnika może reagować na gracza znajdującego się w określonym promieniu od przeciwnika, drzwi mogą odblokować się i otworzyć w wyniku interakcji gracza itp. +Obiekt gry z komponentem skryptu implementuje pewną logikę. Często zależy ona od zewnętrznych czynników. Sztuczna inteligencja przeciwnika może reagować na gracza znajdującego się w określonym promieniu od niej, drzwi mogą się odblokować i otworzyć w wyniku interakcji gracza itd. -Funkcja `update()` pozwala na implementację złożonych zachowań zdefiniowanych jako automat stanów, który działa w każdej klatce - czasami jest to odpowiednie podejście. Jednak z każdym wywołaniem `update()` wiąże się pewien koszt. Jeśli naprawdę nie potrzebujesz tej funkcji, powinieneś ją usunąć i spróbować budować swoją logikę w sposób reaktywny. Oczekiwanie biernie na jakąś wiadomość, która wyzwoli reakcję, jest "tańsze" niż aktywne przeszukiwanie świata gry w poszukiwaniu danych do analizy. Ponadto rozwiązanie danego problemu w sposób reaktywny zazwyczaj prowadzi do czystszego i bardziej stabilnego projektu i jego implementacji. +Funkcja `update()` pozwala implementować złożone zachowania zdefiniowane jako automat stanów wykonywany w każdej klatce. Czasami jest to właściwe podejście. Każde wywołanie `update()` ma jednak swój koszt. Jeśli naprawdę nie potrzebujesz tej funkcji, usuń ją i spróbuj budować logikę w sposób _reaktywny_. Taniej jest biernie czekać na wiadomość, która wywoła reakcję, niż aktywnie sondować świat gry w poszukiwaniu danych do obsługi. Dodatkowo reaktywne rozwiązanie problemu projektowego często prowadzi do czytelniejszego i stabilniejszego projektu oraz implementacji. -Przyjrzyjmy się konkretnemu przykładowi. Załóżmy, że chcesz, aby komponent skryptu wysłał wiadomość 2 sekundy po inicjalizacji. Następnie powinien oczekiwać na określoną wiadomość odpowiedzi i po jej otrzymaniu, wysłać inną wiadomość 5 sekund później. Niereaktywny kod dla tego wyglądałby mniej więcej tak: +Spójrzmy na konkretny przykład. Załóżmy, że chcesz, aby komponent skryptu wysłał wiadomość 2 sekundy po inicjalizacji. Następnie powinien zaczekać na określoną wiadomość odpowiedzi i po jej otrzymaniu wysłać kolejną wiadomość 5 sekund później. Kod niereaktywny wyglądałby mniej więcej tak: ```lua function init(self) - -- Licznik czasu. + -- Licznik do śledzenia czasu self.counter = 0 - -- Potrzebujemy tego do śledzenia naszego stanu. + -- Potrzebujemy tego do śledzenia stanu self.state = "first" end function update(self, dt) self.counter = self.counter + dt if self.counter >= 2.0 and self.state == "first" then - -- wysłanie wiadomości po 2 sekundach + -- wyślij wiadomość po 2 sekundach msg.post("some_object", "some_message") self.state = "waiting" end if self.counter >= 5.0 and self.state == "second" then - -- wysłanie wiadomości 5 sekund po otrzymaniu "response" + -- wyślij wiadomość 5 sekund po otrzymaniu "response" msg.post("another_object", "another_message") - -- Wyczyszczenie stanu, aby nie wykonać tego bloku stanu ponownie. + -- Ustaw stan na nil, aby nie wejść w ten blok ponownie. self.state = nil end end function on_message(self, message_id, message, sender) if message_id == hash("response") then - -- Stan "pierwszy" zakończony, wchodzi kolejny + -- Zakończono stan "first", przejdź do następnego self.state = "second" - -- Wyzerowanie licznika + -- Wyzeruj licznik self.counter = 0 end end ``` -Even in this quite simple case we get fairly tangled up logic. It's possible to make this look better with the help of coroutines in a module (see below), but let's instead try to make this reactive and use a built-in timing mechanism. +Nawet w tak prostym przypadku logika dość szybko się komplikuje. Można ją uporządkować przy pomocy korutyn w module, zobacz niżej, ale spróbujmy zamiast tego podejścia reaktywnego i użyjmy wbudowanego mechanizmu odmierzania czasu. ```lua local function send_first() @@ -147,7 +157,7 @@ local function send_first() end function init(self) - -- Poczekaj 2 s, a następnie wywołaj send_first() + -- Poczekaj 2 s, a potem wywołaj send_first() timer.delay(2, false, send_first) end @@ -157,30 +167,31 @@ end function on_message(self, message_id, message, sender) if message_id == hash("response") then - -- Poczekaj 5 s, a następnie wywołaj send_second() + -- Poczekaj 5 s, a potem wywołaj send_second() timer.delay(5, false, send_second) end end ``` -To jest bardziej przejrzyste i łatwiejsze do śledzenia. Pozbywamy się wewnętrznych zmiennych stanu, które często są trudne do śledzenia przez logikę - i które mogą prowadzić do subtelnych błędów. Dodatkowo całkowicie rezygnujemy z funkcji `update()`. Zwalnia to silnik z wywoływania naszego skryptu 60 razy na sekundę. +To podejście jest czytelniejsze i łatwiejsze do śledzenia. Pozbywamy się wewnętrznych zmiennych stanu, które często trudno przeanalizować w toku logiki i które mogą prowadzić do subtelnych błędów. Dodatkowo całkowicie usuwamy funkcję `update()`. Dzięki temu silnik nie musi wywoływać naszego skryptu 60 razy na sekundę, nawet jeśli nic się w nim nie dzieje. ## Preprocessing -Przetwarzanie wstępne, czyli preprocessing wykrozystuje preprocesor Lua i specjalne znaczniki, aby warunkowo dołączać kod w zależności od wariantu budowy. Przykład: + +Można używać preprocesora Lua i specjalnych znaczników, aby warunkowo dołączać kod zależnie od wariantu builda. Przykład: ```lua --- Użyj jednego z tych słów kluczowych: RELEASE, DEBUG lub HEADLESS +-- Użyj jednego z następujących słów kluczowych: RELEASE, DEBUG lub HEADLESS --#IF DEBUG local lives_num = 999 ---#ELSE +--#ELSE local lives_num = 3 --#ENDIF ``` -Preprocesor jest dostępny jako rozszerzenie budowania. Dowiedz się więcej na temat sposobu instalacji i użycia na [stronie rozszerzenia na GitHubie](https://github.com/defold/extension-lua-preprocessor). +Preprocesor jest dostępny jako rozszerzenie builda. Więcej informacji o instalacji i użyciu znajdziesz na [stronie rozszerzenia w GitHub](https://github.com/defold/extension-lua-preprocessor). -## Wsparcie Edytora +## Wsparcie edytora -Edytor Defold obsługuje edycję skryptów Lua z kolorowaniem składni i autouzupełnianiem. Aby wyświetlić nazwy funkcji Defold, naciśnij Ctrl+Spacja, aby wyświetlić listę funkcji pasujących do tego, co wpisujesz. +Edytor Defold obsługuje edycję skryptów Lua z kolorowaniem składni i autouzupełnianiem. Aby uzupełnić nazwy funkcji Defold, naciśnij Ctrl+Space, by wyświetlić listę funkcji pasujących do wpisywanego tekstu. -![Automatyczne uzupełnianie](images/script/completion.png) +![Auto completion](images/script/completion.png) diff --git a/docs/pl/manuals/sprite.md b/docs/pl/manuals/sprite.md index 1dcda973..d698a8e9 100644 --- a/docs/pl/manuals/sprite.md +++ b/docs/pl/manuals/sprite.md @@ -1,89 +1,129 @@ --- -title: Sprite - reprezentacja graficzna 2D -brief: Instrukcja ta opisuje jak pokazywać dwuwymiarowe grafiki używając komponentu typu Sprite. +title: Wyświetlanie obrazów 2D +brief: Ta instrukcja opisuje, jak wyświetlać obrazy 2D i animacje przy użyciu komponentu Sprite. --- -# Sprite +# Sprite -Komponent typu Sprite (z ang. dosłownie: chochlik/duszek/krasnoludek - popularna w gamedevie od lat nazwa obrazków 2D w grach - przyp.tłum.) to dwuwymiarowa reprezentacja wizualna w grafice komputerowej wyświetlana jako pojedynczy obrazek lub animacja poklatkowa (flipbook animation). +Komponent Sprite to prosty obraz lub animacja poklatkowa (flipbook), która jest wyświetlana na ekranie. ![sprite](images/graphics/sprite.png) -Komponent typu Sprite może wykorzystywać jako teksturę galerię obrazów, tzw. [Atlas](/manuals/atlas) lub [Źródło kafelków - Tile Source](/manuals/tilesource). +Komponent Sprite może korzystać jako źródła grafiki z [Atlasu](/manuals/atlas) albo [Tile source (Źródła kafelków)](/manuals/tilesource). -## Właściwości Sprite'ów +## Właściwości komponentu Sprite -Poza właściwościami takimi jak *Id*, *Position* i *Rotation* komponenty te posiadają swoje specyficzne właściwości (properties): +Poza właściwościami *Id*, *Position* i *Rotation* komponent ma następujące właściwości specyficzne dla Sprite: *Image* -: Obraz/tekstura dwuwymiarowa - może nią być Galeria - `Atlas` lub Źródło kafelków - `Tile Source`. +: Jeśli shader ma pojedynczy sampler, to pole nosi nazwę `Image`. W przeciwnym razie każde pole jest nazwane zgodnie z samplerem tekstury w materiale. Każde pole określa zasób atlasu albo źródła kafelków używany przez sprite na danym samplerze tekstury. *Default Animation* -: Domyślna animacja używana przy wyświetlaniu obrazu. +: Animacja używana przez sprite. Informacje o animacji są pobierane z pierwszego atlasu albo źródła kafelków. *Material* -: Materiał służący do renderowania. +: Materiał używany do renderowania sprite'a. *Blend Mode* -: Tryb "mieszania"/blendowania używany również przy renderowaniu. Więcej szczegółów poniżej. +: Tryb mieszania używany podczas renderowania sprite'a. *Size Mode* -: Tryb rozmiaru - jeśli ustawiony na `Automatic`, to Edytor będzie ustawiał rozmiar sprite'a. Jeśli ustawiony na `Manual`, to możesz dopasować rozmiar sprite'a. +: Jeśli ustawisz `Automatic`, edytor sam ustawi rozmiar sprite'a. Jeśli ustawisz `Manual`, możesz ustawić rozmiar ręcznie. *Slice 9* -: Przekrój na 9 części - ustaw tę właściwość aby zachować prawidłowość pikseli na rogach sprite'a, kiedy jego rozmiar jest zmieniany. +: Ustaw tę opcję, aby zachować rozmiar pikseli tekstury przy krawędziach sprite'a podczas zmiany jego rozmiaru. -:[Więcej o funkcjonalności Slice-9 tutaj.](../shared/slice-9-texturing.md) +:[Slice-9](../shared/slice-9-texturing.md) -### Blend modes - tryby blendowania +### Tryby mieszania :[blend-modes](../shared/blend-modes.md) -## Manipulacja w trakcie działania programu +## Manipulacja w czasie działania -Możesz manipulować właściwościami Sprite'ów w trakcie działania programu dzięki wielu funkcjom i zmiennym właściwościom (szukaj przykładów użycia w [API](/ref/sprite/)). Funkcje: +Możesz modyfikować sprite'y w czasie działania za pomocą różnych funkcji i właściwości. Sposób użycia znajdziesz w [dokumentacji API](/ref/sprite/). Funkcje: -* `sprite.play_flipbook()` - Odtwarzaj animację sprite'a. -* `sprite.set_hflip()` and `sprite.set_vflip()` - Odwróć w pionie lub poziomie animację/obraz sprite'a. +* `sprite.play_flipbook()` - Odtwarza animację na komponencie Sprite. +* `sprite.set_hflip()` i `sprite.set_vflip()` - Ustawiają poziome i pionowe odbicie animacji sprite'a. -Sprite posiada również różne właściwości, którymi można manipulować przy użyciu funkcji `go.get()` i `go.set()`: +Sprite ma też kilka właściwości, którymi można manipulować przy użyciu `go.get()` i `go.set()`: `cursor` -: Znormalizowany (czyli w przedziale 0-1) kursor animacji, czyli wskaźnik na klatki danej animacji poklatkowej (liczba - `number`). +: Znormalizowany kursor animacji (`number`). `image` -: Obraz sprite'a (`hash`). Możesz użyć tej właściwości do podmiany tekstury sprite'a na inną galerią lub źródło kafelków, które mogą być właściwościami zasobu (resource property) i ustawić używając `go.set()`. Sprawdź szczegóły i przykłady w [API](/ref/sprite/#image). +: Obraz sprite'a (`hash`). Możesz go zmienić za pomocą właściwości zasobu wskazującej atlas albo źródło kafelków i funkcji `go.set()`. Przykład znajdziesz w [referencji API](/ref/sprite/#image). `material` -: Materiał sprite'a (`hash`). Możesz podmienić materiał korzystając z właściwości zasobu (resource property) i ustawić używając `go.set()`. Sprawdź szczegóły i przykłady w [API](/ref/sprite/#material). +: Materiał sprite'a (`hash`). Możesz go zmienić za pomocą właściwości zasobu materiału i funkcji `go.set()`. Przykład znajdziesz w [referencji API](/ref/sprite/#material). `playback_rate` -: Wskaźnik odtwarzania animacji, czyli prędkość z jaką odtwarzana jest animacja (`number`). +: Tempo odtwarzania animacji (`number`). `scale` -: Skala obrazka (wektor - `vector3`). +: Niejednorodna skala sprite'a (`vector3`). `size` -: Rozmiar obrazka (`vector3`) (Wartość tylko do odczytu - pokazuje rozmiar tekstury). +: Rozmiar sprite'a (`vector3`). Tę właściwość można zmienić tylko wtedy, gdy tryb rozmiaru sprite'a jest ustawiony na ręczny. ## Stałe materiału {% include shared/material-constants.md component='sprite' variable='tint' %} `tint` -: Kolor zabarwienia/odcienia obrazka (`vector4`). Wektor czterech komponentów reprezentuje zabarwienie, gdzie komponenty x, y, z, w odpowiadają składowym: czerwony, zielony, niebieski i przezroczystość (red, green, blue, alpha). +: Odcień koloru sprite'a (`vector4`). `vector4` reprezentuje zabarwienie, gdzie składowe x, y, z i w odpowiadają kolejno kanałom czerwieni, zieleni, błękitu i alfa. ## Atrybuty materiału -Sprite może nadpisywać atrybuty wierzchołków (vertex attributes) aktualnie przypisanego materiały i przekazywać je do shadera wierzchołków (vertex shader) z komponentu (szczegóły znajdziesz w [instrukcji do materiałów](/manuals/material/#attributes)). +Sprite może nadpisywać atrybuty wierzchołków z aktualnie przypisanego materiału. Zostaną one przekazane z komponentu do vertex shadera. Więcej informacji znajdziesz w [instrukcji do materiałów](/manuals/material/#attributes). -Atrybuty określone w materiale pokażą się jako zwykłe właściwości w widoku inspekcyjnym i mogą być ustawione na indywidualne komponenty sprite. Jeśli jakikolwiek atrybut jest nadpisany, zostanie on zaznaczony jako nadpisana właściwość i przechowana w pliku komponenty sprite na dysku. +Atrybuty określone w materiale pojawią się w inspectorze jako zwykłe właściwości i można je ustawiać osobno dla każdego komponentu Sprite. Jeśli którykolwiek atrybut zostanie nadpisany, będzie widoczny jako nadpisana właściwość i zostanie zapisany w pliku sprite'a na dysku: ![sprite-attributes](../images/graphics/sprite-attributes.png) -::: sidenote -Niestandardowe atrybuty są dostępne od wersji Defold 1.4.8! -::: - ## Konfiguracja projektu -Plik *game.project* zawiera [te ustawienia](/manuals/project-settings#sprite) dotyczące sprite'ów. +Plik *game.project* zawiera kilka [ustawień projektu](/manuals/project-settings#sprite) związanych ze sprite'ami. + +## Sprite'y z wieloma teksturami + +Gdy sprite korzysta z wielu tekstur, warto pamiętać o kilku rzeczach. + +### Animacje + +Dane animacji, takie jak fps i nazwy klatek, są obecnie pobierane z pierwszej tekstury. Nazwijmy ją „animacją sterującą”. + +Id obrazów z animacji sterującej są używane do wyszukiwania obrazów w kolejnej teksturze. Dlatego ważne jest, aby id klatek były zgodne pomiędzy teksturami. + +Na przykład, jeśli `diffuse.atlas` ma animację `run` w takiej postaci: + +``` +run: + /main/images/hero_run_color_1.png + /main/images/hero_run_color_2.png + ... +``` + +to id klatek będą wyglądały tak: `run/hero_run_color_1`. Taki identyfikator prawdopodobnie nie zostanie znaleziony na przykład w `normal.atlas`: + +``` +run: + /main/images/hero_run_normal_1.png + /main/images/hero_run_normal_2.png + ... +``` + +Dlatego używamy `Rename patterns` w [instrukcji do atlasów](/manuals/atlas/), aby zmienić te nazwy. Ustaw `_color=` i `_normal=` w odpowiednich atlasach, a w obu atlasach otrzymasz nazwy klatek w tej postaci: + +``` +run/hero_run_1 +run/hero_run_2 +... +``` + +### UVs + +Współrzędne UV są pobierane z pierwszej tekstury. Ponieważ istnieje tylko jeden zestaw wierzchołków, nie da się zagwarantować dobrego dopasowania, jeśli dodatkowe tekstury mają więcej współrzędnych UV albo inny kształt. + +Warto o tym pamiętać i zadbać, aby obrazy miały wystarczająco podobne kształty, bo w przeciwnym razie może pojawić się bleeding tekstur. + +Wymiary obrazów w poszczególnych teksturach mogą się różnić. From c5ff54ff1684be7a0e9fec037621811dc255c5e5 Mon Sep 17 00:00:00 2001 From: AGulev Date: Fri, 13 Mar 2026 13:22:00 +0100 Subject: [PATCH 3/3] tiny fixes --- docs/pl/manuals/collection-factory.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pl/manuals/collection-factory.md b/docs/pl/manuals/collection-factory.md index bc1f9cbd..99e76012 100644 --- a/docs/pl/manuals/collection-factory.md +++ b/docs/pl/manuals/collection-factory.md @@ -3,7 +3,7 @@ title: Fabryki kolekcji brief: Ta instrukcja wyjaśnia, jak używać komponentów Collection factory do tworzenia hierarchii obiektów gry. --- -# Fabryki kolekcji +# Fabryki kolekcji (Collection factory) Komponent Collection factory służy do tworzenia grup i hierarchii obiektów gry zapisanych w plikach kolekcji w działającej grze.