1.8.1. Android là gì?
Android là một hệ điều hành dựa trên nền tảng Linux đƣợc thiết kế dành cho các thiết bị di động có màn hình cảm ứng nhƣ điện thoại thông minh và máy tính bảng.
Android có mã nguồn mở và Google phát hành mã nguồn theo giấy phép apache. Chính mã nguồn mở cùng với một giấy phép không có nhiều ràng buộc đã cho phép các nhà phát triển thiết bị, mạng di động và các lập trình viên nhiệt huyết đƣợc điều chỉnh và phân phối Android một cách tự do.
1.8.2. Các tính năng mở của Android
- Bộ nguồn đƣợc cung cấp miễn phí cho các nhà sản xuất, và nhà sản xuất có thể sử dụng thoài mái mà không cần xin phép google.
- Cho phép các nhà phát triển xây dựng đƣợc những ứng dụng mà có thể sử dụng tối đa những thành phần phần cứng và hệ điều hành cung cấp.
- Các ứng dụng do các nhà phát triển hoàn toàn thay thế đƣợc các ứng dụng lõi của hệ điều hành: phone, sms.
- Ngoài ra, Android cũng đƣợc cung cấp một bộ phát triển mạnh nhiều tool và debug dễ dàng ngay cả với máy thật, kết hợp với IDE là Eclipse.
1.8.3. Một số phiên bản của Android
Từ năm 2008, Android đã trải qua nhiều lần cập nhật để cải tiến hệ điều hành, bổ sung các tính năng mới và sửa các lỗi trong những lần phát hành trƣớc.
- Android 1.0 - Android 1.1 - Android 1.5: Cupcake - Android 1.6: Donut - Android 2.0: Eclair - Android 2.2: Froyo - Android 2.3: Gingerbread - Android 3.0: Honeycomb
Nguyễn Thị Ngọc Thúy – 10CNTT4 Trang 24
- Android 4.0: Ice Cream Sandwich
- Android 4.1: Jelly Bean
- Android 4.2: Jelly Bean
- Android 4.4: KitKat
TỔNG KẾT CHƢƠNG 1
Chƣơng này tôi đã trình bày tóm tắt các lý thuyết về OpenGL ES 2.0, cơ chế hoạt động của nó, các lý thuyết về phép biến đổi hình học trong không gian 3 chiều, và các phép chiếu. Đó là cơ sở để xây dựng game bằng cách vẽ các đối tƣợng ra màn hình một cách phù hợp.
Nguyễn Thị Ngọc Thúy – 10CNTT4 Trang 25
CHƢƠNG 2: PHÂN TÍCH THIẾT KẾ GAME HIGHWAY
2.1. KỊCH BẢN CỦA GAME
Highway là game thuộc thể loại game tốc độ. Trong game này sẽ gồm nhiều chiếc xe: một xe cho ngƣời chơi và những chiếc xe khác chạy ngƣợc chiều cản trở sự di chuyển của xe ngƣời chơi. Ngƣời chơi cố gắng di chuyển để tránh xe cản trên đƣờng và chạm những vật phẩm trên đƣờng để giành điểm cao nhất đƣợc lọt vào bảng xếp hạng top năm điểm số cao.
2.2. PHÂN TÍCH YÊU CẦU
Dựa vào kịch bản của game đƣợc phân thành các thành phần nhỏ để dễ giải quyết.
Game đƣợc thiết kế chạy trên nền hệ điều hành Windows và Android. Tận dụng đƣợc các tính năng cảm ứng khi chơi trên điện thoại di động và các phím xử lý khi trên hệ điều hành Windows, game gồm ba phần chính: Phần đồ họa, âm thanh và phần mã nguồn.
Phần đồ họa bao gồm: Các model và texture.
Phần âm thanh bao gồm âm thanh nền, âm thanh khi xe tăng tốc, âm thanh khi xe va chạm và âm thanh khi hai xe va chạm nhau.
Phần mã nguồn xác định các đối tƣợng và các state cần có. Quản lý tốt các resource và scene của chƣơng trình tránh lãng phí tài nguyên.
Bố trí các đối tƣợng:
Xe của ngƣời chơi sẽ đƣợc đặt ở tọa độ: (0.0, 0.0, 5.0) ở phía trƣớc gần camera.
Các xe cản sẽ đƣợc bố trí ở tọa độ vị trí cách xa camera: (0.0, 0.0, -500.0). Vị trí của xe cản có thể đƣợc random theo tọa độ x.
Khi quá trình va chạm giữa hai xe thì game over. Cách tính điểm:
Khi quá trình va chạm giữa xe của ngƣời chơi và các vật phẩm trên đƣờng thì điểm số sẽ đƣợc tăng thêm 10 điểm.
Nguyễn Thị Ngọc Thúy – 10CNTT4 Trang 26 Khi xe của ngƣời chơi tránh đƣợc một xe trên đƣờng điểm số sẽ tăng thêm 20 điểm.
Xác định đƣợc ngƣời chơi có điểm số cao nhất đƣa vào top 5 ngƣời có điểm số cao nhất.
2.3. ĐẶC TẢ CHỨC NĂNG CỦA GAME2.3.1. Biểu đồ Use case 2.3.1. Biểu đồ Use case
Nguyễn Thị Ngọc Thúy – 10CNTT4 Trang 27
2.3.2. Mô tả Actor
Tên Actor Mô tả
Ngƣời chơi Bắt đầu chơi game.
Ngƣời chơi điều khiển xe để tránh các xe đi ngƣợc chiều và ăn các vật phẩm trên đƣờng để tăng điểm số. AI Sự điều khiển xe của các xe ngƣợc chiều.
n 4: Đặc t Actor
Tên Use case Mô tả
Điều khiển xe của ngƣời chơi
Use case này cho phép ngƣời chơi điều khiển chiếc xe của mình, thay đổi tốc độ của xe.
Xem hƣớng dẫn chơi Use case này cho phép ngƣời chơi xem hƣớng dẫn cách chơi của game.
Xem điểm cao Use case này cho phép ngƣời chơi xem top năm những điểm số cao nhất.
Play game Use case này cho phép ngƣời chơi bắt đầu chơi game. Điều khiển xe của AI Use case này cho phép xe đối thủ tự động di chuyển
cản trở xe của ngƣời chơi.
n 5: Đặc t Use case
2.4. XÂY DỰNG GAME ENGINE
2.4.1. Trạng thái game và vòng lặp game
Trạng thái game
Game là một chuỗi các trạng thái đƣợc diễn ra một cách tuần tự dƣới sự điều khiển của ngƣời chơi. Các trạng thái game luôn có liên quan và ảnh hƣởng lẫn nhau.
Một số trạng thái game cơ bản nhƣ: game loading, game play, game menu, high score, help state…
Nguyễn Thị Ngọc Thúy – 10CNTT4 Trang 28
H nh 24: Mô h nh chuyển đổi trạn thái ame
Vòng lặp game
Vòng lặp game là quá trình thực hiện lặp đi lặp lại một số công việc để duy trì hoạt động và ổn định của game. Vòng lặp game là thành phần cơ bản nhất mà của game mà game nào cũng có.
Mỗi trạng thái game đƣợc thiết kế bằng một vòng lặp game, trƣớc khi chuyển qua các trạng thái tiếp theo, một vòng lặp game đƣợc tổ chức nhƣ sau:
Vòng lặp game đƣợc bắt đầu bằng quá trình khởi tạo các thành phần cần thiết cho các quá trình sau hoạt động.
Quá trình update thực hiện tất cả các vấn đề liên quan đến tính toán nhƣ: tính toán va chạm, di chuyển, cập nhật các trí tuệ nhân tạo, đối tƣợng, âm thanh..
Quá trình render thực hiện vẽ tất cả các đối tƣợng ra màn hình.
Kết thúc là quá trình thu dọn các tài nguyên hệ thống nhƣ dọn dẹp, giải phóng bộ nhớ…
Quá trình update và render đƣợc thực hiện lặp đi lặp lại cho đến khi ngƣời chơi kết thúc game, mỗi lần quá trình update và render đƣợc thực hiện gọi là một khung hình.
Nguyễn Thị Ngọc Thúy – 10CNTT4 Trang 29 Để đảm bảo sự độc lập của tốc độ game và các thiết bị khi thực hiện quá trình update sẽ đƣợc tính toán tỉ lệ thuận với thời gian giữa hai khung hình.
H nh 25: Vòn lặp game
2.4.2. Xây dựng cấu trúc game
Một đối tƣợng trong game 3D luôn chứa ba thành phần: shader, texture, model. Nhƣ vậy, hai đối tƣợng khác nhau có thể dùng chung một mô hình, shader hoặc texture, để thuận tiện cho việc quản lý và tránh lãng phí bộ nhớ ta sẽ cần xây dựng một trình quản lý các tài nguyên này.
Trong game, nhiều đối tƣợng đƣợc vẽ ra cùng một lúc, cùng một thời điểm, vì vậy ta sẽ cần xây dựng một chƣơng trình quản lý tất cả các đối tƣợng này để đảm bảo các đối tƣợng đều đƣợc vẽ ra hoặc đƣợc cập nhật trạng thái khi thay đổi. Từ những vấn đề đã đề cập ở trên ta đƣa ra cấu trúc của một game thỏa mãn đƣợc các yêu cầu trên:
Nguyễn Thị Ngọc Thúy – 10CNTT4 Trang 30
H nh 26: Cấu trúc ame en ine
Ta xây dựng hai file Resourcer manager và Scene Manager. Trong đó file Resource Manager để quản lý toàn bộ các tài nguyên nhƣ model, texture của game. File Scene Manager chứa các thông tin hiển thị trên màn hình game.
Lớp Object: Là một lớp trừu tƣợng dùng để mô ta các đối tƣợng 2D, 3D và các hiệu ứng đƣợc sử dụng trong chƣơng trình.
H nh 27: Lớp dẫn xuất cơ b n của lớp Object
Lớp Object2D: dùng để vẽ các đối tƣợng 2D gồm có các thuộc tính:
ID background STATE 1
TEXTURE 15 X Y 0.0, 0.0 SIZE 800, 600
Nguyễn Thị Ngọc Thúy – 10CNTT4 Trang 31 SHADER 3
POSITION -400.0, -240.0, 0.0 SCALE 2.0, 1.7, 1.0
Trong đó:
- IDlà một giá trị duy nhất cho một đối tƣợng. - STATE trạng thái của đối tƣợng ẩn hoặc hiện. - TEXTURE ID của texture.
- X Y là tọa độ lấy màu của sprite.
- SIZE width, height - Kích thƣớc chiều dài và chiều rộng lấy màu trong sprite lớn.
- POSITION là vị trí của đối tƣợng trong không gian.
- ROTATION là góc quay theo trục x, y, z.
- SCALE là tỷ lệ của đối tƣợng.
Lớp Object3D: dùng để vẽ các đối tƣợng 3D gồm có các thuộc tính sau:
#Objects: 1 #ROAD ID 0 MODEL 8 TEXTURES 1 TEXTURE 4 CUBETEXTURES 0 SHADER 0 LIGHTS 0 LIGHT 0 POSITION 0.0, 0.0, 0.0 ROTATION 0.0, 0.0, 0.0 SCALE 0.15, 0.03, 5.0 - #Objects: số lƣợng đối tƣợng 3D. - #Tên đối tƣợng.
- ID thuộc tính duy nhất của game. - MODEL ID của model.
Nguyễn Thị Ngọc Thúy – 10CNTT4 Trang 32 - TEXTURE ID của texture.
- CUBETEXTURES Số lƣợng của texture bube. - SHADER ID của shader.
- LIGHTS Số lƣợng ánh sáng. - LIGHT ID của ánh sáng.
- POSITION là vị trí của đối tƣợng trong không gian.
- ROTATION là góc quay theo trục x, y, z.
- SCALE là tỷ lệ của đối tƣợng.
Lớp Resource manager: Chứa tất cả các tài nguyên đƣợc sử dụng trong chƣơng trình, bao gồm texture, shader, các model 3D và 2D, có chức năng khởi tạo tất cả tài nguyên khi chƣơng trình bắt đầu thực thi và thu dọn tất cả càng tài nguyên này khi chƣơng trình kết thúc.
Lớp Scene manager: Chứa một danh sách các đối tƣợng 2D, 3D trong chƣơng trình nhƣ nhân vật, thực đơn, camera… khi chƣơng trình cập nhật, hay thực hiện vẽ thì tất cả các đối tƣợng trong Scenes đều đƣợc cập nhật hay vẽ ra màn hình.
H nh 28: Sơ đồ cấu trúc mối quan hệ giữa Resource mana er và Scene mana er
Scene Manager và Resource Manager đều đƣợc xây dựng với cấu trúc Singleton. Để dễ truy cập và xử lý.
Nguyễn Thị Ngọc Thúy – 10CNTT4 Trang 33 Cấu trúc file có dạng: #Models: 2 ID 0 FILE ../sdcard/ExamGL/Resources/Models/gateway.nfg ID 1 FILE ../sdcard/ExamGL/Resources/Models/SkyBox.nfg #Textures: 2 ID 0 FILE ../sdcard/ExamGL/Resources/Textures/Terrain.tga TILING REPEAT ID 1 FILE ../sdcard/ExamGL/Resources/Textures/background_ gamePlay.tga TILING CLAMP #Shaders: 2 ID 0 VS ../sdcard/ExamGL/Resources/Shaders/Basic.vs FS ../sdcard/ExamGL/Resources/Shaders/Basic.fs ID 1 VS ../sdcard/ExamGL/Resources/Shaders/Basic.vs FS ../sdcard/ExamGL/Resources/Shaders/Cube.fs Trong đó Model: - #Model số lƣợng.
- ID: một giá trị duy nhất cho một model. - FILE: đƣờng dẫn tƣơng đối đến file model.
Texture:
- #Textures: Số lƣợng texture. - ID giá trị duy nhất của texture.
- FILE: đƣờng dẫn tƣơng đối đến filetexture.
Nguyễn Thị Ngọc Thúy – 10CNTT4 Trang 34
Shader:
- #Shaders: Số loại shader - ID giá trị duy nhất của shader.
- VS đƣờng dẫn tƣơng đối đến file vertex shader. - FS đƣờng dẫn tƣơng đối đến file fragment shader.
Lớp GameState: Là một lớp trừu tƣợng chứa thông tin một trạng thái của chƣơng trình. Tƣơng tự nhƣ một vòng lặp game. Dùng SetState để chuyển đổi giữa các game state với nhau.
Từ đó ta xây dựng các lớp dẫn xuất của game state để tạo ra các state cho game.
H nh 29: Lớp dẫn xuất của lớp game state
Lớp GamePlay: Là lớp chính thực hiện các thao tác lời gọi khởi tạo, cập nhật các đối tƣợng, vẽ các đối tƣợng và dọn dẹp các tài nguyên khi chƣơng trình kết thúc.
Nguyễn Thị Ngọc Thúy – 10CNTT4 Trang 35
2.4.3. Xử lý va chạm giữa các đối tƣợng
Nhằm đơn giản các tính toán, tính toán các va chạm trong game đƣợc quy đổi về các bài toán tính toán va chạm của các khối hình học nhƣ là khối hộp.
Trong khi đọc dữ liệu từ các model, ta xác định đƣợc các tọa độ theo trục theo các trục Ox, Oy, Oz lần lƣợt nhƣ sau: Xmax, Xmin, Ymax, Ymin, Zmax, Zmin. Từ đó xác định khối hộp bao quanh vật.
H nh 30: Khối hộp bao quanh đối tượng
Để xác định va chạm giữa hai vật trong không gian ta xác định khối hộp của hai đối tƣợng đó và kiểm tra so sánh tọa độ giữa hai vật.
Ta xét vị trí của hai vật A và B.
Trƣờng hợp 1 Trƣờng hợp 2
Ở trƣờng hợp 1: Xét vị trí tƣơng đối A ở bên cạnh B. Nếu Axmax > Axmin→ Hai vật không va chạm nhau.
Nếu Axmax <= Bxmin → Hai va hạm nhau.
Ở trường hợp 2: Xét vị trí tươ g đối A ở trước B. Nếu Azmin > Azmax →
Hai vật khô g va hạm nhau.
Nguyễn Thị Ngọc Thúy – 10CNTT4 Trang 36
2.5. XÂY DỰNG CẦU NỐI CỦA GAME TRÊN WINDOWS VÀ ANDROID ANDROID
2.5.1. Trên Windows
Window cung cấp sẵn các hàm tạo các cửa sổ hiển thị, tạo môi trƣờng cho OpenGL ES hoạt động, các hàm để tiếp nhận sự kiện.
Đầu tiên ta tạo cửa sổ hiển thị trong windows là khởi tạo môi trƣờng. Tạo hàm tiếp nhận xử lý sự kiện.
LRESULT CALLBACK WndProcedure(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
LRESULT lRet = 1;
int x = LOWORD(lParam);
int y = HIWORD(lParam);
static bool mouseDown = false;
switch (Msg) { case WM_CREATE: break; case WM_DESTROY: PostQuitMessage(WM_QUIT); break; case WM_KEYDOWN:
Game::GetInstance()->OnKey((unsigned char) wParam, true);
break;
case WM_KEYUP:
Game::GetInstance()->OnKey((unsigned char) wParam, false);
break; case WM_LBUTTONDOWN: case WM_RBUTTONDOWN: mouseDown = true; Game::GetInstance()->OnPointer(POINTER_DOWN, x, y); break; case WM_LBUTTONUP: case WM_RBUTTONUP: mouseDown = false; Game::GetInstance()->OnPointer(POINTER_UP, x, y); break; case WM_MOUSEMOVE: if (mouseDown) { Game::GetInstance()->OnPointer(POINTER_DRAGGED, x, y); } break; default:
lRet = DefWindowProc (hWnd, Msg, wParam, lParam);
break;
}
Nguyễn Thị Ngọc Thúy – 10CNTT4 Trang 37
}
Hàm kiểm tra lỗi
bool Game::TestEGLError(HWND hWnd, char* pszLocation)
{
EGLint iErr = eglGetError();
if (iErr != EGL_SUCCESS)
{
TCHAR pszStr[256];
sprintf_s(pszStr, ("%s failed (%d).\n"), pszLocation, iErr);
MessageBox(hWnd, pszStr, ("Error"), MB_OK|MB_ICONEXCLAMATION); return false; } return true; } Vòng lặp game int main() {
Game* game = Game::GetInstance(); game->Init(800, 480);
game->SetState(new LoadingState());
while ( game->IsRuning() ) { game->Update(); } Game::FreeInstance(); ResourceManager::FreeInstance(); } 2.5.2. Trên Android
Khởi tạo môi trƣờng và xử lý sự kiện
Android cung cấp lớp GLSurfaceView cho khởi tạo môi trƣờng hoạt động cho OpenGL ES.
private static class Renderer implements GLSurfaceView.Renderer {
public void onDrawFrame(GL10 gl) {
GL2JNILib.step(); }
public void onSurfaceChanged(GL10 gl, int width, int height) {
GL2JNILib.init(width, height); }
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
} }
Nguyễn Thị Ngọc Thúy – 10CNTT4 Trang 38 Lớp GLSurfaceView.Render cung cấp cho ta các hàm onDrawFrame dùng để vẽ, onSurfaceChanged dùng để tiếp nhận xử lý khi có sự thay đổi của môi trƣờng vẽ, nhƣ kích thƣớc, trạng thái… hàm onSurfaceCreated đƣợc gọi đến một lần đầu tiên khi môi trƣờng vẽ đƣợc thực hiện.
Khai báo các hàm native ở ứng dụng Android:
public static native void BridgeJ2C(GL2JNILib obj);
public static native void init(int width, int height);
public static native void step();
public static native void pointer(int type, int x, int y, int x2, int y2);
Ở chƣơng trình C++ ta hiện thực các hàm native tƣơng ứng:
extern "C" {
JNIEXPORT void JNICALL Java_com_drybones_evate_GL2JNILib_init(JNIEnv * env,
jobject obj, jint width, jint height);
JNIEXPORT void JNICALL Java_com_drybones_evate_GL2JNILib_step(JNIEnv * env,
jobject obj);
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; jclass glViewClass;
(jVM)->GetEnv((void**) &env, JNI_VERSION_1_6);
bridge = (jobject)(env)->NewGlobalRef( obj); glViewClass = (env)->GetObjectClass( bridge); }
};
JNIEXPORT void JNICALL Java_com_drybones_evate_GL2JNILib_init(JNIEnv * env,
jobject obj, jint width, jint height) {
Game* game = Game::GetInstance(); game->Init(width, height);
game->SetState(new LoadingState());
}
JNIEXPORT void JNICALL Java_com_drybones_evate_GL2JNILib_step(JNIEnv * env,
jobject obj) {
Game::GetInstance()->Update(); }
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) { InputManager::GetInstance()->OnTouch(POINTER_DOWN, x, y, x2, y2); } else if (type == 2)
Nguyễn Thị Ngọc Thúy – 10CNTT4 Trang 39