This translation is community contributed and may not be up to date. We only maintain the English version of the documentation. Read this manual in English
Jeśli potrzebujesz niestandardowej integracji z zewnętrznym oprogramowaniem lub sprzętem na niskim poziomie, gdzie Lua nie wystarcza, Defold SDK pozwala pisać rozszerzenia do silnika w C, C++, Objective-C, Java lub JavaScript, zależnie od platformy docelowej. Typowe zastosowania natywnych rozszerzeń to:
Defold udostępnia gotowy punkt startowy do pracy z natywnymi rozszerzeniami dzięki chmurowemu rozwiązaniu do budowania. Każde natywne rozszerzenie, które zostanie dodane do projektu gry, bezpośrednio lub przez Library Project, staje się częścią zwykłej zawartości projektu. Nie ma potrzeby budowania specjalnych wersji silnika i rozsyłania ich do członków zespołu. Robi się to automatycznie - każdy członek zespołu, który zbuduje i uruchomi projekt, otrzyma plik wykonywalny silnika specyficzny dla projektu, z wszystkimi natywnymi rozszerzeniami wbudowanymi na stałe.

Defold udostępnia serwer budowania w chmurze bezpłatnie i bez żadnych ograniczeń użycia. Serwer jest hostowany w Europie, a URL, pod który wysyłany jest kod natywny, konfiguruje się w oknie Editor Preferences albo przez opcję wiersza poleceń --build-server narzędzia bob. Jeśli chcesz uruchomić własny serwer, postępuj zgodnie z tymi instrukcjami.
Aby utworzyć nowe rozszerzenie, utwórz folder w katalogu głównym projektu. Ten folder będzie zawierał wszystkie ustawienia, kod źródłowy, biblioteki i zasoby związane z rozszerzeniem. Serwer budowania rozpoznaje strukturę folderów i zbiera wszystkie pliki źródłowe oraz biblioteki.
myextension/
│
├── ext.manifest
│
├── src/
│
├── include/
│
├── lib/
│ └──[platforms]
│
├── manifests/
│ └──[platforms]
│
└── res/
└──[platforms]
platform albo architecture-platform, zależnie od tego, jakie architektury są obsługiwane przez twoje biblioteki.
Obsługiwane platformy to ios, android, osx, win32, linux, web.
Obsługiwane pary arc-platform to arm64-ios, x86_64-ios, armv7-android, arm64-android, arm64-osx, x86_64-osx, x86-win32, x86_64-win32, arm64-linux, x86_64-linux, js-web, wasm-web oraz wasm_pthread-web.
platform albo architecture-platform, tak samo jak podfoldery w “lib”. Dozwolony jest też podfolder common, zawierający pliki zasobów wspólne dla wszystkich platform.Opcjonalny folder manifests rozszerzenia zawiera dodatkowe pliki używane podczas procesu budowania i pakowania. Pliki należy umieszczać w podfolderach nazwanych według platform:
android - Ten folder przyjmuje plik-szablon manifestu, który zostanie scalony z główną aplikacją (jak opisano tutaj).
build.gradle z zależnościami, które mają być rozwiązywane przez Gradle.ios - Ten folder przyjmuje plik-szablon manifestu, który zostanie scalony z główną aplikacją (jak opisano tutaj).
Podfile z zależnościami, które mają być rozwiązywane przez CocoaPods.osx - Ten folder przyjmuje plik-szablon manifestu, który zostanie scalony z główną aplikacją (jak opisano tutaj).web - Ten folder przyjmuje plik-szablon manifestu, który zostanie scalony z główną aplikacją (jak opisano tutaj).Rozszerzenia są traktowane tak samo jak inne zasoby w projekcie i można je udostępniać w ten sam sposób. Jeśli folder natywnego rozszerzenia zostanie dodany jako folder biblioteki, można go udostępniać i używać jako zależności projektu. Więcej informacji znajdziesz w instrukcji o bibliotekach.
Zbudujmy bardzo proste rozszerzenie. Najpierw tworzymy nowy folder główny myextension i dodajemy plik ext.manifest zawierający nazwę rozszerzenia MyExtension. Zwróć uwagę, że ta nazwa jest symbolem C++ i musi odpowiadać pierwszemu argumentowi DM_DECLARE_EXTENSION (patrz niżej).

# Symbol C++ w twoim rozszerzeniu
name: "MyExtension"
Rozszerzenie składa się z jednego pliku C++, myextension.cpp, który tworzymy w folderze src.

