Erste Schritte mit GameActivity Teil des Android Game Development Kit.
In diesem Leitfaden wird die Einrichtung und Integration
GameActivity
und Ereignisse auf Ihrem Android-Gerät verwalten
Spiel.
Mit GameActivity
können Sie Ihre C- oder
C++-Spiele in Android durch die Vereinfachung der Verwendung wichtiger APIs
Bisher wurde NativeActivity
empfohlenen Kurs für Spiele. GameActivity
ersetzt es als empfohlene
und ist abwärtskompatibel mit API-Level 19.
Ein Beispiel mit GameActivity-Einbindung finden Sie in der Repository für Spielebeispiele.
Vorbereitung
Siehe GameActivity
-Releases für
um eine Verteilung zu erhalten.
Build einrichten
Unter Android dient ein Activity
als Eintrag
für Ihr Spiel und bietet Ihnen
Window
, um darin zu zeichnen. Viele Spiele erweitern
Activity
mit ihrer eigenen Java- oder Kotlin-Klasse, um Einschränkungen in
NativeActivity
, während mit JNI
-Code eine Bridge verwendet wird
in ihren C- oder C++-Spielcode ein.
GameActivity
bietet folgende Funktionen:
Übernimmt von
AppCompatActivity
, Sie können damit Android Jetpack Architecture Komponenten:Wird in ein
SurfaceView
, mit dem Sie mit anderen Android-UI-Elementen verknüpft.Verarbeitet Java-Aktivitätsereignisse. Dadurch kann jedes Android-UI-Element (z. B. ein
EditText
,WebView
oder einAd
) wird über eine C-Schnittstelle in dein Spiel integriert.Bietet ein ähnliches C-API wie
NativeActivity
undandroid_native_app_glue
Bibliothek.
GameActivity
wird als Android Archive vertrieben.
automatisch angewendete Empfehlungen. Dieses AAR enthält die Java-Klasse,
die Sie in Ihrem
AndroidManifest.xml
sowie das C
und C++ Quellcode, der die Java-Seite von GameActivity
mit der
Implementierung in C/C++. Wenn Sie GameActivity
1.2.2 oder höher verwenden, wird die C/C++-
statische Bibliothek zur Verfügung. Wir empfehlen, wenn möglich,
die statische Bibliothek anstelle
des Quellcodes verwenden.
Fügen Sie diese Quelldateien oder die statische Bibliothek als Teil Ihres
während des gesamten Prozesses
Prefab
,
der native Bibliotheken und Quellcode für Ihre
CMake-Projekt oder NDK-Build
Folgen Sie der Anleitung auf der Jetpack Android Games (Jetpack-Android-Spiele)
GameActivity
-Bibliotheksabhängigkeit zurbuild.gradle
-Datei deines Spiels.Aktivieren Sie Prefab, indem Sie Folgendes mit Android-Plug-in-Version (AGP) ab 4.1:
- Fügen Sie Folgendes in den Block
android
der Dateibuild.gradle
Ihres Moduls ein:
buildFeatures { prefab true }
- Wählen Sie eine Vorabversion aus.
und legen Sie dafür die Datei
gradle.properties
fest:
android.prefabVersion=2.0.0
Wenn Sie frühere AGP-Versionen verwenden, Prefab-Dokumentation finden Sie die entsprechende Konfigurationsanleitung.
- Fügen Sie Folgendes in den Block
Importieren Sie entweder die statische C/C++-Bibliothek oder den C/++-Quellcode in Ihr wie im Folgenden beschrieben.
Static-Bibliothek
Importieren Sie das statische
game-activity
-Objekt in die DateiCMakeLists.txt
Ihres Projekts. in dasgame-activity_static
-Fertigmodul:find_package(game-activity REQUIRED CONFIG) target_link_libraries(${PROJECT_NAME} PUBLIC log android game-activity::game-activity_static)
Quellcode
Importieren Sie den
game-activity
in die DateiCMakeLists.txt
Ihres Projekts. Paket und fügen es Ihrem Ziel hinzu. Dasgame-activity
-Paket benötigtlibandroid.so
. Fehlt sie, müssen Sie sie auch importieren.find_package(game-activity REQUIRED CONFIG) ... target_link_libraries(... android game-activity::game-activity)
Fügen Sie außerdem die folgenden Dateien in die
CmakeLists.txt
Ihres Projekts ein:GameActivity.cpp
,GameTextInput.cpp
undandroid_native_app_glue.c
.
So startet Android Ihre Aktivitäten
Das Android-System führt durch Aufrufen eines Callbacks Code in Ihrer Activity-Instanz aus die bestimmten Phasen des Aktivitätslebenszyklus entsprechen. Um Damit Android deine Aktivität starten und dein Spiel starten kann, musst du mit den entsprechenden Attributen im Android-Manifest. Weitere Informationen finden Sie unter Einführung in Aktivitäten.
Android-Manifest
Jedes App-Projekt muss einen AndroidManifest.xml-Datei unter Stamm des Quellsatzes des Projekts. In der Manifestdatei werden wichtige Informationen zu Ihrer App an die Android-Build-Tools, das Android-Betriebssystem und Google Play. Sie beinhalten die folgenden Funktionen:
Paketname und App-ID zur eindeutigen Identifizierung deines Spiels bei Google Play.
App-Komponenten wie Aktivitäten, Dienste, Übertragungsempfänger und Contentanbietern.
Berechtigungen für den Zugriff geschützte Teile des Systems oder anderer Apps.
Gerätekompatibilität um Hardware- und Softwareanforderungen für dein Spiel festzulegen.
Name der nativen Bibliothek für
GameActivity
undNativeActivity
(Standardwert ist libmain.so).
GameActivity im Spiel implementieren
Erstellen oder identifizieren Sie Ihre Java-Klasse für die Hauptaktivität (die im
activity
-Element in der DateiAndroidManifest.xml
). Diesen Kurs ändern in Erweitern SieGameActivity
aus demcom.google.androidgamesdk
-Paket:import com.google.androidgamesdk.GameActivity; public class YourGameActivity extends GameActivity { ... }
Sorgen Sie dafür, dass Ihre native Bibliothek von vornherein mit einem statischen Block geladen wird:
public class EndlessTunnelActivity extends GameActivity { static { // Load the native library. // The name "android-game" depends on your CMake configuration, must be // consistent here and inside AndroidManifect.xml System.loadLibrary("android-game"); } ... }
Native Bibliothek zu
AndroidManifest.xml
hinzufügen Wenn der Name der Bibliothek nicht der Standardname (libmain.so
) ist:<meta-data android:name="android.app.lib_name" android:value="android-game" />
android_main implementieren
Die
android_native_app_glue
-Bibliothek ist eine Quellcodebibliothek, die von Ihrem in dem SpielGameActivity
Lifecycle-Events in einem separaten Thread in um eine Blockierung in Ihrem Hauptthread zu verhindern. Wenn Sie die Bibliothek verwenden, registrierst du den Callback für die Verarbeitung von Lebenszyklus-Ereignissen wie Berührungseingaben. Ereignisse. DasGameActivity
-Archiv enthält eine eigene Version desandroid_native_app_glue
-Bibliothek, daher können Sie die Version aus NDK-Releases Wenn deine Spiele dieandroid_native_app_glue
-Mediathek verwenden die im NDK enthalten ist, wechseln Sie zurGameActivity
-Version.Nachdem Sie den Quellcode der
android_native_app_glue
-Bibliothek zu Ihrem verknüpft ist, besteht die Verbindung zuGameActivity
. Implementieren Sie eine Funktion namensandroid_main
, das vom und als Einstiegspunkt für dein Spiel verwendet. Es wird ein Struktur namensandroid_app
. Das kann je nach Spiel und Engine unterschiedlich sein. Beispiel:#include <game-activity/native_app_glue/android_native_app_glue.h> extern "C" { void android_main(struct android_app* state); }; void android_main(struct android_app* app) { NativeEngine *engine = new NativeEngine(app); engine->GameLoop(); delete engine; }
android_app
in deiner Hauptspielschleife verarbeiten, z. B. Abfragen und Verarbeitung in NativeAppGlueAppCmd definierte App-Zyklusereignisse. Mit dem folgenden Snippet wird beispielsweise die Funktion_hand_cmd_proxy
alsNativeAppGlueAppCmd
-Handler, fragt dann App-Zyklusereignisse ab und sendet sie an den registrierter Handler(inandroid_app::onAppCmd
) für die Verarbeitung:void NativeEngine::GameLoop() { mApp->userData = this; mApp->onAppCmd = _handle_cmd_proxy; // register your command handler. mApp->textInputState = 0; while (1) { int events; struct android_poll_source* source; // If not animating, block until we get an event; // If animating, don't block. while ((ALooper_pollAll(IsAnimating() ? 0 : -1, NULL, &events, (void **) &source)) >= 0) { if (source != NULL) { // process events, native_app_glue internally sends the outstanding // application lifecycle events to mApp->onAppCmd. source->process(source->app, source); } if (mApp->destroyRequested) { return; } } if (IsAnimating()) { DoFrame(); } } }
Untersuchen Sie für weitere Informationen die Implementierung des Endless Tunnels. NDK-Beispiel. Der Hauptunterschied besteht darin, wie Ereignisse verarbeitet werden, wie in im nächsten Abschnitt.
Ereignisse verarbeiten
Erstelle und registriere dein Ereignis, damit Eingabeereignisse deine App erreichen können
Filter mit android_app_set_motion_event_filter
und android_app_set_key_event_filter
.
Standardmäßig erlaubt die native_app_glue
-Mediathek nur Bewegungsereignisse von
QUELL-TOUCHSCREEN
Eingabe. Sieh dir auch die Referenzdokumentation an.
und den Implementierungscode android_native_app_glue
für die Details.
Um Eingabeereignisse zu verarbeiten, rufen Sie einen Verweis auf android_input_buffer
ab mit
android_app_swap_input_buffers()
in Ihrer Spielschleife. Dazu gehören Bewegungsereignisse und Schlüsselereignisse, die seit der letzten Ausführung dieser Aktion aufgetreten sind.
. Die Anzahl der enthaltenen Ereignisse wird in motionEventsCount
gespeichert.
keyEventsCount
.
Iteriere und bearbeite jedes Ereignis in deiner Spielschleife. In diesem Beispiel hat der Parameter Der folgende Code iteriert
motionEvents
und verarbeitet sie überhandle_event
:android_input_buffer* inputBuffer = android_app_swap_input_buffers(app); if (inputBuffer && inputBuffer->motionEventsCount) { for (uint64_t i = 0; i < inputBuffer->motionEventsCount; ++i) { GameActivityMotionEvent* motionEvent = &inputBuffer->motionEvents[i]; if (motionEvent->pointerCount > 0) { const int action = motionEvent->action; const int actionMasked = action & AMOTION_EVENT_ACTION_MASK; // Initialize pointerIndex to the max size, we only cook an // event at the end of the function if pointerIndex is set to a valid index range uint32_t pointerIndex = GAMEACTIVITY_MAX_NUM_POINTERS_IN_MOTION_EVENT; struct CookedEvent ev; memset(&ev, 0, sizeof(ev)); ev.motionIsOnScreen = motionEvent->source == AINPUT_SOURCE_TOUCHSCREEN; if (ev.motionIsOnScreen) { // use screen size as the motion range ev.motionMinX = 0.0f; ev.motionMaxX = SceneManager::GetInstance()->GetScreenWidth(); ev.motionMinY = 0.0f; ev.motionMaxY = SceneManager::GetInstance()->GetScreenHeight(); } switch (actionMasked) { case AMOTION_EVENT_ACTION_DOWN: pointerIndex = 0; ev.type = COOKED_EVENT_TYPE_POINTER_DOWN; break; case AMOTION_EVENT_ACTION_POINTER_DOWN: pointerIndex = ((action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); ev.type = COOKED_EVENT_TYPE_POINTER_DOWN; break; case AMOTION_EVENT_ACTION_UP: pointerIndex = 0; ev.type = COOKED_EVENT_TYPE_POINTER_UP; break; case AMOTION_EVENT_ACTION_POINTER_UP: pointerIndex = ((action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT); ev.type = COOKED_EVENT_TYPE_POINTER_UP; break; case AMOTION_EVENT_ACTION_MOVE: { // Move includes all active pointers, so loop and process them here, // we do not set pointerIndex since we are cooking the events in // this loop rather than at the bottom of the function ev.type = COOKED_EVENT_TYPE_POINTER_MOVE; for (uint32_t i = 0; i < motionEvent->pointerCount; ++i) { _cookEventForPointerIndex(motionEvent, callback, ev, i); } break; } default: break; } // Only cook an event if we set the pointerIndex to a valid range, note that // move events cook above in the switch statement. if (pointerIndex != GAMEACTIVITY_MAX_NUM_POINTERS_IN_MOTION_EVENT) { _cookEventForPointerIndex(motionEvent, callback, ev, pointerIndex); } } } android_app_clear_motion_events(inputBuffer); }
Weitere Informationen finden Sie in der GitHub-Beispiel zur Implementierung von
_cookEventForPointerIndex()
und anderen verwandten Funktionen.Wenn Sie fertig sind, denken Sie daran, die Warteschlange der Ereignisse zu löschen, gehandhabt:
android_app_clear_motion_events(mApp);
Weitere Informationen
Weitere Informationen zu GameActivity
finden Sie hier:
- Versionshinweise zu GameActivity und AGDK
- GameTextInput in GameActivity verwenden
- Migrationsanleitung für NativeActivity
- GameActivity-Referenzdokumentation
- GameActivity-Implementierung
Wenn Sie Fehler melden oder neue Funktionen für GameActivity anfordern möchten, verwenden Sie den GameActivity-Issue Tracker.