Este artigo apresenta um guia completo e autossuficiente para criar um jogo Android integrando React Native com o Axmol Engine. O objetivo é combinar a interface moderna em JavaScript com a performance nativa em C++ do motor de jogo, cobrindo todos os arquivos e configurações necessários.
O conteúdo descreve passo a passo a estrutura do projeto, arquivos Java/Kotlin e C++, scripts de build, configuração do NDK e do CMake, além do código-fonte do jogo simples com sprites e detecção de colisão. As instruções assumem ambiente de desenvolvimento onde ferramentas básicas já estão instaladas.
Visão geral da arquitetura e termos principais
O projeto combina duas camadas: a camada de UI em React Native, escrita em JavaScript, e a camada de renderização em C++ fornecida pelo Axmol Engine. O NDK (Native Development Kit) permite compilar código C++ para o Android. O CMake é o gerador de build que cria os artefatos nativos para integração com o Gradle. A ponte entre JavaScript e C++ passa por módulos nativos Java + JNI (Java Native Interface).
Pré-requisitos de software
A lista abaixo mostra o software mínimo e versões recomendadas para seguir o guia sem falhas.
- Node.js 20.x ou superior e npm 10.x+
- React Native CLI para criação do projeto
- Android Studio 2024.3.2+ com NDK r25+ instalado
- CMake 3.28.1+ instalado
- Python 3.9+ para scripts de setup do Axmol
- Git e um editor de código (por exemplo, VS Code)
Criação do projeto React Native
O trecho a seguir mostra os comandos para inicializar o projeto React Native. Estes comandos geram a estrutura básica de um app Android com suporte à ponte nativa.
# Instalar o CLI (se necessário)
npm install -g @react-native-community/cli
# Criar o projeto (exemplo com versão fixa)
npx @react-native-community/cli@latest init MyAxmolGame --version 0.75.4
# Acessar a pasta do projeto
cd MyAxmolGame
O arquivo package.json mínimo do projeto deve conter dependências essenciais para React Native e a definição do aplicativo. Abaixo está um exemplo reduzido, incluindo a dependência do módulo nativo que será exposto.
{
"name": "MyAxmolGame",
"version": "0.0.1",
"private": true,
"scripts": {
"android": "react-native run-android"
},
"dependencies": {
"react": "18.2.0",
"react-native": "0.75.4"
}
}
Estrutura da interface React Native (App.js)
O arquivo App.js expõe um botão de controle e uma view nativa que receberá a renderização do Axmol. O trecho abaixo cria a interface principal e demonstra a chamada ao módulo nativo para iniciar o jogo.
import React, { useEffect, useState } from 'react';
import { View, Text, Button, StyleSheet, NativeModules, requireNativeComponent } from 'react-native';
const { AxmolModule } = NativeModules;
const AxmolView = requireNativeComponent('AxmolView');
export default function App() {
const [score, setScore] = useState(0);
const startGame = () => {
AxmolModule.startGame();
setScore(prev => prev + 1); // demonstração local de atualização
};
useEffect(() => {
return () => {
AxmolModule.stopGame && AxmolModule.stopGame();
};
}, []);
return (
);
}
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: 'center', alignItems: 'center' },
title: { fontSize: 24, marginBottom: 20 },
gameView: { width: 360, height: 640, marginBottom: 20 }
});
Clonagem e configuração do Axmol Engine
O repositório do Axmol Engine precisa ser clonado e inicializado para gerar as bibliotecas nativas usadas pelo aplicativo Android. Os comandos a seguir exemplificam o fluxo de preparação do motor.
# Clonar o Axmol (exemplo de branch/tag compatível)
git clone https://github.com/axmolengine/axmol.git
cd axmol
# Executar script de setup do Axmol (pode criar variáveis de ambiente)
python setup.py
# Instalar NDK r25 (script de exemplo presente no repositório)
./tools/external/install-ndk-r25.sh
O passo acima gera bibliotecas e ferramentas internas do Axmol. É importante manter o diretório do Axmol acessível ao projeto React Native para referências no CMake.
Estrutura de arquivos nativos Android a criar
A seguir aparecem os arquivos Java e C++ principais que compõem a integração nativa. Cada arquivo será fornecido com conteúdo completo para inclusão no diretório indicado do projeto Android.
Lista de arquivos e seus locais (explicação antes da listagem): a lista aponta os arquivos que devem existir em android/app/src/main e subpastas relacionadas.
- android/app/src/main/java/com/myaxmolgame/AxmolModule.java
- android/app/src/main/java/com/myaxmolgame/AxmolPackage.java
- android/app/src/main/java/com/myaxmolgame/AxmolView.java
- android/app/src/main/java/com/myaxmolgame/AxmolViewManager.java
- android/app/src/main/java/com/myaxmolgame/AxmolRenderer.java
- android/app/src/main/java/com/myaxmolgame/MainActivity.java (modificado)
- android/app/src/main/cpp/CMakeLists.txt
- android/app/src/main/cpp/native-lib.cpp
- android/app/src/main/jniLibs/libaxmol.so (pré-compilado ou gerado pelo Axmol)
- android/app/src/main/assets/player.png e obstacle.png
Código do módulo nativo Java: AxmolModule.java
O módulo nativo Java expõe métodos que serão chamados a partir do JavaScript. O código abaixo mostra a declaração do módulo e métodos de início/parada do motor via JNI.
// android/app/src/main/java/com/myaxmolgame/AxmolModule.java
package com.myaxmolgame;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
public class AxmolModule extends ReactContextBaseJavaModule {
static {
System.loadLibrary("native-lib"); // carrega a biblioteca nativa construída
}
public AxmolModule(ReactApplicationContext context) {
super(context);
}
@Override
public String getName() {
return "AxmolModule";
}
@ReactMethod
public void startGame() {
// Chamada JNI para iniciar a cena Axmol
nativeStartGame();
}
@ReactMethod
public void stopGame() {
// Chamada JNI para parar o motor Axmol
nativeStopGame();
}
// Declarações JNI
private native void nativeStartGame();
private native void nativeStopGame();
}
Registro do pacote e view manager: AxmolPackage.java
O pacote registra módulos nativos e view managers para expor a view OpenGL ao React Native. O código abaixo adiciona AxmolModule e AxmolViewManager à lista de pacotes.
// android/app/src/main/java/com/myaxmolgame/AxmolPackage.java
package com.myaxmolgame;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class AxmolPackage implements ReactPackage {
@Override
public List createNativeModules(ReactApplicationContext reactContext) {
List modules = new ArrayList<>();
modules.add(new AxmolModule(reactContext));
return modules;
}
@Override
public List createViewManagers(ReactApplicationContext reactContext) {
List managers = new ArrayList<>();
managers.add(new AxmolViewManager());
return managers;
}
}
View nativa para renderização OpenGL: AxmolView.java e AxmolRenderer.java
A view personalizada cria um contexto OpenGL ES e delega a renderização ao motor nativo. O AxmolRenderer mantém pontos de entrada onde a camada nativa pode inicializar e desenhar cada frame.
// android/app/src/main/java/com/myaxmolgame/AxmolView.java
package com.myaxmolgame;
import android.content.Context;
import android.opengl.GLSurfaceView;
public class AxmolView extends GLSurfaceView {
public AxmolView(Context context) {
super(context);
setEGLContextClientVersion(2); // OpenGL ES 2.0
setRenderer(new AxmolRenderer());
setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
}
}
// android/app/src/main/java/com/myaxmolgame/AxmolRenderer.java
package com.myaxmolgame;
import android.opengl.GLSurfaceView;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.egl.EGLConfig;
public class AxmolRenderer implements GLSurfaceView.Renderer {
static {
System.loadLibrary("native-lib");
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// Chama inicialização nativa do Axmol
nativeOnSurfaceCreated();
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
nativeOnSurfaceChanged(width, height);
}
@Override
public void onDrawFrame(GL10 gl) {
nativeOnDrawFrame();
}
private native void nativeOnSurfaceCreated();
private native void nativeOnSurfaceChanged(int width, int height);
private native void nativeOnDrawFrame();
}
View manager para expor AxmolView ao React Native
O view manager registra o nome da view que será referenciada em JavaScript por meio de requireNativeComponent. O código abaixo cria a instância da view nativa.
// android/app/src/main/java/com/myaxmolgame/AxmolViewManager.java
package com.myaxmolgame;
import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.ThemedReactContext;
public class AxmolViewManager extends SimpleViewManager {
@Override
public String getName() {
return "AxmolView";
}
@Override
protected AxmolView createViewInstance(ThemedReactContext reactContext) {
return new AxmolView(reactContext);
}
}
Integração na MainActivity e registro de pacote
O registro do pacote nativo é necessário para que o React Native carregue AxmolPackage. O trecho abaixo demonstra a inclusão no método de obtenção de pacotes do aplicativo Android.
// android/app/src/main/java/com/myaxmolgame/MainActivity.java (trecho para registro)
import com.myaxmolgame.AxmolPackage;
@Override
protected List getPackages() {
List packages = new PackageList(this).getPackages();
packages.add(new AxmolPackage());
return packages;
}
Arquivo CMakeLists.txt para build nativo
O CMakeLists define como o código nativo será ligado à biblioteca Axmol pré-compilada e como será gerado o artefato nativo. O exemplo abaixo assume que libaxmol.so está em jniLibs.
cmake_minimum_required(VERSION 3.28.1)
project(MyAxmolGame)
# Diretório base do projeto nativo
set(CMAKE_CXX_STANDARD 17)
include_directories(${CMAKE_SOURCE_DIR}/../../../../axmol/core)
# Considera que libaxmol.so foi colocada em jniLibs/$(ANDROID_ABI)/
add_library(axmol SHARED IMPORTED)
set_target_properties(axmol PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libaxmol.so)
add_library(native-lib SHARED native-lib.cpp)
find_library(log-lib log)
target_link_libraries(native-lib axmol ${log-lib})
Código C++ nativo: native-lib.cpp e lógica do jogo
O código nativo inicializa o Axmol, cria uma cena simples com dois sprites e implementa movimento e colisão. Comentários em português explicam cada parte essencial.
// android/app/src/main/cpp/native-lib.cpp
#include
#include
#include
// Usando namespace do Axmol
USING_NS_AX;
static Scene* g_scene = nullptr;
static Sprite* player = nullptr;
static Sprite* obstacle = nullptr;
// Classe de cena com lógica básica
class GameScene : public Scene {
public:
static Scene* createScene() {
return GameScene::create();
}
bool init() override {
if (!Scene::init()) return false;
auto visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();
// Adiciona caminho de recursos
FileUtils::getInstance()->addSearchPath("assets");
// Cria jogador
player = Sprite::create("player.png");
player->setPosition(visibleSize.width / 4, visibleSize.height / 2);
this->addChild(player);
// Cria obstáculo
obstacle = Sprite::create("obstacle.png");
obstacle->setPosition(visibleSize.width * 3 / 4, visibleSize.height / 2);
this->addChild(obstacle);
// Agendar update para lógica de movimento
scheduleUpdate();
return true;
}
void update(float dt) override {
auto pos = player->getPosition();
pos.x += 150.0f * dt; // movimento contínuo para a direita
if (pos.x > Director::getInstance()->getVisibleSize().width) {
pos.x = 0; // reinicia posição no limite
}
player->setPosition(pos);
// Verificação simples de colisão por bounding box
if (player->getBoundingBox().intersectsRect(obstacle->getBoundingBox())) {
log("Colisão detectada!");
}
}
};
extern "C" JNIEXPORT void JNICALL
Java_com_myaxmolgame_AxmolModule_nativeStartGame(JNIEnv* env, jobject thiz) {
// Inicializa diretor e executa cena
auto director = Director::getInstance();
if (!g_scene) {
g_scene = GameScene::createScene();
}
if (!director->getRunningScene()) {
director->runWithScene(g_scene);
} else {
director->replaceScene(g_scene);
}
}
extern "C" JNIEXPORT void JNICALL
Java_com_myaxmolgame_AxmolModule_nativeStopGame(JNIEnv* env, jobject thiz) {
auto director = Director::getInstance();
director->end();
}
extern "C" JNIEXPORT void JNICALL
Java_com_myaxmolgame_AxmolRenderer_nativeOnSurfaceCreated(JNIEnv* env, jobject thiz) {
// Inicialização gráfica do Axmol, se necessário
}
extern "C" JNIEXPORT void JNICALL
Java_com_myaxmolgame_AxmolRenderer_nativeOnSurfaceChanged(JNIEnv* env, jobject thiz, jint width, jint height) {
// Atualizar viewport ou estados dependentes de resolução
}
extern "C" JNIEXPORT void JNICALL
Java_com_myaxmolgame_AxmolRenderer_nativeOnDrawFrame(JNIEnv* env, jobject thiz) {
// Este método pode permanecer vazio se Axmol fizer loop interno
}
Recursos e pastas de assets
As imagens do jogador e do obstáculo devem ficar em android/app/src/main/assets/ para serem carregadas pelo Axmol usando FileUtils. Abaixo está a estrutura de pastas relevante.
- android/app/src/main/assets/player.png
- android/app/src/main/assets/obstacle.png
- android/app/src/main/jniLibs/armeabi-v7a/libaxmol.so (exemplo ABI)
Alterações no android/app/build.gradle
O arquivo build.gradle do módulo app deve declarar a integração com o CMake e versões do NDK. O trecho abaixo mostra a configuração mínima necessária para compilar o código nativo.
android {
compileSdkVersion 35
defaultConfig {
applicationId "com.myaxmolgame"
minSdkVersion 21
targetSdkVersion 35
versionCode 1
versionName "1.0"
externalNativeBuild {
cmake {
cppFlags "-std=c++17 -frtti -fexceptions"
}
}
}
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
version "3.28.1"
}
}
ndkVersion "25.2.9519653"
}
Arquivo .axproj e alinhamento com Axmol
O arquivo .axproj contém parâmetros que ajudam a ferramenta do Axmol a gerar projetos compatíveis. Abaixo segue um exemplo que deve ficar na raiz do projeto React Native.
# .axproj
packageName=com.myaxmolgame
minSdk=21
targetSdk=35
ndkVer=25.2.9519653
cmakeVer=3.28.1
cmakeOptions=[]
Comandos de build e execução para Android
Os comandos a seguir exemplificam a ordem de compilação e deploy do app Android. A execução pode ser feita em emulador ou dispositivo físico com depuração habilitada.
# Construir e instalar o app via React Native CLI
npx react-native run-android
# Em caso de problemas com build nativo, limpar build e tentar novamente
cd android
./gradlew clean
cd ..
npx react-native run-android
Dicas de depuração e resolução de problemas
Erros comuns incluem incompatibilidades de versão do NDK, paths incorretos para libaxmol.so e problemas no CMake. Mensagens do Gradle e do logcat ajudam a identificar bibliotecas ausentes ou símbolos JNI não encontrados. Verificar se System.loadLibrary utiliza o mesmo nome do artefato gerado evita falhas de carregamento.
Cuidados com performance e gerenciamento de recursos
Manter a renderização do Axmol em uma view separada ajuda a isolar a GPU e reduzir conflitos com componentes React Native. Evitar alocações pesadas no loop de render reduz variações no frame rate. Encerrar corretamente o diretor do Axmol no método stopGame evita vazamentos de memória ao sair da atividade.
Resumo dos arquivos entregues neste guia
Foram apresentados os arquivos Java, C++ e de configuração essenciais para executar o jogo Android integrado com React Native e Axmol Engine. A lista inclui App.js, package.json exemplo, todos os arquivos Java nativos, CMakeLists.txt, native-lib.cpp, .axproj e instruções de build e assets. Com essas peças reunidas, o projeto contém tudo o que é necessário para compilar e executar a versão Android do jogo simples descrito neste documento.