Plik źródłowy rozszerzenia zawiera następujący kod:
// myextension.cpp
// Definicje biblioteki rozszerzenia
#define LIB_NAME "MyExtension"
#define MODULE_NAME "myextension"
// dołącz Defold SDK
#include <dmsdk/sdk.h>
static int Reverse(lua_State* L)
{
// Oczekiwana liczba elementów na stosie Lua
// po wyjściu tej struktury z zakresu
DM_LUA_STACK_CHECK(L, 1);
// Sprawdź i pobierz parametr tekstowy ze stosu
char* str = (char*)luaL_checkstring(L, 1);
// Odwróć łańcuch znaków
int len = strlen(str);
for(int i = 0; i < len / 2; i++) {
const char a = str[i];
const char b = str[len - i - 1];
str[i] = b;
str[len - i - 1] = a;
}
// Umieść odwrócony łańcuch na stosie
lua_pushstring(L, str);
// Zwróć 1 element
return 1;
}
// Funkcje udostępnione do Lua
static const luaL_reg Module_methods[] =
{
{"reverse", Reverse},
{0, 0}
};
static void LuaInit(lua_State* L)
{
int top = lua_gettop(L);
// Zarejestruj nazwy w Lua
luaL_register(L, MODULE_NAME, Module_methods);
lua_pop(L, 1);
assert(top == lua_gettop(L));
}
dmExtension::Result AppInitializeMyExtension(dmExtension::AppParams* params)
{
return dmExtension::RESULT_OK;
}
dmExtension::Result InitializeMyExtension(dmExtension::Params* params)
{
// Zainicjalizuj Lua
LuaInit(params->m_L);
printf("Registered %s Extension\n", MODULE_NAME);
return dmExtension::RESULT_OK;
}
dmExtension::Result AppFinalizeMyExtension(dmExtension::AppParams* params)
{
return dmExtension::RESULT_OK;
}
dmExtension::Result FinalizeMyExtension(dmExtension::Params* params)
{
return dmExtension::RESULT_OK;
}
// Defold SDK używa makra do ustawiania punktów wejścia rozszerzenia:
//
// DM_DECLARE_EXTENSION(symbol, name, app_init, app_final, init, update, on_event, final)
// MyExtension to symbol C++, który przechowuje wszystkie istotne dane rozszerzenia.
// Musi odpowiadać polu name w `ext.manifest`
DM_DECLARE_EXTENSION(MyExtension, LIB_NAME, AppInitializeMyExtension, AppFinalizeMyExtension, InitializeMyExtension, 0, 0, FinalizeMyExtension)
Zwróć uwagę na makro DM_DECLARE_EXTENSION, które służy do deklarowania różnych punktów wejścia do kodu rozszerzenia. Pierwszy argument symbol musi odpowiadać nazwie podanej w ext.manifest. W tym prostym przykładzie nie ma potrzeby definiować żadnych punktów wejścia “update” ani “on_event”, więc w tych miejscach do makra przekazano 0.
Teraz wystarczy zbudować projekt (Project ▸ Build). Spowoduje to wysłanie rozszerzenia do serwera budowania, który wygeneruje własny silnik z nowym rozszerzeniem wbudowanym na stałe. Jeśli serwer budowania napotka jakiekolwiek błędy, pojawi się okno dialogowe z błędami budowania.
Aby przetestować rozszerzenie, utwórz obiekt gry i dodaj do niego komponent skryptu z krótkim kodem testowym:
local s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
local reverse_s = myextension.reverse(s)
print(reverse_s) --> ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba
I to wszystko! Utworzyliśmy w pełni działające natywne rozszerzenie.
Jak widzieliśmy wyżej, makro DM_DECLARE_EXTENSION służy do deklarowania różnych punktów wejścia do kodu rozszerzenia:
DM_DECLARE_EXTENSION(symbol, name, app_init, app_final, init, update, on_event, final)
Punkty wejścia pozwalają uruchamiać kod w różnych momentach cyklu życia rozszerzenia:
app_initinit - wszystkie API Defold są już zainicjalizowane. To zalecany moment w cyklu życia rozszerzenia na utworzenie wiązań Lua do kodu rozszerzenia.init() plików skryptów.updateupdate() plików skryptów.on_eventfinal() plików skryptów.finalapp_finalNastępujące identyfikatory są definiowane przez serwer budowania dla każdej odpowiedniej platformy:
DM_PLATFORM_WINDOWSDM_PLATFORM_OSXDM_PLATFORM_IOSDM_PLATFORM_ANDROIDDM_PLATFORM_LINUXDM_PLATFORM_HTML5Dzienniki serwera budowania są dostępne, gdy projekt korzysta z natywnych rozszerzeń. Dziennik serwera budowania (log.txt) jest pobierany razem z własnym silnikiem podczas budowania projektu, przechowywany w pliku .internal/%platform%/build.zip i rozpakowywany także do folderu budowania projektu.
Portal zasobów Defold także zawiera kilka natywnych rozszerzeń.