Đặc biệt trong ngành phần mềm, game là một lĩnh vực đặc biệt, đang có bước phát triển mạnh mẽ, khi mà nhu cầu giải trí trên các thiết bị di động của người sử dụng ngày một tăng cao.. Do
Trang 1TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TIN
TP.HCM, ngày 01 tháng 06 năm 2012
Trang 2LỜI MỞ ĐẦU
Ngày nay, điện thoại di động là một vật dụng không thể thiếu được trong cuộc sống Nó không chỉ có chức năng nghe gọi, mà còn có thể thực hiện được hầu hết những công việc
mà máy tính có thể làm, phục vụ cho nhu cầu văn phòng, giải trí và công việc
Đặc biệt trong ngành phần mềm, game là một lĩnh vực đặc biệt, đang có bước phát triển mạnh mẽ, khi mà nhu cầu giải trí trên các thiết bị di động của người sử dụng ngày một tăng cao Do đó, lập trình game trên các thiết bị di động đang là một xu hướng tất yếu củacác nhà làm phần mềm
Điện thoại Android với số lượng người dùng đông đảo, cùng với sự đa dạng về cấu hình,
đa dạng về chủng loại, đang là mảnh đất màu mỡ cho các nhà phát triển game Do đó, google cũng đã hỗ trợ Android rất nhiều những thư viện để lập trình game hiệu quả, trong
đó có thể kể đến OpenGL, một thư viện đồ họa rất mạnh mẽ
Với sự phát triển mạnh mẽ như vậy của Android, và lập trình game trên Android, cơ hội cho lập trình viên là rất lớn Vì vậy, nhóm đã chọn đề tài “Lập trình ứng dụng game trên Android” Trong đề tài này, nhóm sẽ trình bày cái nhìn cơ bản về lập trình game trên Android và demo một ứng dụng game trong đó
Cảm ơn thầy Nguyễn Trác Thức đã tận tình hướng dẫn chúng em hoàn thành đồ án này
Trang 3M c l c ục lục ục lục
1 Tìm hiểu về Android 1
1.1 Giới thiệu 1
1.2 Cấu trúc hệ thống 1
1.3 Các thành phần cơ bản của một ứng dụng Android 4
2 Kỹ thuật lập trình game trên Android 11
2.1 Thư viện đồ họa OpenGL 11
2.2 Thư viện âm thanh OpenAL 13
2.3 NDK 15
2.4 Lưu trữ thông tin 18
2.5 Các thư viện khác 22
2.6 Vòng đời của một game 22
3 Những khác biệt so giữa lập trình game trên thiết bị di động và trên máy tính 24
4 Những khác biệt so giữa lập trình game trên Android và các nền tảng di động khác 26 5 Giới thiệu game Kim cương 27
5.1 Giới thiệu cơ bản 27
5.2 Giao diện người dùng 27
5.3 Cách chơi 29
5.4 Tính năng mở rộng (item, mission) 30
5.5 Những điểm hấp dẫn trong game 30
Trang 41 Tìm hi u v Android ểu về Android ề Android.
1.1 Gi i thi u ới thiệu ệu
Android là một hệ điều hành dành cho các thiết bị di động, được phát triển bởi Open Handset Alliance, dẫn đầu bởi Google
Android được phát triển bởi Google, dựa trên nền tảng Linux và các phần mềm nguồn mở Ban đầu nó được phát triển bởi Android Inc (sau đó được Google mua lại) và gần đây nó trở thành một trong những phần mềm đứng đầu của liên minh OHA (Open Handset Alliance - với khoảng 78 thành viên bao gồm cả nhà sản xuất, nhà phát triển ứng dụng cho thiết bị di dộng mà dẫn đầu là Google)
Android được phát triển nhằm cạnh tranh với các hệ điều hành di động khác như iOS (Apple), BlackBerry OS, Windows Mobile (Microsoft), Symbian (Nokia), Samsung (Bada), WebOS (Palm) Theo thống kê trong quý II năm 2010 tại Mỹ, hệ điều hành Android chiếm thị phần 33% (cao nhất) trong tổng số các hệ điều hành di động được bán ra, thứ 2 là
BlackBerry OS 28% và iOS (Apple) xếp thứ 3 với 22%
1.2 C u trúc h th ng ấu trúc hệ thống ệu ống
Android gồm các tầng thành phần như sau : Application, Application Framework, Libraries, Linux Kernel
Trang 5Các tầng cơ bản của nền tảng Android
- Một bộ các đối tượng View để xây dựng nên các ứng dụng bao gồm list, grid, textboxes, buttons, và trình duyệt nhúng
- Content Providers cung cấp khả năng truy cập tới các dữ liệu của cácứng dụng khác
- Resource Manager cung cấp khả năng truy cập tới các resource không phải dạng code, như chuỗi, đồ họa và layout
Trang 6- Notification Manager giúp hiện các alert lên status bar.
- Activity Manager cung cấp khả năng quản lý vòng đời của ứng dụng
1.2.3 Libraries.
Android bao gồm một bộ các thư viện C/C++ sử dụng bởi các thành phần khác nhau Một số thư viện Android được sử dụng như :
- System C library : Thư viện chuẩn C
- Thư viện đa phương tiện : dựa trên PacketVideo's OpenCORE, thư viện hỗ trợ chơi các định dạng âm thanh và video phổ biến như MPEG4, H.264, MP3, AAC, JPG, PNG…
- Quản lý surface : Quản lý việc truy cập các hệ thống hiển thị bên dưới, các lớp đồ họa 2D, 3D
- LibWebCore : Một engine trình duyệt hiện đại, được sử dụng trong
cả trình duyệt Android và WebView control
- SGL : Cơ sở của đồ họa 2D
- 3D libraries : thư viện đồ họa 3D OpenGL, sử dụng tăng tốc đồ họa nếu phần cứng cho phép
- FreeType : thư viện render vector và bitmap font
- SQLite : Engine hệ quản trị cơ sở dữ liệu mạnh mẽ và nhẹ
1.2.4 Android Runtimes
Mỗi ứng dụng Android chạy trên một tiến trình riêng, với một máy ảo Dalvik Máy ảo này thực thi file dex, một dạng file được tối ưu cho bộ nhớ nhỏ
1.2.5 Nhân linux
Android dựa trên nhân linux 2.6 cho những dịch vụ hệ thống như bảo mật, quản lý bộ nhớ, network stack và driver model Nhân cũng được coi như là một lớp ảo trung gian giữa phần cứng và phần mềm
Trang 71.3 Các thành ph n c b n c a m t ng d ng Android ần cơ bản của một ứng dụng Android ơ bản của một ứng dụng Android ản của một ứng dụng Android ủa một ứng dụng Android ột ứng dụng Android ứng dụng Android ục lục
Một ứng dụng Android được tạo bởi một hay nhiều thành phần cơ bản dướiđây:
1.3.1 Activity
Activity là thành phần có nhiệm vụ hiển thị ra giao diện của ứng dụng Một ứng dụng có thể bao gồm nhiều Activity Chúng tồn tại độc lập với nhau, nhưng cũng có thể gọi lẫn nhau Một ứng dụng cũng có thể gọi tớiActivity của một ứng dụng khác (nếu được ứng dụng kia cho phép)
• Vòng đời của Activity
Actitvity là thành phần quan trọng nhất và đóng vai trò chính trong xây dựng ứng dụng Android
Hệ điều hành Android quản lý Activity theo dạng stack: khi một
Activity mới được khởi tạo, nó sẽ được xếp lên đầu của stack và trở thành running activity, các Activity trước đó sẽ bị tạm dừng và chỉ hoạt động trở lại khi Activity mới được giải phóng
Các trạng thái trong Activity:
Trang 8Running: Activity đang hiển thị trên màn hình (foreground).
Paused: Activity vẫn hiển thị (visible) nhưng không thể tương tác (lost
focus)
Stop: Activity bị thay thế hoàn toàn bởi Activity mới sẽ tiến đến trạng
thái stop
Trang 9Killed: Khi hệ thống bị thiếu bộ nhớ, nó sẽ giải phóng các tiến trình
theo nguyên tắc ưu tiên Các Activity ở trạng thái stop hoặc paused cũng
có thể bị giải phóng và khi nó được hiển thị lại thì các Activity này phải khởi động lại hoàn toàn và phục hồi lại trạng thái trước đó
• Khởi động Activity
- Khai báo tường minh: cung cấp chính xác thông tin của activity cần gọi (nếu cùng ứng dụng chỉ cần cung cấp tên class, nếu ứng dụng khác nhau thì cung cấp tên package, tên class)
Ví dụ: Gọi Activity tường minh
Intent intent = new Intent(getApplicationContext(),
TargetActivity.class);
startActivity(intent);
- Khai báo không tường minh: cung cấp thao tác cần làm gì, với loại
dữ liệu nào, thao tác thuộc nhóm nào… hệ thống sẽ tìm activity tương ứng để khởi động
Ví dụ: Gọi Activity không tưởng minh
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(MediaStore.Images.Media.EXTERNAL_CONTENT_URI); startActivity(intent);
• Liên lạc giữa 2 Activity
Khi khởi động một activity, ta có thể gửi kèm dữ liệu trong intent như ví
dụ sau:
intent.putExtra("value1", new String("Hello"));
intent.putExtra(“value2", new Long(100));Bên phía activity được khởi động, có thể lấy dữ liệu được gửi như sau:
getIntent().getExtras().getString("value1");
getIntent().getExtras().getLong("value2");
Có thể khởi động một activity với một yêu cầu nào đó và activity kia khilàm xong công việc sẽ trả lại kết quả cho activity trước
Trang 10Ví dụ activity A yêu cầu một activity làm giúp việc chụp ảnh, activity Bđáp ứng được việc này, sau khi user chụp ảnh xong sẽ trả lại file ảnh cho activity A.
Như thế sẽ đỡ tốn nhiều công sức làm một việc mà người khác đã làm rồi
1.3.2 Services
Service là một thành phần chạy nền, thực thi trong một thời gian dài Một service không cung cấp giao diện người dùng, mà chạy phía dưới, không cần tương tác với người dùng Một activity có thể khởi chạy một dịch vụ và tương tác với chúng
Một Service có thể được sử dụng theo 2 cách:
- Nó có thể được bắt đầu và được cho phép hoạt động cho đến khi một người nào đó dừng nó lại hoặc nó tự ngắt Ở chế độ này, nó được bắt đầu bằng cách gọi Context.startService() và dừng bằng lệnh
Context.stopService() Nó có thể tự ngắt bằng lệnh Service.stopSelf() hoặc Service.stopSelfResult() Chỉ cần một lệnh stopService() để ngừng Service lại cho dù lệnh startService() được gọi ra bao nhiêu lần
- Service có thể được vận hành theo như đã được lập trình việc sử dụng một Interface mà nó định nghĩa Các người dùng thiết lập một đường truyền tới đối tượng Service và sử dụng đường kết nói đó để thâm nhập vào Service Kết nối này được thiết lập bằng cách gọi lệnh
Context.bindService() và được đóng lại bằng cách gọi lệnh
Context.unbindService() Nhiều người dùng có thể kết nối tới cùng một thiết bị Nếu Service vẫn chưa được khởi chạy, lệnh bindService() có thể tùy ý khởi chạy nó Hai chế độ này thì không tách biệt toàn bộ Bạn
có thể kết nối với một Service mà nó đã được bắt đầu với lệnh
startService() Ví dụ, một Service nghe nhạc ở chế độ nền có thể được bắt đầu bằng cách gọi lệnh startService() cùng với một đối tượng Intent
mà định dạng được âm nhạc để chơi Chỉ sau đó, có thể là khi người sử dụng muốn kiểm soát trình chơi nhạc hoặc biết thêm thông tin về bài háthiện tại đang chơi, thì sẽ có một Activity tạo lập một đường truyền tới
Trang 11Service bằng cách gọi bindService() Trong trường hợp như thế này, stopService() sẽ không thực sự ngừng Service cho đến khi liên kết cuối cùng được đóng lại.
Giống như một Activity, một Service cũng có các phương thức chu kỳ thời gian mà bạn có thể cài đặt để kiểm soát những sự thay đổi trong trạng thái của nó Những những phương thức của Service thì ít hơn là của Activity – chỉ có 3- và chúng thì được sử dụng rộng rãi, không đượcbảo vệ
Ví dụ, một Service phát lại nhạc có thể tạo ra một luồng và bắt đầu chơi nhạc onCreate(),và sau đó luồng chơi nhạc sẽ dừng lại ở onCreate(), Active lifetime của một Service bắt đầu bằng một lệnh tới onStart() Đâylà phương thức được chuyển giao đối tượng Intent mà đã được thông qua để tới startService() Service âm nhạc sẽ mở đối tượng Intent
để quyết định xem sẽ chơi loại nhạc nào và bắt đầu phát nhạc
Không có callback tương đương nào cho thời điểm Service ngừng lại – không có phương thức onStop()
Các phương thức onCreate() và onDestroy() được gọi cho tất cả các Service dù chúng có được bắt đầu bằng Context.startService() hoặc Context.bindService() hay không Tuy nhiên thì, onStart() chỉ được gọi
ra đối với các Service bắt đầu bằng startService()
Nếu một Service cho phép những Service khác kết nối với nó thì sẽ có thêm các phương thức callback dành cho Service đó để thực hiên
IBinder onBind(Intent intent)
boolean onUnbind(Intent intent)
void onRebind(Intent intent)
Trang 12Hàm callback onBind() thông qua đối tượng Intent đã đựoc truyền đến bindService và onUnbind() được chuyển giao đối tượng mà đã được chuyển đến Nếu Service đang được chỉ định (binding), onBind() quay trở lại kênh thông tin mà người dùng sử dụng để tương tác với Service Phương thức onUnbind() có thể yêu cầu onRebind() được gọi nếu một người dùng kết nối với Service.
Biểu đồ dưới đây minh họa cho các phương thức callback giành cho một Service Mặc dù, nó phân tách các Service được tạo ra thông qua startService với các Service mà được tạo ra bằng bindService() Hãy nhớ rằng bất kì Service nào, cho dù nó được khởi tạo như thế nào thì nó vẫn có thể cho phép các người dùng kết nối tới nó một cách hiệu quả nhất, cho nên bất kì Service nào cũng có thể được chỉ định thông qua các các phương thức onBind()và onUnbind()
Trang 13Service LifeCycle
1.3.3 Content Provider
Content Provider quản lý việc chia sẻ dữ liệu Dữ liệu được lưu trữ trong cơ sở dữ liệu, thẻ nhớ, trên Web Thông qua content provider, những ứng dụng khác có thể truy cập được những dữ liệu này
1.3.4 Broadcast Receiver
Boardcast Receiver là thành phần đáp ứng lại những thông báo từ phía
hệ thống Ví dụ như những thông báo tắt màn hình, pin yếu, … Một ứngdụng cũng có thể tạo ra Broadcast Receiver, ví dụ như để thông báo đã download xong một file nào đó Tóm lại, Broadcast Receiver là thành
Trang 14phần giúp phát ra một sự kiện nào đó tới toàn bộ hệ thống, và một ứng dụng nào đó có thể nhận sự kiện này và xử lý tương ứng.
2 Kỹ thu t l p trình game trên Android ật lập trình game trên Android ật lập trình game trên Android.
Lập trình game về logic thì cũng giống như lập trình game trên các thiết bị khác Vấn đề ở đây là thiết bị di động Android có cấu hình khá thấp so với máy tính, màn hình nhiều kích cỡ khác nhau, việc nhập liệu cũng không linh hoạt bằng Vì vậy lập trình game trên Android cũng đòi hỏi xử lý nhiều vấn đề phát sinh Dưới đây là một số kỹ thuật về lập trình game trên Android
2.1 Th vi n đ h a OpenGL ư viện đồ họa OpenGL ệu ồ họa OpenGL ọa OpenGL
Như đã nói ở trên, thư viện đồ họa OpenGL là một thư viện đồ họa 3D, hỗ trợ tương tác trực tiếp với phần cứng, nhất là với bộ tăng tốc đồ họa Sử dụng thư viện đồ họa này, người dùng có thể tạo ra nhưng game có những hiệu ứng phức tạp, chất lượng hình ảnh cao, mà vẫn giữ được sử mượt mà cho game
OpengGL là một giao diện phần mềm độc lập với phần cứng (hardware – independent software interface) hộ trợ cho lập trình đồ họa Để làm được điều này, OpenGL không thực hiện các tác vụ thuộc về hệ điều hành cũng như không nhận dữ liệu nhập của người dùng (người dùng giao tiếp với OpenGL thông qua OpenGL API) Nó là lớp trung gian giữa người dùng vàphần cứng Nghĩa là nó giao tiếp trực tiếp với driver của thiết bị đồ họa.Trong bộ NDK của Android đã tích hợp sẵn OpenGL ES, nên ta chỉ việc include khi cần dùng đến những API của OpenGL
OpenGL vốn là một thư viện đồ họa 3D Nhưng ta cũng có thể dùng nó để
vẽ hình ảnh 2D
2.1.1 Khởi tạo OpenGL
Trang 15Để tương tác được với OpenGL, trước tiên ta phải khởi tạo thiết bị sử dụng OpenGL Để khởi tạo, bên phía Java, ta tạo ra một lớp
GL2JNIView thừa kế từ lớp GLSurfaceView GLSurfaceView là một
lớp được thừa kế từ lớp View, có tác dụng hiển thị hình ảnh được vẽ từ OpenGL
Trong hàm khởi tạo Activity, ta set view cho Activity là đối tượng GL2JNIView
mView = new GL2JNIView(getApplication(), 320, 480);
setContentView(mView);
Tiếp theo, ta gọi một số hàm cài đặt phép chiếu của OpenGL, để chuyển
từ môi trường 2D sang 3D Để tạo được hình ảnh 2D, ta sử dụng phép chiếu song song Trong hình bên dưới, bên trái là phép chiếu phối cảnh,
sẽ cho ta hình ảnh 3D, với cảm giác xa gần Còn hình bên phải là phép chiếu song song, sẽ loại bỏ cảm giác xa gần, cho ta hình ảnh 2D
Để tạo được hình ảnh này, ta dùng hàm
glOrthof(0.0f, width, height, 0.f, -100.0f, 100.0f);
Tiếp theo, ta sẽ cấu hình một số thuộc tính, enable một số chức năng như VertexArray (buffer chứa các đỉnh), TexureCoordinateArray (mảngchứa tọa độ texture), chức năng vẽ với kênh trong suốt alpha (Blend) Ngoài ra ta cũng disable một số chức năng không cần thiết trong vẽ hình2D như CullFace (loại bỏ hình ảnh dựa vào chiều của các vertex,
thường sử dụng trong 3D)
Trang 162.1.2 Texture
Texture là lớp vật liệu để phủ lên bề mặt 3D Nhưng ở đây khi ta vẽ hình ảnh 2D, thì texture chính là những hình ảnh cần vẽ Để load được texture, chúng ta cần phải có một ImageData, là một mảng byte màu Mảng này được đọc ra từ file ảnh, trong trường hợp này là file PNG
Sau khi khởi tạo texture, ta sẽ đưa mảng byte này gắn với texture đó
2.1.3 Vẽ texture
Để vẽ được texture lên, ta cần phủ texture này lên một mảng đỉnh Mảngđỉnh này tạo ra một hình có dạng hình chữ nhật, với kích thước bằng kích thước ta muốn vẽ lên màn hình Sau đó, khi muốn vẽ phần nào của texture lên màn hình, ta gán toạ độ tương ứng cho hình vẽ
2.2 Th vi n âm thanh OpenAL ư viện đồ họa OpenGL ệu
Thư viện âm thanh OpenAL giúp cho việc chơi âm thanh hiệu quả hơn Thư viện này giúp tương tác trực tiếp với phần cứng âm thanh, đặc biệt có khả năng tạo ra âm thanh vòm, làm cho game trở nên trung thực hơn
(0.0f, 0.0f) (1.0f, 0.0f) (1.0f, 0.0f) (1.0f,1.0f)
Trang 17Các hàm chức năng chính của OpenAL được đóng gói trong source object, audio buffer và single listener Source object chứa con trỏ tới buffer, vận tốc, vị trí và hướng của âm thanh Listener object cũng tương tự source object, nhưng là đối tượng người nghe Buffer chứa dữ liệu âm thanh, định dạng PCM Renderring engine cần thiết cho việc tính toán khoảng cách, tạohiệu ứng Doppler…
Trong NDK đã tích hợp các file header và thư viện OpenAL
2.2.1 Khởi tạo OpenAL
Để khởi tạo OpenAL, ta cần khởi tạo context cho device đó
_mContext = alcCreateContext(_mDevice, contextAttribs);
alcMakeContextCurrent(_mContext);
Hàm alcCreateContext sẽ tạo ra context cho thiết bị, trong đó _mDevice
là id của thiết bị âm thanh Thông thường điện thoại Android chỉ có mộtchip xử lý âm thanh Do đó ta gán _mDevice = 0
Hàm alcMakeContextCurrent sẽ gán context vừa tạo thành context hiện tại
2.2.2 Tạo đối tượng Audio
Để tạo được đối tượng Audio, ta cần có audio data Audio data sẽ được load từ file
Trước tiên ta load dữ liệu vào buffer:
alSourcei(sourceID, AL_BUFFER, bufferID);
2.2.3 Chơi âm thanh.
Trước khi chơi âm thanh, ta phải chỉ ra rằng ta đang sử dụng source đó Sau đó gọi hàm chơi âm thanh
if (isLoop) {
alSourcei(sourceID, AL_LOOPING, AL_TRUE);
} else {