Chƣơng 2 : PHÂN TÍCH VÀ XÂY DỰNG ĐỀ TÀI
4. Chuyển game trên máy tính sang điện thoại
Để chuyển game từ máy tính sang điện thoại, chúng ta cần cài đặt các công cụ
- Android SDK
- Android NDK
- Cygwin
Sau khi cài đặt hoàn tất các mơi trƣờng trên thì bắt đầu việc chuyển đổi bằng cách tạo ra một Project Android.
Sau đó ta cần biên dịch các file CPP của game bằng cách dùng NDK và Cygwin và Make. Sau đây là file định nghĩa các file CPP cần biên dịch cho MAKE.
LOCAL_MODULE := libgl2jni LOCAL_CFLAGS := -Werror LOCAL_SRC_FILES := ../../InternshipFW/3DMath.cpp \ ../../InternshipFW/Application.cpp \ ../../InternshipFW/BoxObject.cpp \ ../../InternshipFW/BrokenGlass.cpp \ ../../InternshipFW/Bullet.cpp \ ../../InternshipFW/Camera.cpp \ ../../InternshipFW/Cannon.cpp \ ../../InternshipFW/Castle.cpp \ ../../InternshipFW/CreditsState.cpp \ ../../InternshipFW/EnemyBullet.cpp \ ../../InternshipFW/FileSystem.cpp \ ../../InternshipFW/FinishLevelState.cpp \ ../../InternshipFW/GameLevelState.cpp \ ../../InternshipFW/GameOverState.cpp \ ../../InternshipFW/Graphic.cpp \ ../../InternshipFW/Ground.cpp \ ../../InternshipFW/HP.cpp \ ../../InternshipFW/IngameState.cpp \ ../../InternshipFW/Input.cpp \ ../../InternshipFW/LevelSelectState.cpp \ ../../InternshipFW/LoadingState.cpp \ ../../InternshipFW/LogoScreenState.cpp \ ../../InternshipFW/MainMenuState.cpp \ ../../InternshipFW/ManageEnemy.cpp \ ../../InternshipFW/Model.cpp \ ../../InternshipFW/ObjManager.cpp \ ../../InternshipFW/Objects.cpp \ ../../InternshipFW/ObjectsManager.cpp \ ../../InternshipFW/Particle.cpp \ ../../InternshipFW/ParticleHP.cpp \ ../../InternshipFW/ParticleSystem.cpp \
66 ../../InternshipFW/PearlSkill.cpp \ ../../InternshipFW/ResourcesManager.cpp \ ../../InternshipFW/SceneManager.cpp \ ../../InternshipFW/ScoreManager.cpp \ ../../InternshipFW/Sea.cpp \ ../../InternshipFW/Shaders.cpp \ ../../InternshipFW/StateManager.cpp \ ../../InternshipFW/Status_Bar.cpp \ ../../InternshipFW/TGA.cpp \ ../../InternshipFW/Texture.cpp \ ../../InternshipFW/TopScoreState.cpp \ ../../InternshipFW/WaitingScreenState.cpp \ ../../InternshipFW/WarShip.cpp \ ../../InternshipFW/WaterSpark.cpp \ gl_code.cpp \
LOCAL_LDLIBS := -llog -lGLESv2
Sau khi biên dịch xong, chúng ta sẽ dùng một chƣơng trình JNI trung gian làm cầu nối giữa C++ và Java. Chƣơng trình này có nhiệm vụ liên kết các file vừa biên dịch với Java để chạy trên Android.
#include <jni.h>
#include <android/log.h>
#include "../../InternshipFW/Application.h" #include "../../InternshipFW/Input.h"
static jobject bridge;
static jmethodID android_playSound; static jmethodID android_playMusic; static jmethodID android_stopSound; static jmethodID android_stopMusic; static JavaVM* jVM;
extern "C" {
JNIEXPORT void JNICALL Java_com_drybones_evate_GL2JNILib_init(JNIEnv * env, jobject obj, jstring sdpath);
JNIEXPORT void JNICALL Java_com_drybones_evate_GL2JNILib_step(JNIEnv * env, jobject obj, jfloat deltaTime);
JNIEXPORT void JNICALL
Java_com_drybones_evate_GL2JNILib_pointer(JNIEnv * env, jobject obj, jint type, jint x, jint y, jint x2, jint y2);
void
Java_com_drybones_evate_GL2JNILib_BridgeJ2C( JNIEnv* env,
jobject thiz, jobject obj )
{
bridge = obj;
67
(jVM)->GetEnv((void**) &env, JNI_VERSION_1_6); bridge = (jobject)(env)->NewGlobalRef( obj); glViewClass = (env)->GetObjectClass( bridge);
android_playSound = (env)->GetMethodID(glViewClass, "playSound",
"(II)V");
android_playMusic = (env)->GetMethodID(glViewClass, "playMusic",
"(II)V");
android_stopSound = (env)->GetMethodID(glViewClass, "stopSound",
"()V");
android_stopMusic = (env)->GetMethodID(glViewClass, "stopMusic",
"()V");
LOGI("End C call java init"); }
int
JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv *env; jVM = vm;
LOGI("JNI ONLOAD");
if((vm)->GetEnv((void**) &env, JNI_VERSION_1_6) != JNI_OK) { return -1; } return JNI_VERSION_1_6; } // Play Sound
void PlaySound(int id, int loop) {
JNIEnv *env;
(jVM)->GetEnv((void**) &env, JNI_VERSION_1_6);
(env)->CallVoidMethod(bridge, android_playSound, id, loop); LOGI("\nPlay Sound from jni!!");
};
void PlayMusic(int id, int loop) {
JNIEnv *env;
(jVM)->GetEnv((void**) &env, JNI_VERSION_1_6);
(env)->CallVoidMethod(bridge, android_playMusic, id, loop); LOGI("\nPlay Music from jni!!");
}
void StopSound() {
JNIEnv *env;
(jVM)->GetEnv((void**) &env, JNI_VERSION_1_6); (env)->CallVoidMethod(bridge, android_stopSound);
68
}
void StopMusic() {
JNIEnv *env;
(jVM)->GetEnv((void**) &env, JNI_VERSION_1_6); (env)->CallVoidMethod(bridge, android_stopMusic); }
};
JNIEXPORT void JNICALL Java_com_drybones_evate_GL2JNILib_init(JNIEnv * env, jobject obj, jstring sdpath)
{
LOGI("Start JNI Load");
Application::GetInstance()->Init( "/mnt/sdcard/Evate/Resource" ); LOGI("Finish JNI Load");
}
JNIEXPORT void JNICALL Java_com_drybones_evate_GL2JNILib_step(JNIEnv * env, jobject obj, jfloat deltaTime)
{
//LOGI("JNI deltaTime: %f", deltaTime);
Application::GetInstance()->Render();
Application::GetInstance()->Update(deltaTime); }
JNIEXPORT void JNICALL Java_com_drybones_evate_GL2JNILib_pointer(JNIEnv * env, jobject obj, jint type, jint x, jint y, jint x2, jint y2)
{ if (type == 1) Input::GetInstance()->OnPointer(POINTER_DOWN, x, y, x2, y2); if (type == 2) Input::GetInstance()->OnPointer(POINTER_UP, x, y, x2, y2); }
Dòng lệnh sau đây dùng để chỉ định đƣờng dẫn load dữ liệu là trên thẻ nhớ cho game.
Application::GetInstance()->Init( "/mnt/sdcard/Evate/Resource" );
Trong mã nguồn game, có những đoạn xử lý kiểm tra, nếu hệ thống là Android thì sẽ thực hiện các chức năng riêng biệt, ví dụ:
#ifdef _ANDROID if (ResourcesManager::GetInstance()->isPlaySound == 1) { StopSound(); PlaySound(2, 0); } #endif
69