Nghiên cứu đồ họa 2D, 3D và phát triển Game trên hệ điều hành Android

Do thời gian làm khóa luận có hạn, nên khóa luận cũng không thể tránh được những thiếu sót mà ta không thể lường trước được. Còn rất nhiều vấn đề mà ta cần phải giải quyết để cho khóa luận được tốt hơn: - Nghiên cứu sâu hơn về đồ họa 3D nói chung và trên hệ điều hành Android riêng. - Xây dựng thêm một số tính năng cần thiết cho trò chơi Bom Offline như + Các quái vật có khả năng tìm được đi ngắn nhất để di chuyển đến nhân vật. + Cần cải thiện tốc độ của trò chơi. + Thêm chức năng chơi trực tuyến. + Có thêm phần thách thức người chơi khác. + Có thể chơi thông qua giao tiếp Bluetooth. + Nâng cấp giao diện trò chơi. + Thương mại hóa sả phẩm. - Tiếp tục hoàn thiện trò chơi Line3D.

doc98 trang | Chia sẻ: lylyngoc | Lượt xem: 3405 | Lượt tải: 1download
Bạn đang xem trước 20 trang tài liệu Nghiên cứu đồ họa 2D, 3D và phát triển Game trên hệ điều hành Android, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
etShadowLayer(50, 0, +50, Color.YELLOW); p.setStyle(Style.STROKE); canvas.drawPath(circle, p); //Vẽ hình chữ nhật p.setColor(Color.BLUE); Rect r = new Rect(); r.set(200, 200, 50, 30); canvas.drawRect(r, p); //Vẽ 1 bức ảnh p.reset(); Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.bomb); canvas.drawBitmap(bitmap, 20, 300, p); super.onDraw(canvas); } } Để vẽ 1 đối tượng đồ họa trong Android ta cần phải khai báo đối tượng Paint, trong lớp Customview ở dòng 22 chúng ta đã khai bao đối tượng Paint. Để vẽ 1 đường thẳng với màu đỏ ta đặt màu đỏ cho đối tượng Paint với câu lệnh dòng 24. Muốn vẽ 1 đường thẳng ta dùng phương thức drawLine của đối tượng Canvas, với dòng 25 ta sẽ vẽ 1 đường thẳng bắt đầu từ vị trí (0,10) cho đến vị trí kết thúc là (100, 10). Muốn vẽ 1 đường tròn thì ta dùng phương thức drawPath nhưng trước đó ta phải khai báo đối tượng circle, đối tượng này thể hiện 1 đường tròn. Muốn màu đổ bóng là màu vàng cho đặt màu vàng cho biến p tại dòng 29. Như vậy là ta vẽ được đường tròn với đổ bóng màu vàng. Để vẽ hình chữ nhật ta khai báo thêm đối tượng hình chữ nhật, dòng 35 khai báo 1 đối tượng hình chữ nhật, muốn hình chữ nhật có màu xanh ta đặt màu cho biến p là màu BLUE (dòng 34), muốn vẽ hình chữ nhật ta dùng phương thức drawRect. Tiếp theo là vẽ 1 bức ảnh: Muốn vẽ 1 bức anh ta cần khai báo thêm đối tượng Bitmap, đối tượng này tải dữ liệu từ thư mục drawble với đoạn mã dòng 40, muốn vẽ lên màn hình ta dùng phương thức drawBitmap của đối tượng canvas. Cuối cùng ta đã vẽ được 1 số thành phần cơ bản của Android. Kết quả chương trình trên như sau. Xem hình 11. Đồ họa 3D trong Android. 3.3.1 Một số thành phần trong đồ họa 3D. Android cung cấp cho ta gói thư viện OpenGL cụ thể ở đây là OpenGL ES API. OpenGL là một nền tảng rất tốt, nó giúp tăng tốc đồ họa 1 cách đáng kể. Ngay từ khi ra đời với phiên bản Android 1.0 thì Android đã hỗ trợ OpenGL 1.0. Đến phiên bản Android 2.2 API 8 thì Android đã hộ trợ thêm OpenGL 2.0, với việc hộ trợ thêm OpenGL 2.0 thì hệ điều hành này ngày càng được mọi người quan tâm hơn. Sau đây là 1 số thành phần đồ họa 3D quan trọng của hệ điều hành này. GLSurfaceView: Đây là nơi bạn có thể vẽ và thao tác đối tượng bằng cách gọi OpenGL API và các nó chức năng giống như một SurfaceView. Bạn có thể sử dụng lớp này bằng cách tạo ra 1 đối tượng thể hiện GLSurfaceView và thêm phần Renderer của bạn vào. Tuy nhiên nếu bạn muốn bắt sự kiện cảm ứng trên màn hình thì bạn phải mở rộng lớp này và cài đặt sự kiến lắng nghe. GLSurfaceView.Renderer: Giao diện này định nghĩa các phương thức được yêu cầu để vẽ các thành phần đồ họa của một đối tượng GLSurfaceView. GLSurfaceView.Renderer yêu cầu cần phải cài đặt các phương thức sau: onSurfaceCreated(): Phương thức này chỉ được hệ thống gọi 1 lần duy nhất, nó được gọi khi tạo ra GLSurfaceView. Phương thức này thường để thực hiện 1 số cài đặt cần thiết như là cài đặt các thuộc tính khi hiện thị giao diện đồ họa như chiều cao, chiều rộng… onDrawFrame(): Hệ thống sẽ gọi phương thức này mỗi khi vẽ lại GLSurfaceView. onSurfaceChanged(): Hệ thống sẽ gọi phương thức này khi GLSurfaceView có sự thay đổi, bao gồm việc thay đổi chiều cao, rộng của màn hình và sự thay đổi về chiều của màn hình (Nằm ngang hay dọc). Một số gói trong thư viện OpenGL: Gói OpenGL API 1.0: + Android.opengl: Gói này cung cấp các giao diện tĩnh và nó thực hiện tốt hơn gói  javax.microedition.khronos. GLES10 GLES10Ext GLES11 GLES10Ext + javax.microedition.khronos.opengles : Gói này cung cấp các đối tượng chuẩn của opengl 1.0 GL10 GL10Ext GL11 GL11Ext GL11ExtensionPack OpenGL ES 2.0 API Class + Android.opengl.GLES20: Gói này cung cấp giao diện OpenGL 2.0 và bắt đầu có mặt từ Android 2.2 (API 8). Ngoài các thành phần trên thì Android còn cung cấp rất nhiều các đối tượng khác, để tìm hiểu thêm ta có thể tìm hiểu tại đường dẫn sau: Chương trình minh họa. Để hiểu rõ được cách thức hoạt động của các đối tượng đồ họa 3D trong Android ta cùng xét 1 ví dụ đơ giản là hiện thị khung hình và thay đổi màu nền. Đầu tiên ta tạo 1 project với tên là TestAndroid3D. Trong project thì activity chính của chúng ta có tên là TestAndroid3Dactivity.java, tiếp sau đó ta tạo thêm 2 lớp nữa lần lượt là MyGLSurfaceView.java, MyGLSurfaceViewRenderer.java. Nội dung chi tiết các lớp trên là: Lớp TestAndroid3Dactivity.java. package TestAndroid3D.gioi; import Android.app.Activity; import Android.os.Bundle; public class TestAndroid3DActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); MyGLSurfaceView myGLSurfaceView = new MyGLSurfaceView(this); setContentView(myGLSurfaceView); } } Lớp này sẽ được gọi đầu tiên khi chương trình chạy và nó thực hiện chức năng cho hiện thị đối tượng MyGLSurfaceView. Lớp MyGLSurfaceView.java package TestAndroid3D.gioi; import Android.content.Context; import Android.opengl.GLSurfaceView; import Android.view.MotionEvent; public class MyGLSurfaceView extends GLSurfaceView{ MyGLSurfaceViewRenderer myGLSurfaceViewRenderer; public MyGLSurfaceView(Context context) { super(context); myGLSurfaceViewRenderer = new MyGLSurfaceViewRenderer(); setRenderer(myGLSurfaceViewRenderer); } public boolean onTouchEvent(final MotionEvent event) { queueEvent(new Runnable() { public void run() { //Bắt sự kiện và làm thay đổi màu nền myGLSurfaceViewRenderer.setColor(event.getX() / getWidth(), event.getY() / getHeight(), 1.0f); } }); return true; } } Khi ta muốn bắt sự kiện cảm ứng của thiết bị thì ta bắt buộc phải có thêm phương thức onTouchEvent. Lớp MyGLSurfaceViewRenderer.java package TestAndroid3D.gioi; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import Android.opengl.GLSurfaceView; public class MyGLSurfaceViewRenderer implements GLSurfaceView.Renderer{ private float red = 0.9f; private float green = 0.2f; private float blue = 0.2f; @Override public void onDrawFrame(GL10 gl) { // TODO Auto-generated method stub gl.glClearColor(red, green, blue, 1.0f); gl.glClear(GL10.GL_COLOR_BUFFER_BIT); } @Override public void onSurfaceChanged(GL10 gl, int w, int h) { // TODO Auto-generated method stub gl.glViewport(0, 0, w, h); } @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { // TODO Auto-generated method stub } //Phương thức đặt lại màu nền public void setColor(float r, float g, float b) { red = r; green = g; blue = b; } } Trong lớp này ta xây dựng thêm phương thức setColor nhằm mục đích thay đổi màu màn hình nền. Kết quả của chương trình TestAndroid3D như sau. Xem hình 12. Mỗi khi ta chạm vào màn hình hiện thị của thiết bị thì màn hình hiện thị sẽ thay đổi màu nền theo giá trị mà ta chạm trên màn hình. Chương trình minh họa. Chương trình chính (2D). Mục đích chính của chương trình minh họa. Để có thể hiểu rõ về các thành phần đồ họa của hệ điều hành Android thì chúng ta cùng xây dựng 1 chương trình hoàn chỉnh. Chương trình sẽ sử dụng các đối tượng đồ họa 2D của Android. Ý tưởng thực hiện. Xây dựng Game BomOffline. Ý tưởng: Game BomOffline là Game có thể chơi không cần phải kết nối với sever mà vẫn chơi được Game. Game theo thể loại chiến thuật, đối với người chơi thì người chơi phải thực hiện các hành động sau. + Di chuyển nhân vật trên màn hình. + Tìm kiếm những chiếc hộp có chứa các quà tặng. + Đặt bom để tiêu diệt các quái vật. Miêu tả quá trình chơi Game: Lúc đầu khi người chơi vào chơi thì người chơi được cung cấp 1 quả bom, mức độ bom ban đầu là 1, số lượt chơi lúc đầu là 3. Người chơi điều khiển nhân vật di chuyển theo 4 hướng trái, phải, lên, xuống thông qua giao điện điều khiển thể hiện trên thiết bị. Người chơi luôn phải tránh xa các quái vật, nếu người chơi di chuyển chạm vào quái vật thì người chơi sẽ bị trừ lượt chơi. Người chơi cần phải đặt bom để tiêu diệt quái vật, mỗi quả bom được đặt xuống thì sau 3 giây thì bom sẽ tự nổ. Mỗi 1 quái vật bị chết ( biến mất ) thì số điểm của người chơi được tăng thêm 50 điểm vào tổng số điểm. Nếu người chơi di chuyển và chạm vào hộp quà thì người chơi có thể nhận được 1 trong 3 loại quà. Loại 1 là tăng thêm 1 lượt chơi, loại 2 là tăng thêm 1 cấp độ bom, loại 3 là tăng thêm số quả bom. Hộp quà xuất hiện ngẫu nhiên trên màn hình, mỗi hộp quà thì hiện thị trong thời gian ngẫu nhiên trong khoảng 5 đến 20 giây. Khi nhân và quái vật di chuyển thì có một số vùng có các đồ vật thì nhân vật và quái vật sẽ không thể đi qua được và bắt buộc phải đi vòng qua các vật này. Ý tưởng về cách xây dựng các giao diện và chức năng cho người dùng: + Về giao diện sẽ có các giao diện chính sau: Giao diện Menu chính (MainMenu) Giao diện giới thiệu cách chơi Giao diện điều khiển nhân vật (giao diện chính cho phép điều khiển nhân vật đặt bom để tiêu diệt quái vật) Giao diện hiện thị khi người chơi bị thua cuộc Giao diện khi người chơi dành chiến thắng Giao diện khi người chơi được lưu lại số điểm Giao diện xem danh sách tốp 10 người có điểm cao nhất. + Các chức năng cần thiết trong từng giao diện Giao diện Menu chính: + Chức năng chơi từ đầu. + Chức năng hiện thị thông tin về người phát triển Game. + Chức năng yêu cầu thoát khỏi Game. + Chức năng cho phép bật tắt âm thanh. Giao diện giới thiệu: + Cho phép chạm vào 1 đối tượng nào đó để chuyển sang giao diện chính. + Chức năng yêu cầu thoát khỏi Game. Giao diện điều khiển nhân vật: + Chức năng hiện thị số điểm người chơi đang có. + Chức năng hiện thị số lượt chơi. + Chức năng cho phép bật tắt âm thanh trong Game. + Chức năng cho phép tạm dừng Game. Đối với chức năng này thì khi hiện thị ra menu thì có chức năng là tiếp tục chơi, chơi lại từ đầu, quay lại menu chính và chức năng thoát khỏi Game. + Chức năng hiện thị vùng điều khiển nhân vật. + Chức năng hiện thị mức mà người chơi đang chơi (level) + Chức năng hiện thị số lượng quả bom mà người chơi đang có. + Chức năng hiện thị cấp độ bom. + Chức năng yêu cầu thoát khỏi Game. Giao diện hiện thị khi người chơi bị thua: + Chức năng chơi lại từ đầu. + Chức năng quay lại menu chính. + Chức năng yêu cầu thoát khỏi Game. Giao diện khi người chơi thắng cuộc: + Chức năng chuyển tới giao diện lưu điểm. Giao diện khi lưu điểm: + Chức năng lưu lại số điểm. + Chức năng xem danh sách điểm. + Chức năng chơi lại từ đầu. + Chức năng yêu cầu thoát khỏi Game. Giao diện xem danh sách điểm cao: + Chức năng hiện thị 10 người có số điểm cao nhất. + Chức năng tắt bỏ phần hiện thị. + Chức năng định dạng lại danh sách (xóa dữ liệu cũ). Phân tích chương trình. Sơ đồ hoạt động của Game. Xác định actor và mô hình use case. Danh sách Actor STT TÊN ACTOR Ý NGHĨA/GHI CHÚ 1 Người dùng Người sử dụng điện thoại chơi Game Sơ đồ Use Case Bảng danh sách UseCase STT TÊN USE CASE Ý NGHĨA/GHI CHÚ 1 Bắt đầu chơi Chọn Activity MainGameActivity 2 Tạm dừng Game Chọn biểu tượng tạm dừng 3 Điều khiển nhân vật Xác định hướng đi của nhân vật 4 Bật / Tắt âm thanh Chọn biểu tượng bật tắt âm thanh 5 Đặt bom Đặt bom tại vị trí hiện tại của nhân vật 6 Thoát Thoát khỏi Game Đặc tả các Use Case. Đặc tả use case Bất đầu chơi: Tóm tắt: Khi người dùng chọn Activity MainGameActivity trên menu chính. Dòng sự kiện: Dòng sự kiện chính: + Trên menu chính người chơi chọn chơi luôn + Chuyển sang và hiện thị Activity MainGameActivity + Kết thúc use case Dòng sự kiện khác: Không có Các yêu cầu đặc biệt: Không có Trạng thái của hệ thống khi bắt đầu use case: Khi biểu tượng trên menu chơi luôn được chuyển sang trạng thái được chọn. Khi menu chính đang được hiện thị. Trạng thái của hệ thống sau khi thực hiện use case: Hiện thị Activity MainGameActivity Điểm mở rộng: Không có. Đặc tả use case Tạm dừng Game: Tóm tắt: Khi người dùng chọn biểu tượng tạm dừng trên màn hình chơi Game. Dòng sự kiện: Dòng sự kiện chính: + Trên giao diện chơi Game người dùng chọn vào biểu tượng tạm dừng Game. + Hiện thị giao diện menu phụ. + Kết thúc use case. Dòng sự kiện khác: + Chọn tiếp tục chơi lại để chơi lại. + Chọn chơi lại từ đầu để bắt đầu 1 lượt chơi khác. + Chọn quay lại menu chính để quay lại menu chính. + Chọn thoát để quay lại màn hình Game. Các yêu cầu đặc biệt: Không có. Trạng thái của hệ thống khi bắt đầu use case: Khi đang ở giao diện chơi Game. Trạng thái của hệ thống sau khi thực hiện use case: Hiện thị menu phụ Điểm mở rộng: Khi hiện thị menu phụ thì người chơi phải chọn 1 trong 4 chức năng mà menu phụ hiện thị lên. Đặc tả use case Điều khiển nhân vật: Tóm tắt: Người chơi chọn hướng để di chuyển nhân vật trên giao diện chơi Game. Dòng sự kiện: Dòng sự kiện chính: + Trên giao diện Game người chơi chạm vào vùng điều khiển và di chuyển theo hướng mà nhân vật muốn di chuyển. + Kết thúc use case. Dòng sự kiện khác: Các yêu cầu đặc biệt: Không có Trạng thái của hệ thống khi bắt đầu use case: Khi đang ở giao diện chơi Game. Trạng thái của hệ thống sau khi thực hiện use case: Nhân vật sẽ di chuyển theo các hướng mà người chơi điều khiển. Khi người chơi không chạm vào vùng điều khiển thì nhân vật trở lại trạng thái ban đầu. Khi di chuyển nhân vật thì nhân vật sẽ không đi qua các vật cản. Khi nhân vật va chạm với các quái vật thì nhân vật sẽ bị khởi tạo lại vị trí. Khi người chơi va chạm với bom khi đang nổ thì nhân vật cũng bị khởi tạo lại vị trí ban đầu. Điểm mở rộng: Không có. Đặc tả use case Bật / Tắt âm thanh: Tóm tắt: Khi người chơi chọn biểu tượng âm thanh trên giao diện chơi chính. Dòng sự kiện: Dòng sự kiện chính: + Trên giao diện Game thì người chơi chọn vào biểu tượng âm thanh. + Kết thúc use case Dòng sự kiện khác: Không có Các yêu cầu đặc biệt: Không có Trạng thái của hệ thống khi bắt đầu use case: Khi đang ở giao diện chơi Game. Trạng thái của hệ thống sau khi thực hiện use case: Thay đổi trạng thái hiện thị của biểu tượng. Điểm mở rộng: Không có. Đặc tả use case Đặt bom: Tóm tắt: Khi người chơi chọn biểu tượng quả bom trên giao diện chơi Game. Dòng sự kiện: Dòng sự kiện chính: + Trên giao diện Game thì người chơi chọn vào biểu tượng quả bom. + Kết thúc use case Dòng sự kiện khác: Không có Các yêu cầu đặc biệt: Không có Trạng thái của hệ thống khi bắt đầu use case: Khi đang ở giao diện chơi Game. Trạng thái của hệ thống sau khi thực hiện use case: Hiện thị trên giao diện Game 1 quả bom được đặt tại vị trí mà nhân vật đang đứng. Điểm mở rộng: Không có. Đặc tả use case Thoát: Tóm tắt: Khi người chơi bấm phím back trên thiết bị. Dòng sự kiện: Dòng sự kiện chính: + Người chơi bấm phím back trên thiết bị. + Kết thúc use case Dòng sự kiện khác: Không có Các yêu cầu đặc biệt: Không có Trạng thái của hệ thống khi bắt đầu use case: Khi trò chơi đang trong giao diện chơi Game. Trạng thái của hệ thống sau khi thực hiện use case: Hiện thị thông báo hỏi người chơi xem có muốn thoát hay không. Điểm mở rộng: Không có. Thiết kế chương trình. 3.4.1.3.3.1 Thiết kế kiến trúc hệ thống. Hệ thống của chương trình được chia thành 2 tầng. + Tầng hiện thị giao diện. + Tầng quản lý các đối tượng liên quan. Activity Mô hình: BUS THÀNH PHẦN DIỄN GIẢI Activity Thành phần này gồm có các lớp để hiện thị giao diện Game. BUS (Business Logic Layer) Quản lý việc kiểm tra các yêu cầu nghiệp vụ, các phương thức. 3.4.1.3.3.2 Mô tả chi tiết các thành phần. Các lớp Activity. Gồm có 2 gói là Bom.gioi.MainGame và Bom.gioi. LỚP ĐỐI TƯỢNG DIỄN GIẢI ChienThang Hiện thị thông tin khi người chơi chiến thắng. Gameover Hiện thị giao diện khi người chơi thua cuộc. HuongDan Hiện thị thông tin chi tiết về giao diện Game. Luudiem Cho người chơi lưu lại số điểm của mình khi số điểm người đó nằm trong tốp 10 người chơi có điểm cao nhất. MainGameActivity Là nơi cho người chơi điều khiển nhân vật chính. BomActivity Là Menu chính, cho phép chọn các chức năng. Các lớp thuộc BUS. Các lớp thuộc BUS gồm có các gói sau: Bom.gioi.BaseAndengine. Bom.gioi.ClassStatic. Bom.gioi.Bom. Bom.gioi.Database. Bom.gioi.Dialog. Bom.gioi.Maps Bom.gioi.Other. Bom.gioi.Player. Bom.gioi.Quaivat. Bom.gioi.Sound. Bom.gioi.Tools. LỚP ĐỐI TƯỢNG DIỄN GIẢI MultiTouch Thực hiện kiểm tra xem thiết bị có hộ trợ màn hình cảm ứng đa điểm không. MultiTouchController Sử lý các sự kiện cảm ứng đa điểm ControlerStatic Lưu trữ các biến điều khiển dưới dạng static (biến tĩnh) ScreenStatic Lưu trữ các giá trị định nghĩa liên quan đến màn hình hiện thị Bom Thể hiện 1 quả bom, trong 1 quả bom thì có nhiều đối tượng No No Thể hiện 1 vụ nổ. QuaBom Là lớp thể hiện sự nổ của lớp No và hiện thị bom của lớp Bom Database Thao tác với csdl để thêm, sửa, xóa, cập nhật các thông tin cần lưu trữ trong Game DialogInfor Hiện thị thông tin về Game và người viết DialogExit Hiện thị thông báo hỏi xem có muốn thoát hay không DialogXemDiem Hiện thị danh sách 10 người có điểm cao nhất Maps Tải Maps từ thư mục Sound Chạy âm thanh nhạc nền Player Hiện thị nhân vật và sử lý các vấn đề liên quan đến nhân vật StatusPlayer Lưu các giá trị về trạng thái của nhân vật chính Quaivat_1 Thể hiện 1 loại quái vật Quaivat Bao gồm nhiều Quaivat_1, gồm có nhiều phương thức để quản lý Quaivat_1 3.4.1.3.3.3 Một số quan hệ giữa các đối tượng. Quan hệ giữa các đối tượng trong gói Bom Quan hệ giữa các đối tượng trong gói Player Quan hệ giữa các đối tượng trong gói Quaivat Thiết kế giao diện người dùng. Giao diện menu chính. Xem hình 13. Giao diện hiện thị thông tin tác giả. Xem hình 14. Giao diện hiện thị xác minh thoát. Xem hình 15. Giao diện hiện thị phần giới thiệu. Xem hình 16. Giao diện hiện thị khi tải dữ liệu. Xem hình 17. Giao diện chính của Game. Xem hình 18. Giao diện menu phụ. Xem hình 19. Giao diện khi người chơi thua cuộc. Xem hình 20. Giao diện khi người chơi thắng cuộc. Xem hình 21. Giao diện lưu điểm. Xem hình 22. Giao diện hiện thị danh sách điểm. Xem hình 23. Thiết kế các thuật toán. Thuật toán xác định vị trí pX,pY có nằm trong 1 vùng của Maps. Xác định dữ liệu đầu vào gồm có: + Đối tượng TMXTiledMap + Đối tượng TMXTile + Vị trí pX kiểu float + Vị trí pY kiểu float Xác định đầu ra Đầu ra dạng đúng/sai (true/false) + Nếu tạo độ pX, pY không nằm trong TMXTile thì ta trả về kết quả là sai (false). + Nếu tọa độ pX, pY thuộc trong TMXTile thì ta trả về kết quả là đúng (true). Viết thuật toán bằng ngôn ngữ java. public boolean collidesWith(TMXTiledMap mTMXTiledMap, TMXLayer VatCanTMXLayer, float pX, float pY){ TMXTile mTMXTile = VatCanTMXLayer.getTMXTileAt(pX,pY); try{ if(mTMXTile == null){} else{ TMXProperties mTMXProperties= mTMXTile.getTMXTileProperties(mTMXTiledMap); TMXTileProperty mTMXTileProperty = mTMXProperties.get(0); } return true; }catch(Exception e){ return false; } } Ví dụ minh họa thuật toán: Giả sử ta có một map như sau. Xem hình 24. Với đối tượng TMXTiledMap thì lưu trữ toàn bộ các hình ảnh để tạo ra map và đối tượng này cũng chứa luôn cả đối tượng TMXLayer. Đối tượng TMXLayer trong hình vẽ trên là các viên gạch. Để kiểm tra xem vị trí pX, pY có nằm trên đối tượng TMXLayer hay không ta phải xác định xem vị trí đó có tồn tại 1 TMXTile. Nếu tồn tại thì giá trị TMXTile sẽ không bằng null. Ngược lại là null tức là vị trí pX, pY nằm ngoài TMXLayer. Ảnh thể hiện điểm pX, pY nằm trên đối tượng TMXLayer. Xem hình 25. Ảnh thể hiện điểm pX, pY nằm ngoài đối tượng TMXLayer. Xem hình 26. Thuật toán xác định va chạm giữa 2 sprite. Xác định dữ liệu đầu vào. + AnimatedSprite A + AnimatedSprite B Xác định dữ liệu đầu ra. + Dữ liệu trả ra dạng đúng/sai (true/false). Viết thuật toán bằng ngôn ngữ java. public boolean vaCham(AnimatedSprite A, AnimatedSprite B){ this.A.setPosition(A.getX() + 8,A.getY() + 8); this.B.setPosition(B.getX() + 8,B.getY() + 8); if(A.collidesWith(B)) return true;//Có va chạm return false;//Không va chạm } Với thuật toán này điều kiện ban đầu là phải có 2 AnimatedSprite A, B. Mỗi 1 đối tượng AnimatedSprite thì được thể hiện bằng 1 hình chữ nhật. Nhưng hình ảnh thể hiện nhân vật thì có chiều cao và chiều rộng nhỏ hơn hình chữ nhật, nếu ta cứ so sánh bình thường thì kết quả cho thấy sự va chạm là không chính xác, để va xác định va chạm 1 cách chính xác hơn thì ta cần phải tính toán lại chiều cao và chiều rộng của AnimatedSprite để so sánh. Ví dụ minh họa: Giả sử ta có 1 AnimatedSprite với chiều cao và chiều rộng như hình vẽ sau. Kích thước của AnimatedSprite này là 32x32. Nhưng nhân vật nằm trong hình chữ nhật này lại nhỏ hơn nhiều so với hình chữ nhật. Hình vẽ thể hiện nhân vật nằm trong AnimatedSprite nhưng lại nhỏ hơn hình chữ nhật. Hình màu đỏ tượng trưng cho nhân vật. Như vậy ta cần so sánh giữa các nhân vật chứ không phải so sánh giữa các hình chữ nhật của các AnimatedSprite. Viết chương trình. Hiện thị menu chính. Chuẩn bị. Một số hình ảnh cần thiết để tạo giao diện. + Ảnh nền: Xem hình 27. + 3 ảnh thể hiện các chức năng chơi, hiện thị thông tin, yêu cầu thoát khỏi Game. Xem hình 28. Viết mã lệnh. Trích đoạn tạo ra hiệu ứng các ảnh trong menu xoay tròn. final Handler handler = new Handler() { @Override public void handleMessage(Message msg) { if(nhac_nen.complet && ControlerStatic.SOUND){ nhac_nen.complet = false; nhac_nen.replay(); System.out.println("replay"); } switch (index) { case 0: ImageButton_exit.clearAnimation(); ImageButton_infor.clearAnimation(); ImageButton_play.startAnimation(animation_xoay); break; case 1: ImageButton_play.clearAnimation(); ImageButton_infor.clearAnimation(); ImageButton_exit.startAnimation(animation_xoay); break; case 2: ImageButton_exit.clearAnimation(); ImageButton_play.clearAnimation(); ImageButton_infor.startAnimation(animation_xoay); break; default: break; } super.handleMessage(msg); } }; Thread th = new Thread(new Runnable() { @Override public void run() { while (true) { try { Thread.sleep(8000); } catch (InterruptedException e) { e.printStackTrace(); } index++; if (index > 2) index = 0; Message msg = handler.obtainMessage(); handler.sendMessage(msg); } } }); th.start(); Trích đoạn kiểm tra xem CSDL đã tồn tại hay chưa. public void csdlMau() { // Lần đầu khi bắt đầu chơi // Giả lập dữ liệu mẫu db = new Database(this); // Dữ liệu mẫu gồm 10 người try { db.open(); Cursor c = db.getAllRows(); if (!c.moveToFirst()) {// Nếu CSDL chưa có thì thêm 10 hàng để tạo ra dữ liệu mẫu. db.isertRow("Player", 100); db.isertRow("Player", 100); db.isertRow("Player", 100); db.isertRow("Player", 100); db.isertRow("Player", 100); db.isertRow("Player", 100); db.isertRow("Player", 100); db.isertRow("Player", 100); db.isertRow("Player", 100); db.isertRow("Player", 100); } c.close(); db.close(); } catch (SQLiteException e) { e.printStackTrace(); } } Hiện thị phần giới thiệu về giao diện chính. Để hiện thị giao diện giới thiều về giao diện chính thì ta chỉ cần hiện thị bức ảnh và cho phép người chơi chọn và chuyển sang phần giao diện chính của trò chơi. Mã lệnh: package Bom.gioi.MainGame; import Bom.gioi.R; import Android.app.Activity; import Android.content.Intent; import Android.os.Bundle; import Android.view.View; import Android.view.Window; import Android.view.WindowManager; import Android.widget.ImageView; public class Huongdan extends Activity{ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.huongdan); ImageView imageView = (ImageView)findViewById(R.id.button1); imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { Intent i = new Intent(Huongdan.this, MainGameActivity.class); Huongdan.this.startActivity(i); Huongdan.this.finish(); } }); } } Giao diện chơi Game. Chuẩn bị. Chuẩn bị một số hình ảnh. + Hình trái tim thể hiện số lượt chơi. + Hình thể hiện trạng thái tạm dừng. + Hình thể hiện quả bom. (3 hình trên xem hình 29.) Xem hình 29. Viết mã lệnh. Trích doạn mã vòng lặp để cập nhật các đối tượng. IUpdateHandler UpdateHandler = new IUpdateHandler(){ public void reset() { } public void onUpdate(float pSecondsElapsed) { if(!OVERGAME){ if(!WIN){ try { Thread.sleep(20);//Ngủ trong 20ms for(int i=0;i<MyQuaivat.max_quai;i++){ if(MyQuaivat.quaivat_1[i].Quaivat_1_AnimatedSprite.isVisible()) MyQuaivat.quaivat_1[i].moveRandom();//Nếu quái vật nào mà ở trạng thái ẩn thì ta cho hiện thị lên. //Với điều kiện là số quái vật cần phải tiêu diệt lớn hơn so với tổng số quái vật có if(SO_QUAI_CAN_TIEU_DIET - DEM_SO_QUAI_BI_TIEU_DIET >= MAX_SO_QUAI_VAT){ if(!MyQuaivat.quaivat_1[i].Quaivat_1_AnimatedSprite.isVisible()) MyQuaivat.quaivat_1[i].bool_reset = true; } if((SO_QUAI_CAN_TIEU_DIET*50) - diem1 >= (MAX_SO_QUAI_VAT*50)){ if(!MyQuaivat.quaivat_1[i].Quaivat_1_AnimatedSprite.isVisible()) MyQuaivat.quaivat_1[i].bool_reset = true; } MyQuaivat.quaivat_1[i].reset();//Kiểm tra xem quái vật có va chạm với player không. Nếu có va chạm thì player sẽ bị reset vàbị mất 1 mạng if(vaCham( MyQuaivat.quaivat_1[i].Quaivat_1_AnimatedSprite, MyPlayer.player_AnimatedSprite) && MyQuaivat.quaivat_1[i].Quaivat_1_AnimatedSprite.isVisible()){ if(ControlerStatic.SOUND) sound_resetplayer.play(); //Có va chạm //Khởi tạo lại vị trí MyPlayer.moveXY(64, 64); //Bị trừ đi 1 lượt chơi MyPlayer.setHeart(MyPlayer.getHeart() - 1); //Cập nhật và hiện thị số mạng còn lại TextHeart.setText(String.valueOf(MyPlayer.getHeart())); } } try{ if(ArrayListQuaBom.size() != 0){ for(QuaBom quabom : ArrayListQuaBom){ if(!quabom.no_end){ quabom.delayNo(); if(quabom.begin_no){//Khi quả bom đang trong trạng thái nổ thì kiểm tra xem có quái vật nào //va chạm với bom không. Nếu quái vật va chạm với quả bom thì quái vật đó sẽ bị biến mất for(int i=0;i<MyQuaivat.max_quai;i++){ if(vaCham(quabom, MyQuaivat.quaivat_1[i].Quaivat_1_AnimatedSprite)){ //Mỗi 1 quái vật bị chết sẽ cộng thêm 50 điểm vào số điểm if(MyQuaivat.quaivat_1[i].Quaivat_1_AnimatedSprite.isVisible()){ DIEM = DIEM + 50; diem1 = diem1 + 50; DEM_SO_QUAI_BI_TIEU_DIET++; if(SO_QUAI_CAN_TIEU_DIET == DEM_SO_QUAI_BI_TIEU_DIET){ //Đã tiêu diệt xong quái vật/ //Hiện thông báo vượt qua level và chuyển sang level tiếp theo System.out.println("Thành công. Đã tiêu diệt xong."); WIN = true;} if(SO_QUAI_CAN_TIEU_DIET - DEM_SO_QUAI_BI_TIEU_DIET >= MAX_SO_QUAI_VAT){ if(!MyQuaivat.quaivat_1[i].Quaivat_1_AnimatedSprite.isVisible()) MyQuaivat.quaivat_1[i].bool_reset = true; } if((SO_QUAI_CAN_TIEU_DIET*50) - diem1 >= (MAX_SO_QUAI_VAT*50)){ if(!MyQuaivat.quaivat_1[i].Quaivat_1_AnimatedSprite.isVisible()) MyQuaivat.quaivat_1[i].bool_reset = true; } } MyQuaivat.quaivat_1[i].Quaivat_1_AnimatedSprite.setVisible(false); MyQuaivat.quaivat_1[i].Quaivat_1_AnimatedSprite.setPosition(-100, -100); //Hiện thị điểm TextDiem.setText(String.valueOf(DIEM), true);//Nếu nhiều hơn 10 ký tự thì hiện thị ...} //Kiểm tra với player. Nếu chạm vào player thì player sẽ khởi tạo lại vị trí ban đầu if(vaCham(quabom, MyPlayer.player_AnimatedSprite)){ if(ControlerStatic.SOUND) sound_resetplayer.play(); MyPlayer.moveXY(64, 64); //Khi bị chết thì ta trừ đi 1 mạng MyPlayer.setHeart(MyPlayer.getHeart() - 1); //trừ đi 1 cấp bom if(MyPlayer.getCurrent_cap_quabom() - 1 != 0) MyPlayer.setCurrent_cap_quabom(MyPlayer.getCurrent_cap_quabom() - 1); //trừ đi 1 quả bom if(MyPlayer.getCurrent_quabom() - 1 != 0) MyPlayer.setCurrent_quabom(MyPlayer.getCurrent_quabom() - 1); } } } }else{ ArrayListRemoveQuaBom.add(quabom); } } }}catch(Exception e){ System.out.println("CÓ thể có lỗi: "+e.toString()); } if(ArrayListRemoveQuaBom.size() != 0 && ArrayListQuaBom.size() != 0){ for(QuaBom quabom : ArrayListRemoveQuaBom){ ArrayListQuaBom.remove(quabom); ArrayListRemoveQuaBom.removeAll(ArrayListRemoveQuaBom); } //Text current_quabom_ChangeableText.setText(String.valueOf(MyPlayer.current_quabom - ArrayListQuaBom.size())); //Cập nhật và hiện thị số mạng còn lại TextHeart.setText(String.valueOf(MyPlayer.getHeart())); //Cập nhật và hiện thị số cấp bom TextCapBom.setText(String.valueOf(MyPlayer.getCurrent_cap_quabom())); if(MyPlayer.getHeart() <= 0){ //Game over System.out.println("GameOver"); OVERGAME = true;//OVERGAME } MyHopqua.hienThi(mTMXTiledMap, VatCanTMXLayer); MyHopqua.collidesWith(MyPlayer); checkIsVisiable();//Cứ sau 15s check 1 lần } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } //=============KHI NGƯỜI CHƠI DÀNH CHIẾN THẮNG=============== }else{ //Vượt qua level if(!NEXT_LEVEL){ TiepTucSprite.setVisible(true); float pX = TiepTucSprite.getX()+1; if(pX > 180) pX = ScreenStatic.CAMERA_WIDTH/2 - TiepTucSprite.getWidth()/2; TiepTucSprite.setPosition(pX, TiepTucSprite.getY()); }else{ } } } //OVERGAME else{//Kiểm tra xem số điểm của người chơi có cao hơn số điểm của những người chơi khác không //Nếu cao hơn ta chuyển qua phần lưu tên người chơi. if(db.kt_luu(DIEM)){ Intent i = new Intent(MainGameActivity.this, Luudiem.class); i.putExtra("diem", DIEM); MainGameActivity.this.startActivity(i); MainGameActivity.this.finish(); } //Nếu không được lưu tên ta quay lại menu chính để người chơi có thể chọn play để chơi lại từ đầu. else{ Intent i = new Intent(MainGameActivity.this, Gameover.class);//Chuyển sang activity Gameover MainGameActivity.this.startActivity(i); MainGameActivity.this.finish(); } } } }; Trích đoạn điều khiển nhân vật. digitalOnScreenControl = new DigitalOnScreenControl(0, ScreenStatic.CAMERA_HEIGHT - this.mOnScreenControlBaseTextureRegion.getHeight(), this.MyCamera, this.mOnScreenControlBaseTextureRegion, this.mOnScreenControlKnobTextureRegion, 0.1f, new IOnScreenControlListener() {float pX = 0, pY = 0; public void onControlChange(final BaseOnScreenControl pBaseOnScreenControl, final float pValueX, final float pValueY) { if(pValueX > 0 && MyPlayer.getStatusPlayer() != StatusPlayer.MOVE_RIGHT){ MyPlayer.setStatusPlayer(StatusPlayer.MOVE_RIGHT); status_digitalOnScreenControl = StatusPlayer.MOVE_RIGHT; pX = MyPlayer.player_AnimatedSprite.getWidth() + MyPlayer.getPositionX(); pY = MyPlayer.getPositionY() + (MyPlayer.player_AnimatedSprite.getHeight() / 2); } else if(pValueX < 0 &&MyPlayer.getStatusPlayer() != StatusPlayer.MOVE_LEFT){ MyPlayer.setStatusPlayer(StatusPlayer.MOVE_LEFT); status_digitalOnScreenControl = StatusPlayer.MOVE_LEFT; pX = MyPlayer.getPositionX(); pY = MyPlayer.getPositionY() + (MyPlayer.player_AnimatedSprite.getHeight() / 2); } else if(pValueY > 0 && MyPlayer.getStatusPlayer() != StatusPlayer.MOVE_DOWN){ MyPlayer.setStatusPlayer(StatusPlayer.MOVE_DOWN); status_digitalOnScreenControl = StatusPlayer.MOVE_DOWN; pX = MyPlayer.getPositionX() +(MyPlayer.player_AnimatedSprite.getWidth()/2); pY = MyPlayer.getPositionY() + MyPlayer.player_AnimatedSprite.getHeight(); } else if(pValueY < 0 && MyPlayer.getStatusPlayer() != StatusPlayer.MOVE_UP){ MyPlayer.setStatusPlayer(StatusPlayer.MOVE_UP); status_digitalOnScreenControl = StatusPlayer.MOVE_UP; pX = MyPlayer.getPositionX() + (MyPlayer.player_AnimatedSprite.getWidth()/2); pY = MyPlayer.getPositionY(); } else{ switch(status_digitalOnScreenControl){ case StatusPlayer.MOVE_RIGHT: MyPlayer.setStatusPlayer(StatusPlayer.UN_MOVE_RIGHT); break; case StatusPlayer.MOVE_LEFT: MyPlayer.setStatusPlayer(StatusPlayer.UN_MOVE_LEFT); break; case StatusPlayer.MOVE_UP: MyPlayer.setStatusPlayer(StatusPlayer.UN_MOVE_UP); break; case StatusPlayer.MOVE_DOWN: MyPlayer.setStatusPlayer(StatusPlayer.UN_MOVE_DOWN); break; default: break; } } if(pValueX != 0 || pValueY != 0){ TMXTile mTMXTile = VatCanTMXLayer.getTMXTileAt(pX + pValueX * 7,pY + pValueY * 7); try{ if(mTMXTile == null){} else{ TMXProperties mTMXProperties= mTMXTile.getTMXTileProperties(mTMXTiledMap); TMXTileProperty mTMXTileProperty = mTMXProperties.get(0); if(mTMXTileProperty.getName().equals("vatcan")){ }} }catch(Exception e){ MyPlayer.moveRelativeXY(pValueX * 7, pValueY * 7); } } } }); Trích đoạn sử lý sự kiện khi người chơi chạm vào quả bom để đặt bom. this.IconBomSprite = new Sprite(ScreenStatic.CAMERA_WIDTH - this.IconBomTextureRegion.getWidth(), ScreenStatic.CAMERA_HEIGHT - this.IconBomTextureRegion.getHeight(), this.IconBomTextureRegion){ @Override public boolean onAreaTouched(final TouchEvent pSceneTouchEvent, final float pTouchAreaLocalX, final float pTouchAreaLocalY) { if(pSceneTouchEvent.getAction() == TouchEvent.ACTION_DOWN){ if(MyPlayer.current_quabom - ArrayListQuaBom.size() != 0 && ControlerStatic.SOUND) beep.play();//Âm thanh khi đặt quả bom xuống với điều kiện là còn bom //Nếu số quả bom có trong ArrayList mà nhiều hơn số quả bom thì không add vào nữa. //Nếu số quả bom có trong ArrayList mà nhiều hơn số quả bom cho phép thì không add nữa. if(ArrayListQuaBom.size() >= MyPlayer.MyQuaBom.length || ArrayListQuaBom.size() >= MyPlayer.current_quabom) return true; //Nếu có 1 quả bom nào đó được kích hoạt thì cho nó vào ArrayList for(QuaBom quabom : MyPlayer.MyQuaBom){ if(quabom.time == 0){ quabom.moveNewXY(MyPlayer.player_AnimatedSprite.getX(),MyPlayer.player_AnimatedSprite.getY()); ArrayListQuaBom.add(quabom); break; } }} return true; } }; Hiện thị giao diện khi người chơi thua cuộc. Trích đoạn mã chương trình như sau. package Bom.gioi.MainGame; import Bom.gioi.BomActivity; import Bom.gioi.R; import Bom.gioi.Dialog.DialogExit; import Android.app.Activity; import Android.content.Intent; import Android.view.KeyEvent; import Android.view.View; import Android.view.Window; import Android.view.WindowManager; import Android.widget.Button; public class Gameover extends Activity{ @Override protected void onCreate(Android.os.Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.Gameover); Button button_Gameover_choilai = (Button)findViewById(R.id.button_Gameover_choilai); Button button_Gameover_mainmenu = (Button)findViewById(R.id.button_Gameover_mainmenu); Button button_Gameover_thoat = (Button)findViewById(R.id.button_Gameover_thoat); button_Gameover_choilai.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { Intent i = new Intent(Gameover.this, MainGameActivity.class); Gameover.this.startActivity(i); Gameover.this.finish(); } }); button_Gameover_mainmenu.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { Intent i = new Intent(Gameover.this, BomActivity.class); Gameover.this.startActivity(i); Gameover.this.finish(); } }); button_Gameover_thoat.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { DialogExit dialogexit = new DialogExit(Gameover.this,Gameover.this); dialogexit.show(); } }); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if(keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN){ DialogExit dialogexit = new DialogExit(Gameover.this, Gameover.this); dialogexit.show(); } return super.onKeyDown(keyCode, event); } } Hiện thị giao diện khi người chơi được lưu điểm. Trích đoạn mã chương trình. package Bom.gioi.MainGame; import Bom.gioi.BomActivity; import Bom.gioi.R; import Bom.gioi.Database.Database; import Bom.gioi.Dialog.DialogExit; import Bom.gioi.Dialog.DialogXemDiem; import Android.app.Activity; import Android.content.Intent; import Android.database.Cursor; import Android.database.sqlite.SQLiteException; import Android.os.Bundle; import Android.view.KeyEvent; import Android.view.View; import Android.view.View.OnClickListener; import Android.view.Window; import Android.view.WindowManager; import Android.widget.Button; import Android.widget.EditText; import Android.widget.LinearLayout; import Android.widget.TextView; import Android.widget.Toast; public class Luudiem extends Activity implements OnClickListener{ Button menu, choilai, luu, xem_diem_cao; TextView text_diem; EditText edit_ten; private Database db; int diem = 0; // ------------------------------------------------------------------ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.luudiem); db = new Database(this); Bundle b = getIntent().getExtras(); if(b != null){ diem = b.getInt("diem"); } choilai = (Button) findViewById(R.id.choilai); choilai.setOnClickListener(this); luu = (Button) findViewById(R.id.luu); luu.setOnClickListener(this); menu = (Button) findViewById(R.id.menu); menu.setOnClickListener(this); xem_diem_cao = (Button) findViewById(R.id.xem_diem_cao); xem_diem_cao.setOnClickListener(this); text_diem = (TextView) findViewById(R.id.diem); text_diem.setText(String.valueOf(diem)); edit_ten = (EditText) findViewById(R.id.name); } // ------------------------------------------------------------------ public void onClick(View v) { // TODO Auto-generated method stub switch (v.getId()) { case R.id.choilai: { choilai(); break; } case R.id.luu: { luu(); break; } case R.id.menu: { Intent i = new Intent(this, BomActivity.class); this.startActivity(i); this.finish(); break; } case R.id.xem_diem_cao: { xemdiemcao(); break; } } } // ------------------------------------------------------------------ private void luu() { String name = edit_ten.getText().toString(); int diemchoi = Integer.parseInt(text_diem.getText().toString()); // Nếu chưa nhập tên thì yêu cầu nhập tên if (name.length() == 0 || name == null) { Toast.makeText(this, "Bạn chưa nhập tên.", Toast.LENGTH_LONG).show(); return; } try { db.open(); Cursor c = db.getAllRows(); if (c.moveToPosition(9)) { String id = c.getString(c.getColumnIndex(Database.KEY_ROWID)); int math = c.getInt(c.getColumnIndex(Database.KEY_DIEM)); if (math < diemchoi) { db.updatePlayer(id, name, diemchoi); LinearLayout l = (LinearLayout)findViewById(R.id.linearLayout_diem); l.setVisibility(View.GONE); luu.setVisibility(View.GONE); xem_diem_cao.setVisibility(View.VISIBLE); xemdiemcao(); } } c.close(); db.close(); } catch (SQLiteException e) { e.printStackTrace(); } } public void xemdiemcao(){ DialogXemDiem xemdiem = new DialogXemDiem(this); xemdiem.show(); } // ----------------------------------------------------------------- @Override protected void onPause() { // TODO Auto-generated method stub this.finish(); super.onPause(); } @Override protected void onDestroy() { super.onDestroy(); this.finish(); }; // ------------------------------------------------------------------ @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if(keyCode == KeyEvent.KEYCODE_BACK){ DialogExit dialogexit = new DialogExit(this,this); dialogexit.show(); } return super.onKeyDown(keyCode, event); } // ------------------------------------------------------------------ private void choilai() { Intent i = new Intent(this, MainGameActivity.class); this.startActivity(i); this.finish(); } } Kiểm thử và đánh giá chương trình. Chương trình đã được kiểm thử trên 1 số thiết bị và đều cho kết quả tốt. Một số thiết bị đã cài đặt và chạy thử là: Điện thoại galaxy y, HTC, máy tính bảng Cube và một số điện thoại khác. Đánh giá chung: Do thiết kế chỉ dành cho thiết bị mobile nên khi chạy trên máy tính bảng thì hình ảnh bị phóng to và không được sắc nét, khi chạy trên các thiết bị mobile thì chất lượng âm thanh, hình ảnh đều cho kết quả cao. Chương trình mở rộng (3D). Mục đích chính của chương trình minh họa. Các khái niệm về đồ họa 3D vô cùng trừu tượng, muốn hiểu được các thành phần này thì ta cần phải xây dựng ví dụ cụ thể để có thể hiểu chi tiết các thành phần. Trong phần này chúng ta cùng nhau xây dựng 1 Game có tên là Line3D, trong quá trình xây dựng Game này thì ta sẽ hiểu được phần nào các cách sử dụng các đối tượng 3D trong hệ điều hành Android. Ý tưởng thực hiện. Game Line2D là 1 Game khá nổi tiếng, đây là Game trí tuệ, người chơi cần phải có tư duy tốt, khả năng tính toán nhanh. Game thu hút được người chơi vì cách chơi đơn giản nhưng để có một điểm số cao thì cũng rất là khó. Game Line2D rất phổ biến, vì Game được yêu thích nên ta sẽ xây dựng 1 bản Game Line3D để cho người chơi được trải nghiệm cảm giác chơi Game 3D thật thú vị và hấp dẫn. Mô tả cách chơi Game: Trên một mặt phẳng ta chia mặt phẳng thành nhiều ô vuông bằng nhau, mỗi một lần người chơi di chuyển 1 viên bi thì sau đó sẽ có thêm 3 viên bi được hiện thị lên mặt phẳng, nếu các viên bi cùng màu theo hàng ngang, hàng dọc hoặc đường chéo với số lượng lớn hơn 5 viên thì 5 viên bi này sẽ biến mất, khi mà số viên bi mà biến mất thì sẽ không hiện thị thêm 3 viên bi kia nữa. Người chơi sẽ thua khi toàn bộ các vị trí trên mặt phẳng được đặt kín toàn bộ các viết bi. Trò chơi sẽ lưu lại số điểm của người chơi khi người chơi có số điểm cao. Một số tính năng chính trong Game cần phải thực hiện được là: Chọn viên bi cần di chuyển rồi di chuyển viên bi tới đúng vị trí do người chơi chọn. Khi người chơi chọn 1 viên bi nào đó thì viên bi đó phải thay đổi trạng thái để người chơi biết là viên bi đó đang được chọn. Có thể xoay mặt phẳng để nhìn các góc độ khác nhau. Có thể phóng to thu nhỏ màn hình. Phân tích chương trình. Sơ đồ hoạt động của Game. Xác định actor và mô hình use case. 3.4.2.3.2.1 Xác định actor. STT TÊN ACTOR Ý NGHĨA/GHI CHÚ 1 Người chơi Game Người sử dụng điện thoại để chơi Game 3.4.2.3.2.2 Sơ đồ use case và đặc tả chi tiết. 3.4.2.3.2.2.1 Sơ đồ use case. 3.4.2.3.2.2.2 Danh sách các use case. STT TÊN USE-CASE Ý NGHĨA/GHI CHÚ 1 Bắt đầu chơi Chọn Activity PlayGame 2 Xoay mặt phẳng Thay đổi góc nhìn 3 Chọn viên bi Xác định viên bị muốn điều khiển 4 Chọn vị trí đến Chọn vị trí đến cho viên bi 5 Thoát Thoát khỏi trò chơi 3.4.2.3.2.2.3 Đặc tả các use case. Đặc tả use case Bắt đầu chơi. Tóm tắt : Người dùng chọn khởi động Activity PlayGame. Dòng sự kiện: Dòng sự kiện chính: + Trên Menu chính người chơi chọn bắt đầu. + Hiện thị activity PlayGame. + Kết thúc use case. Dòng sự kiện khác: Không có. Các yêu cầu đặc biệt: Không có. Trạng thái của hệ thống khi bắt đầu thực hiện use case: Nút bắt đầu chuyển sang trạng thái được chọn. Trạng thái của hệ thống sau khi thực hiện use case: Hiện thị activity PlayGame. Điểm mở rộng: Không có. Đặc tả use case Xoay mặt phẳng. Tóm tắt : Người dùng chọn vào màn hình và kéo theo hướng mà muốn xoay. Dòng sự kiện: Dòng sự kiện chính: + Trên giao diện Player người dùng chạm vào màn hình. + Xoay góc nhìn của mặt phẳng. + Kết thúc use case. Dòng sự kiện khác: Không có. Các yêu cầu đặc biệt: Không có. Trạng thái của hệ thống khi bắt đầu thực hiện use case: Game đang trong trạng thái chơi. Trạng thái của hệ thống sau khi thực hiện use case: Mặt phẳng sẽ thay đổi theo hướng mà người chơi xoay. Điểm mở rộng: Không có. Đặc tả use case Chọn viên bi. Tóm tắt : Người dùng chạm vào viên bi trên mặt phẳng. Dòng sự kiện: Dòng sự kiện chính: + Trên giao diện PlayGame người chơi chạm vào viên bi. + Ghi lại vị trí viên bi được người chơi chạm. + Kết thúc use case. Dòng sự kiện khác: Không có. Các yêu cầu đặc biệt: Không có. Trạng thái của hệ thống khi bắt đầu thực hiện use case: Game đang trạng thái chơi. Trạng thái của hệ thống sau khi thực hiện use case: Tô màu ô mà người chơi vừa chọn. Điểm mở rộng: Không có. Đặc tả use case Chọn viên bi. Tóm tắt : Người dùng chạm vào vùng mà không có viên bi. Dòng sự kiện: Dòng sự kiện chính: + Trên giao diện PlayGame người dùng chạm vào các ô không có viên bi. + Nếu vị trí được chọn không có viên bi thì ra sẽ di chuyển viên bi được chọn sang vị trí vừa được chọn. + Kết thúc use case. Dòng sự kiện khác: Không có. Các yêu cầu đặc biệt: Không có. Trạng thái của hệ thống khi bắt đầu thực hiện use case: Game đang trong trạng thái chơi. Trạng thái của hệ thống sau khi thực hiện use case: Tại vị trí người chơi chạm vào sẽ được tô sáng. Viên bi được di chuyển đến vị trí mà người chơi chọn. Điểm mở rộng: Không có. Thiết kế chương trình. 3.4.2.3.3.1 Kiến trúc hệ thống. Hệ thống được chia thành 2 tầng . BUS Activity THÀNH PHẦN DIỄN GIẢI Activity Lớp giao diện, chứa tất cả các giao diện, màn hình chức năng của chương trình. BUS (Business Logic Layer) Quản lý việc kiểm tra các yêu cầu nghiệp vụ, các phương thức. 3.4.2.3.3.2 Mô tả thành phần hệ thống. Các lớp trong Activity. LỚP ĐỐI TƯỢNG DIỄN GIẢI PlayGame Cung cấp các phương thức dùng để giao tiếp với người dùng. MenuChinh Cung cấp các activity để người dùng chọn. Các lớp BUS. LỚP ĐỐI TƯỢNG DIỄN GIẢI VienBi Định nghĩa khối viên bi. QuanLyVienBi Cung cấp các phương thức hiển thị, kiểm tra khối viên bi. VienGach Định nghĩa khối viên gạch QuanLyVienGach Cung cấp các phương thức hiển thị, kiểm tra khối viên gạch GameRenderer Cung cấp phương thức vẽ, quản lý tương tác với người dùng và hiển thị giao diện. Thiết kế giao diện. Giao diện menu: Xem hình 30. Giao diện PlayGame: Xem hình 31. Viết chương trình. Phương thức quay trục tọa độ. Sự khác biệt giữa Game 3D với 2D chính là khả năng xoay hình, có thể nhìn hình với mọi gốc độ. Để làm được điều này thì dùng phương thức xoay: glRotatef(float angle, float x, float y, float z) //Tham số angle: gốc alpha cần xoay. //Tham số x, y, z: Tương ứng với trục muốn xoay, muốn xoay theo trục nào thì thay đổi giá trị đó là 1.0f. Ví dụ muốn xoay 1 góc 45 độ theo trục x thì ta khai báo: glRotatef(45.0f, 1.0f, 0.0f, 0.0f); Cách kiểm tra xem viên bi khi dịch chuyến đến điểm kết thúc thì có ăn được bi hay không. Xử lý ăn bi cũng tương đối đơn giản, sau khi viên bi di chuyển xong thì đếm các vị trí xung quanh viên bi trong ma trận theo hàng dọc, hàng ngang và đường chéo. Nếu giá trị giống với viên bi đang xét thì lưu vị trí vào mảng, sau khi kiểm tra hết các vị trí xung quanh thì kiểm tra số lượng viên bi trong mảng có lớn hơn hoặc bằng 5 thì xóa các viên bi đó. Ví dụ minh họa theo hình sau: Xem hình 32.(Đang nghiên cứu) Kiểm thử và đánh giá chương trình (Đang nghiên cứu). Chương 4: Kết luận và hướng phát triển trong tương lai Kết luận. Sau một khoảng thời gian 4 tháng tìm hiểu về đề tài thì kết quả đạt được như sau. Hiểu được cấu trúc, cách thức hoạt động, cách thức phát triển ứng dụng trên hệ điều hành Android. Tìm hiểu được lý thuyết về đồ họa 2D, 3D. Các lĩnh vực sử dụng các kỹ thuật này. Xây dựng hoàn chỉnh trò chơi Bom Offline và phân tích xong trò chơi Line3D. Tuy nhiên bên cạnh những kết quả đạt được thì vẫn còn gặp một số khó khăn như sau. Vì là một hệ điều hành mới nên số tài liệu tham khảo ít ỏi. Việc kiểm thử chương trình cũng rất khó khăn vì thiếu các thiết bị. Chưa hoàn thiện được trò chơi Line3D. Hướng phát triển trong tương lai. Do thời gian làm khóa luận có hạn, nên khóa luận cũng không thể tránh được những thiếu sót mà ta không thể lường trước được. Còn rất nhiều vấn đề mà ta cần phải giải quyết để cho khóa luận được tốt hơn: Nghiên cứu sâu hơn về đồ họa 3D nói chung và trên hệ điều hành Android riêng. Xây dựng thêm một số tính năng cần thiết cho trò chơi Bom Offline như + Các quái vật có khả năng tìm được đi ngắn nhất để di chuyển đến nhân vật. + Cần cải thiện tốc độ của trò chơi. + Thêm chức năng chơi trực tuyến. + Có thêm phần thách thức người chơi khác. + Có thể chơi thông qua giao tiếp Bluetooth. + Nâng cấp giao diện trò chơi. + Thương mại hóa sả phẩm. Tiếp tục hoàn thiện trò chơi Line3D. Các hình ảnh dùng trong khóa luận. Hình 1.Kiến chúc hệ điều hành Android Hình 2: Bảng liệt kê một số kiểu file trong Linux. Hình 3: Mô tả cây thư mục. Hình 4: Tóm tắt quá trình cập nhật các phiên bản tính đến 2011. Hình 5: Các gói cho các hệ điều hành. Hình 6: Kết quả khi chạy file SDK Manager. Hình 7: Add ADT Hình 8: Cài đặt thành công. Hình 9: 3 bức ảnh được chụp từ 1 đối tượng 3D. Hình 10. Hiện thị 1 hình tròn màu đỏ. Hình 11: Kết quả chương trình minh họa TestAndroid2D Hình 12: Kết quả chương trình TestAndroid3D. Hình 13: Giao diện menu chính. Hình 14: Hiện thị thông tin. Hình 15: Xác thực xem muốn thoát hay không. Hình 16: Giao diện phần hướng dẫn chơi. Hình 17: Hiện thị thông báo đang tải dữ liệu. Hình 18: Giao diện chính của trò chơi. Hình 19: Giao diện menu phụ. Hình 20: Giao diện khi người chơi thua cuộc. Hình 21: Giao diện khi người chơi thắng cuộc. Hình 22: Giao diện lưu điểm. Hình 23: Hiện thị danh sách điểm cao. Hình 24: Ví dụ 1 map(bản đồ). Hình 25: Vị trí pX, pY nằm trên TMXLayer. Hình 26: Vị trí pX, pY nằm ngoài TMXLayer. Hình 27: Ảnh nền phần menu chính. Hình 28: 3 ảnh thể hiện 3 chức năng chính hiện thị trên menu. Hình 29: 3 ảnh dùng trong phần giao diện chính của Game. Ảnh trái tim: Ảnh thể hiện trạng thái tạm dừng: Ảnh thể hiện quả bom: Hình 30: Giao diện menu Game Line3D Hình 31: Giao diện chơi Game Line3D. Hình 32: Ví dụ minh họa cách tính ăn viên bi. Tài liệu tham khảo. [1] [2] [3] [4] [5] docx_20111101_bao_cao_do_an_Android_3491 của Võ Quang Hòa – Nhóm 09A, Lớp 07T4

Các file đính kèm theo tài liệu này:

  • dockhoaluantotnghiep_dangvangioi_9148.doc