View
0
Download
0
Category
Preview:
Citation preview
Trung tâm Đào tạo E-Learning Cơ hội học tập cho mọi người
Lập trình thiết bị di động - Bài 8 Trang 1
BÀI 8: KỸ THUẬT PHÁT TRIỂN GAME TRONG ANDROID
Mục tiêu:
Trong bài này, Anh/Chị cần đạt được những mục tiêu sau:
1. Giới thiệu các khái niệm cơ bản về nguyên lý xây dựng các ứng dụng trò
chơi.
2. Sử dụng AndEngine để phát triển một ứng dụng game đơn giản.
Nội dung:
8.1. Các nền tảng phát triển game trên thiết bị di động
Trong các bài học trước chúng ta đã làm quen với kỹ thuật xử lý đồ họa trên
J2ME, bài học này chúng ta sẽ tập trung vào tìm hiểu kỹ thuật xử lý đồ họa trên
android thông qua tiếp cận một số nền tảng phát triển game và xây dựng một
trò chơi đơn giản trên một engine cụ thể.
Kể từ khi máy tính xuất hiện, game đã trở thành một trong những ứng dụng phổ
biến nhất trên thị trường. Trong cuốn sách Reality Is Broken, tác giả Jane
McGonigal đã nêu ra 4 thuộc tính của phần lớn game trên thị trường:
Mục tiêu: Game chỉ ra một mục tiêu rõ ràng cho người chơi để họ đạt
được. Mục tiêu là những thử thách đối với người chơi, nhưng họ có thể
vượt qua. Người chơi sẽ cảm thấy hứng thú nhất nếu mục tiêu đó phù
hợp với khả năng của mình, không quá khó, không quá dễ. Mục tiêu rõ
ràng, thú vị cũng là yếu tố quan trọng thu hút người chơi đến với game.
Quy tắc: Game cũng có những quy tắc bắt buộc mà tất cả người chơi
phải tuân theo. Các quy tắc này thường làm cho việc đạt được mục tiêu
nêu trên khó khăn hơn. Điều đó cũng khuyến khích sự sáng tạo của mỗi
người.
Phản hồi: Game cần phản hồi cho người chơi biết rằng họ đang làm công
việc của mình tốt hay không. Một điều đáng lưu ý rằng, hệ thống phản
hồi chính là chìa khóa để làm trò chơi thú vị.
Trung tâm Đào tạo E-Learning Cơ hội học tập cho mọi người
Lập trình thiết bị di động - Bài 8 Trang 2
Tham gia một cách tự nguyện: một trò chơi sẽ không còn là một trò chơi
đúng nghĩa nếu bạn không thực sự thích chơi nó. Điều này ngụ ý rằng
người chơi phải chấp nhận được mục tiêu, các quy tắc, và hệ thống phản
hồi của trò chơi.
Các thể loại game cơ bản
Những người phát triển game không chủ động phân loại các trò chơi của họ.
Và tất nhiên, không có danh sách chuẩn nào về việc phân loại game. Mặc dù
vậy, theo thời gian, các trò chơi cũng dần được phân loại vào các lớp khác nhau
theo những cách khác nhau. Việc phân loại chính xác rất khó khăn. Tuy vậy,
chúng ta có thể kể đến một số loại game điển hình như sau:
Game hành động hay kỹ năng: Người chơi phải sử dụng một số kỹ năng
trong thời gian thực (VD: bắn vào một vật đang di chuyển ) để đạt được
mục tiêu.
Game về chiến lược: Người chơi ít phải sử dụng kỹ năng hơn, và chủ
yếu tập trung đưa ra những quyết định lựa chọn chiến lược hợp lý để
vượt qua màn chơi.
Game phiêu lưu hay có cốt truyện: Những game này được xây dựng dựa
trên một cốt truyện hấp dẫn, với các nhân vật được trau chuốt cùng với
một cốt truyện cụ thể. Cốt truyện đó cũng định nghĩa ra mục tiêu cho
người chơi trong thể loại game này.
Game mô phỏng: Thông thường, game thuộc thể loại này mô tả lại một
yếu tố có trong thực tế (VD như lái một chiếc xe, chơi tennis,…)
Game dạng câu đố: Một số trò chơi truyền tải trực tiếp câu đố đến với
người chơi. Tuy nhiên, trong một số game phức tạp, những câu đố này
có thể ẩn dưới nhiều hình thức khác nhau. Có thể hiểu như một game
nhỏ, trong một game lớn hơn.
Việc phát triển các sản phẩm game trên điện thoại di động chưa bao giờ là điều
đơn giản. Một sản phẩm game hoàn chỉnh yêu cầu lập trình viên phải dành rất
nhiều thời gian và công sức để hoàn thiện nó. Để giảm thiểu thời gian và công
việc trong quá trình phát triển game, ngày nay, đã có rất nhiều các thư viện hỗ
trợ phát triển game (Game Engine) trên thiết bị di động được ra đời.
Trung tâm Đào tạo E-Learning Cơ hội học tập cho mọi người
Lập trình thiết bị di động - Bài 8 Trang 3
Trong bài học này, chúng ta cùng tìm hiểu những thư viện game (Game Engine)
trên các thiết bị di động được đánh giá tốt nhất hiện nay.
Unity 3D
Unity 3D là phần mềm phát triển ứng dụng game trực tiếp theo thời gian thực.
Đây là một trong những nền tảng phát triển game tốt nhất, cung cấp một môi
trường phát triển tích hợp trực quan bằng các thao tác kéo thả tùy biến giao
diện một cách nhanh chóng. Unity 3D hỗ trợ hầu hết các định dạng đồ họa được
tạo ra bởi các phần mềm đồ họa chuyên nghiệp như: 3D Max, Blender, Modo,
Autodesk FBX, LightWave, Maya, Cinema 4D,Cheetah 3D.
Một trong những đặc điểm nổi bật nhất của Unity 3D là bộ thư viện vật lý được
tích hợp sẵn. Với thư viện vật lý này, lập trình viên sẽ giảm thiểu được rất nhiều
công việc tính toán và viết code cho các chuyển động (bao gồm cả va chạm)
trong game.
Với Unity, sau khi bạn design được một game thì bạn có thể xuất được ra một
file.exe và có thể chạy và chơi được trên PC khác.
Một thế mạnh nữa của Unity là bạn có thể chạy demo game của bạn ngay trong
khi design, nó có hỗ trợ hai chế độ là Scene và Game, rất thuận tiện cho việc
test thử các modulGame.
Hiện Unity 3D cung cấp cả hai phiên bản miễn phí và mất phí. Bạn có thể dễ
dàng tải phần mềm làm game này tại địa chỉ: http://www.unity3d.com.
Corona SDK
Corona được coi là một trong những nền tảng phát triển game 2D tốt nhất hiện
nay. Corona hỗ trợ đa nền tảng, điều đó có nghĩa là bạn chỉ cần phát triển game
một lần duy nhất và dễ dàng biên dịch sang các nền tảng di động khác nhau.
Đặc biệt Corona SDK sử dụng LUA làm ngôn ngữ chính để phát triển game.
Dưới đây là những đặc trưng của SDK này:
Corona SDK giúp phát triển ứng dụng nhanh hơn 10 lần. Với hệ thống
thư viện hỗ trợ phong phú và được thiết kế rất tốt, lập trình viên có thể
Trung tâm Đào tạo E-Learning Cơ hội học tập cho mọi người
Lập trình thiết bị di động - Bài 8 Trang 4
dễ dàng xây dựng các thao tác (hành động) trong game chỉ bằng một vài
dòng code.
Corona hỗ trợ đa nền tảng. Bạn chỉ cần phát triển game một lần, sau đó
có thể dễ dàng biên dịch ứng dụng sang các nền tảng khác như Android,
iOS, Kindle Fire, Nook và Windows Phone một cách dễ dàng. Không
những vậy Corona còn hỗ trợ chuyển đổi với những thiết bị có kích cỡ
và độ phân giải khác nhau một cách dễ dàng.
Đạt các tiêu chuẩn của ngành công nghiệp game. Hiện Corona SDK cung
cấp 4 phiên bản:
o Starter: Xây dựng và xuất bản các ứng dụng miễn phí.
o BASIC, PRO, Enterprise: tính phí, có thêm các tính năng tiên tiến,
tích hợp thêm các thư viện địa phương, hỗ trợ linh hoạt tối đa. Bạn
có thể xem chi tiết về Corona SDK tại địa chỉ:
http://coronalabs.com/products/corona-sdk/
Game Salad
GameSalad là phần mềm phát triển các ứng dụng game được đánh giá là dễ
nhất so với các sản phẩm cùng loại. Với GameSalad, nhà phát triển chỉ cần dựa
vào giao diện kéo thả để xây dựng game mà gần như không cần kỹ năng lập
trình. GameSalad nhắm tới những đối tượng khách hàng có ý tưởng phát triển
trò chơi nhưng thiếu kỹ năng lập trình. Thống kê hiện nay có khoảng hơn
700.000 nhà phát triển với hơn 200.000 trò chơi trên toàn thế giới. Trong đó có
rất nhiều trò chơi hay và được đánh giá rất cao, thậm chí còn đạt được top 70-
100 trên các kho ứng dụng.
Hiện nay GameSalad hỗ trợ các nền tảng: Android, iOS, Windows Phone,
HTML5. Chi tiết về GameSalad tại địa chỉ: http://gamesalad.com
Sprite Kit
Sprite Kit là thư viện hỗ trợ phát triển game di động của Apple. Các lập trình
viên khi sử dụng Sprite Kit không cần phải tải thêm bất kỳ thư viện nào do
Sprite Kit đã được tích hợp sẵn trong Xcode. Thư viện này không những cung
cấp khá đầy đủ các tính năng để phát triển game trên nền 2D mà còn được tích
Trung tâm Đào tạo E-Learning Cơ hội học tập cho mọi người
Lập trình thiết bị di động - Bài 8 Trang 5
hợp một bộ thư viện vật lý khá tốt, giúp các nhà phát triển có thể lập trình hành
động nhân vật một cách đơn giản và nhanh chóng.
Một số ưu điểm:
Đây là một thư viện được xây dựng ngay trong IOS nên không cần phải
tải thêm bất kì một thư viện số (Extra Libray) hay một mã nguồn nào bên
ngoài nữa. Ngoài ra, nó được viết và phát triển bởi chính Apple nên
chúng ta có thể biết được rằng nó sẽ được Apple hỗ trợ và cập nhật
thường xuyên sớm nhất có thể.
Có sẵn các công cụ để cắt và thể hiện hiệu ứng ngay trong Xcode (particle)
Giúp bạn lập trình và quản lý game một cách dễ dàng do cấu trúc của
Sprite Kit được thiết kế để làm chuyện đó. Hỗ trợ các dạng video và
hiệu ứng hình ảnh đơn giản nhưng chắc chắn sẽ được cải thiện trong
tương lai.
Nhược điểm:
Một khi sử dụng Sprite Kit nghĩa là cuộc sống của bạn sẽ gắn liền với hệ
sinh thái của Apple. Nếu bạn muốn đưa game của bạn lên các hệ điều
hành khác như Android thì nó gần như là viết lại từ đầu.
Sprite Kit đang ở thời kì đầu của nó, việc nó thành công hay thất bại là
thứ hoàn toàn không chắc chắn. Thêm vào đó, Sprite Kit chưa hỗ trợ cho
bạn tham gia vào việc tuỳ chỉnh các mã OpenGL nên đối với những lập
trình viên có thâm niên cao thường không thích thú lắm.
Những thứ bạn đã viết được trên các engine khác như Corona, Cocos2D
không phù hợp với Sprite Kit điều đó có nghĩa là bạn đang bắt đầu từ
vạch xuất phát cùng với tất cả mọi người.
Thông tin chi tiết về game engine này tại địa chỉ sau:
https://developer.apple.com/library/ios/documentation/GraphicsAnimation/C
onceptual/SpriteKit_PG/Introduction/Introduction.html.
Trung tâm Đào tạo E-Learning Cơ hội học tập cho mọi người
Lập trình thiết bị di động - Bài 8 Trang 6
Cocos2d-x
Cocos2D-X là nền tảng phát triển các ứng dụng game mã nguồn mở theo giấy
phép MIT. Cocos2d-x phù hợp trong những dự án xây dựng các trò chơi, ứng
dụng và các chương trình đa nền tảng.
Hiện tại, Cocos2d-x cho phép các nhà phát triển thực hiện dự án với các ngôn
ngữ C++, LUA và JavaScript cùng các nền tảng hỗ trợ như: iOS, Android,
Windows Phone, Mac OS X, Windows PC và Linux PC. Cocos2d-x cung cấp
một môi trường phát triển nhanh chóng, tiết kiệm thời gian, công sức và chi
phí. Cocos2d-x đang là nền tảng phát triển game phổ biến được ưa chuộng
rộng rãi từ nhà phát triển cá nhân cho đến những công ty phát triển game lớn.
Có thể kể đến các công ty lớn sử dụng cocos2d-x như: Zynga, Wooga, Glu,
IGG, Big Fish Games, Fingersoft, Gamevil, GREE, DeNA, Konami, CJ E &
M, NHN, LINE, Square Enix, Disney.
Để biết thêm thông tin của Cocos2d-x, bạn có thể truy cập địa
chỉ: http://www.cocos2d-x.org
AndEngine
AndEngine là một nền tảng phát triển game 2D mã nguồn mở cho phép xây
dựng các ứng dụng trò chơi trên Android một cách nhanh chóng và dễ dàng.
Đặc biệt AndEngine hỗ trợ đầy đủ các thuộc tính quan trọng của OpenGL, nhờ
đó lập trình viên có thể dựng hình, tạo vật thể, quản lý các thiết bị đầu vào
(sensor cảm ứng, màn hình cảm ứng …) và âm thanh khá thuận tiện và hiệu
quả. Dưới đây là những tính năng cơ bản AndEngine cung cấp:
Hỗ trợ các thiết bị với những độ phân giải khác nhau.
Hỗ trợ cảm ứng đa điểm.
Hỗ trợ bộ thư viện vật lý Box2D.
Hỗ trợ bản đồ map Tiled
Một số đánh giá về Andengine:
Chi phí giá thành: Hoàn toàn free.
Trung tâm Đào tạo E-Learning Cơ hội học tập cho mọi người
Lập trình thiết bị di động - Bài 8 Trang 7
Hiệu năng: Tương đối tốt, tuy nhiên chậm hơn so với các Engine khác
(như LibGDX ở phần trên).
Cộng đồng: tương đối tốt, số lượng người sử dụng khá nhiều.
Tài liệu và ví dụ: không có tài liệu cụ thể. Đây là một trong những khó
khăn khi chúng ta làm quen với Andengine. Tuy nhiên có các ví dụ và
các bài viết hướng dẫn của các lập trình viên (có thể tìm được qua
Internet). Do đó nếu bạn muốn sử dụng Andengine hãy chuẩn bị tam lý
là sẽ tìm hiểu bằng các ví dụ là chủ yếu.
Mã nguồn mở, thiết kế sử dụng nhiều phương thức abstract và kế thừa.
Hướng đối tượng tốt, tuy nhiên chưa thật sự tốt với nền tảng di động
Android.
Tính năng: Có đầy đủ hầu hết các tính năng cơ bản để xây dựng một ứng
dụng game. Tuy nhiên vẫn chưa có nhiều tính năng giống như LibGDX.
Điểm cộng dành cho Andengine chính là ở việc dễ sử dụng và dễ học hơn các
Engine khác, đồng thời các tính năng cơ bản cũng khá đầy đủ cho việc xây
dựng một game 2D đơn giản. Hãy nhớ, Andengine chỉ thích hợp cho Game 2D.
Nếu yêu cầu về hiệu năng của bạn thật sự cao và game co nhiều hình ảnh phức
tạp, cũng như hình ảnh vật thể là 3D, hãy tìm một Engine khác.
Để biết thêm thông tin về game enigne này, bạn có thể truy cập địa chỉ
sau: http://www.andengine.org
LibGDX
LibGDX là nền tảng phát triển game mã nguồn mở được đánh giá rất cao về
hiệu năng. LibGDX hỗ trợ đa nền tảng trên Desktop, Android, iOS, HTML5 và
BlackBerry. Sử dụng LibGDX đồng nghĩa với việc cho phép lập trình viên Java
phát triển các dự án game trên máy tính cá nhân và thiết bị di động bằng cách
sử dụng cơ sở mã giống nhau. Điểm được đánh giá cao nhất của LibGDX là
hiệu năng nền tảng này có được nhờ mã nguồn sử dụng cả Java và C để phát
triển. Ngoài khả năng tương đồng nhiều game engine khác như tạo hình, xử lý
đồ họa 2D-3D, quản lý thiết bị đầu vào, quản lý tệp tin hệ thống, LibGDX còn
nổi bật với các công cụ hỗ trợ tạo bản đồ, ảnh đi kèm như Texture Packer và
Particle Editor.
Trung tâm Đào tạo E-Learning Cơ hội học tập cho mọi người
Lập trình thiết bị di động - Bài 8 Trang 8
Một số ưu điểm của Libgdx như sau:
Đa nền tảng: chúng ta chỉ cần viết code 1 lần nhưng có thể chạy trên
được nhiều nền tảng khác nhau. Một ứng dụng của tính năng này đó là
phát triển các ứng dụng cho Android. Để phát triển một ứng dụng cho
Android, khi chạy thử ứng dụng, chúng ta cần chạy ứng dụng trên
Emulator hoặc trên thiết bị thật. Việc này rất mất thời gian do Emulator
chạy rất chậm và quá trình cài đặt cũng như chạy ứng dụng trên thiết bị
thật cũng không khá hơn. Với LibGDX, chúng ta có thể chạy ứng dụng
trên PC, sau đó chỉ cần với vài dòng code, chúng ta có thể chạy ứng dụng
này trên Android với hiệu năng tương đương. Điều này giúp chúng ta
kiểm thử và tìm lỗi ứng dụng nhanh hơn và hiệu quả hơn.
Hiệu năng: Hiệu năng của LibGDX thực sự rất ấn tượng do LibGDX sử
dụng cả Java và mã nguồn C để tạo nên ứng dụng.
Cộng đồng: cộng đồng sử dụng LibGDX rất tuyệt vời với số lượng người
dùng lớn. Các lập trình viên luôn đóng góp và giúp đỡ cho cộng đồng.
Việc sửa lỗi cũng được cập nhật rất thường xuyên.
Tài liệu và ví dụ: rất đầy đủ với Javadoc. LibGDX cũng cung cấp rất
nhiều các ví dụ và demo với đầy đủ các chức năng từ đơn giản đến
phức tạp.
Mã nguồn: mã nguồn mở với thiết kế rất rõ ràng và phù hợp với việc
phát triển ứng dụng cho di động. LibGDX cho phép người lập trình khả
năng sử dụng các API từ các lớp thấp đến cao, tùy theo yêu cầu của người
sử dụng.
Tính năng: LibGDX có rất nhiều tính năng như tạo hình, xử lý đồ họa
2D, 3D, xử lý âm thanh, quản lý các thiết bị vào ra, quản lý file hệ thống.
Cùng với đó là các công cụ đi kèm rất hữu ích như Texture Packer và
Particle Editor.
Để biết thêm thông tin chi tiết về nền tảng game nổi tiếng này, bạn có thể truy
cập địa chỉ: http://libgdx.badlogicgames.com
Trung tâm Đào tạo E-Learning Cơ hội học tập cho mọi người
Lập trình thiết bị di động - Bài 8 Trang 9
8.2. Lập trình game với AndEngine
8.2.1. Các thành phần cơ bản của AndEngine
1. Camera
Các "camera" của trò chơi xác định giao diện được trình bày cho người chơi.
Nó giống như một máy quay phim trong không gian hai chiều. Chiếc máy quay
này có thể giãn và phóng trên các cảnh để thay đổi khung nhìn trình bày. Sự co
giãn và phóng to có thể được thực hiện dưới sự kiểm soát của người chơi hoặc
được điều khiển theo chương trình.
2. Scene
Một trò chơi, giống như một bộ phim, bao gồm một loạt các cảnh nơi hành
động diễn ra. Trong một bộ phim, những cảnh được biên tập lại với nhau theo
một cách cố định. Trong trò chơi, trình tự của cảnh được dẫn dắt bởi lối chơi
của trò chơi. Trò chơi giống như bộ phim được chỉnh sửa từ trên cao nhìn xuống.
3. Layer
Cảnh bao gồm các lớp đồ họa. Các lớp được chồng lên nhau, giống như các tế
bào hoạt hình được sử dụng để tạo phim hoạt hình theo nghề ngày xưa. Các lớp
cũng có thể được sử dụng để giới thiệu 2 ½ D hiệu ứng, ở đâu, như giãn máy
quay, các lớp gần hơn chuyển động nhanh hơn các lớp ở xa nhiều hơn.
4. Sprite
Những Sprite là những đại diện trực quan của các diễn viên trong bộ phim của
chúng ta. Dù cho các sprite là hình động hay tĩnh, chúng vẫn thường di chuyển
trong những màn chơi. Kết cấu Sprite thường được nạp từ một hình ảnh lớn mà
bao gồm một tập hợp các hình ảnh họa tiết, được gọi là một sprite sheet.
Trung tâm Đào tạo E-Learning Cơ hội học tập cho mọi người
Lập trình thiết bị di động - Bài 8 Trang 10
5. Entity
Trong AndEngine, các thực thể là tất cả những thứ được vẽ trên màn hình. Các
thực thể có thể là các sprite, các hình dạng hình học, hay các dòng kẻ trên màn
hình. Tất cả các thực thể đều có các thuộc tính, chẳng hạn như màu sắc, góc
quay, độ lớn, vị trí, và có thể được thay đổi bằng các Modifier.
6. Modifier
Các modifier thay đổi các thuộc tính của một thực thể, và chúng rất mạnh mẽ
trong AndEngine. Chúng có thể được sử dụng trên bất kỳ thực thể nào, và sự
thay đổi mà chúng gây ra có thể là trực tiếp hoặc diễn ra từ từ trong một thời
gian nhất định. Trong trò chơi của chúng ta, chúng ta sẽ sử dụng các modifier
thường xuyên để tạo hiệu ứng với các sprite và các thực thể khác.
7. Texture
Một texture là một kết cấu 2D, thường là đồ họa dạng bitmap. Textures xác
định hình dạng các thực thể, và phần lớn môi trường đồ họa OpenGL được xây
dựng xung quanh việc sử dụng các texture.
8. Texture Region
Một texture định nghĩa một hình ảnh bitmap hoàn tất, và một texture region
định nghĩa một tập hợp con các vùng texture đó.
9. Engine
Mỗi scene được chạy trên một engine. Nó điều khiển các hình ảnh động và các
modifier biết khi nào phải cập nhật trạng thái, điều phối các bản vẽ thực tế, xử
lý các sự kiện đầu vào người dùng (cảm ứng, phím, bộ cảm biến), và nói chung
là quản lý tiến trình của trò chơi. Engine cũng giống như các nhà sản xuất/đạo
diễn của bộ phim của chúng ta, nói với mọi người những gì họ cần phải làm.
10. BaseGameActivity
Lớp này, được mở rộng của lớp Activity Android, sẽ là cơ sở của mỗi scene
trong trò chơi của chúng ta. BaseGameActivity làm các công việc chung cho
tất cả các scene, thiết lập các công cụ trò chơi, phù hợp với các yêu cầu vòng
đời hoạt động Android.
Trung tâm Đào tạo E-Learning Cơ hội học tập cho mọi người
Lập trình thiết bị di động - Bài 8 Trang 11
11. Physics Connector
AndEngine bao gồm khả năng vật lý cơ bản trong engine cơ bản, nhưng Box2D
động cơ vật lý được mở rộng phần lớn vào những khả năng đó. Chúng ta kết
nối với đối tượng AndEngine Box2D thông qua một kết nối vật lý. Nếu game
của bạn không sử dụng Box2D vật lý, bạn sẽ không có một kết nối vật lý.
12. Box2D Physics Engine
Physics Box2D là một thành phần mở rộng của AndEngine, nó hỗ trợ việc
mô phỏng sự tương tác thực tế giữa các đối tượng vật lý trong các trường
hợp sau đây:
Mô phỏng các tính chất vật lý của các vật rắn.
Ổn định xếp chồng.
Trọng lượng.
Các đơn vị được người dùng xác định.
Giải quyết hiệu quả cho sự tương tác / liên lạc.
Trượt ma sát.
Làm việc với các hình học: hình hộp, hình tròn, đa giác.
Một số loại liên kết: khoảng cách, lăng trụ, ròng rọc,…
Trạng thái ngủ (loại bỏ cơ thể bất động từ các mô phỏng cho đến khi
chạm vào).
8.2.2. Ví dụ thiết kế và xây dựng game đơn giản.
Bài toán tháp Hà Nội:
Cho 3 cái đĩa và ba cái trục: A là trục nguồn, B là trục đích, và C là trục trung
chuyển. Những cái đĩa có kích cỡ khác nhau và có lỗ ở giữa để có thể lồng vào
trục, theo quy định "nhỏ trên lớn dưới". Đầu tiên, những cái đĩa này được xếp
tại trục A. Vậy làm thế nào để chuyển toàn bộ các đĩa sang trục B, với điều kiện
chuyển từng cái một và luôn phải đảm bảo quy định "nhỏ trên lớn dưới", biết
rằng trục C được phép sử dụng làm trục trung chuyển?
Trung tâm Đào tạo E-Learning Cơ hội học tập cho mọi người
Lập trình thiết bị di động - Bài 8 Trang 12
a) Cài đặt các gói AndEndgine
Trước hết ta cần cài đặt AndEngine. Ở đây chúng ta cùng cài đặt AndEngine
và tích hợp với Eclipse.
Ta sẽ tạm chia thành 3 bước cài đặt : bước 1 là cài đặt egit - tool quản lý source
phân tán, bước 2 là import các project đã có của Andengine thành các thư viện
của mình , bước 3 là thêm thư viện mới import vào project.
Bước 1: Cài đặt Git
Trong giao diện của Eclipse, tại thanh menu chọn help -> install new software
Tại cửa sổ Install hiện ra, click vào button add sẽ hiện ra tiếp 1 cửa sổ con nữa
tên là add repository, tại hộp textbox location, điền vào đường dẫn sau :
Trung tâm Đào tạo E-Learning Cơ hội học tập cho mọi người
Lập trình thiết bị di động - Bài 8 Trang 13
“http://download.eclipse.org/egit/updates”
Mục name là để điền tên (ta tự đặt) cho gói cài, chúng ta có thể bỏ trống, sau
đó chọn OK.
Sau khi chọn ok sẽ hiện ra bảng chọn các mục sẽ được cài đặt, ở đây ta chọn
cả 2 mục “Eclipse Git Team Provider” và “JGIT”, sau đó chọn next =>…=>
next => finish.
Bước 2 : Import các project của AndEngine thành các thư viện của mình
Trong giao diện eclipse, chọn file => import => chọn thư mục Git => project
from git => URI, lúc này sẽ hiện ra cửa sổ có tên import projects from git nhập
vào url sau vào text box URI :
"https://github.com/nicolasgramlich/AndEngine"
Chọn tiếp next => next ... cho đến khi finish và chờ chương trình download
xong thư viện. Sau khi download về xong, project thường sẽ có lỗi, đó là do
chưa xét Platform hoặc chưa cài đặt trình biên dịch cho nó, thường thì nó sẽ có
lỗi dấu chấm than màu đỏ như hình:
Trung tâm Đào tạo E-Learning Cơ hội học tập cho mọi người
Lập trình thiết bị di động - Bài 8 Trang 14
Lúc này bạn cần chọn vào project mới import, click chuột phải chọn Properties
(hoặc tổ hợp phím Alt + Enter) và làm như sau :
Ở mục Android chọn platform Android 4.0, tick vào ô is Library, ấn OK
Ở mục Java Buil Path, tab order and export, chọn tất cả và ấn OK
Ở mục Java Compiler, chọn như hình, lưu ý chỗ khoanh đỏ nếu có dấu tick
thì bỏ đi (sẽ tự động tick lại khi build), còn nếu chưa có thì tick vào, sau đó
chọn Ok.
Trung tâm Đào tạo E-Learning Cơ hội học tập cho mọi người
Lập trình thiết bị di động - Bài 8 Trang 15
Click chuột phải vào project, chọn build project (hoặc tổ hợp Ctrl + B) để
build lại các file của project.
Như vậy đã import thành công thư viện này.
Trên đây là thư viện cơ bản nhất, để có thể sử dụng đầy đủ các tính năng của
AndEngine, chúng ta cần build thêm các thư viện khác bao gồm cả ví dụ. Dưới
đây là các đường link của các project đó :
1. https://github.com/nicolasgramlich/AndEngineScriptingExtension.git
2. https://github.com/nicolasgramlich/AndEngineAugmentedRealityExtension.git
3. https://github.com/nicolasgramlich/AndEngineMODPlayerExtension.git
4. https://github.com/nicolasgramlich/AndEngineSVGTextureRegionExtension.git
5. https://github.com/nicolasgramlich/AndEnginePhysicsBox2DExtension.git
6. https://github.com/nicolasgramlich/AndEngineTexturePackerExtension.git
7. https://github.com/nicolasgramlich/AndEngineMultiplayerExtension.git
8. https://github.com/nicolasgramlich/AndEngineLiveWallpaperExtension.git
9. https://github.com/nicolasgramlich/AndEngineTMXTiledMapExtension.git
10.https://github.com/nicolasgramlich/AndEngineExamples.git
Khi tiến hành import cái AndEngineExample trước 9 gói còn lại ta sẽ thấy báo
lỗi vì cái project này đã kế thừa các project còn lại, vì thế nên tiến hành import
9 cái kia trước, cái Example để sau cùng, Sau khi cài đặt thì project này vẫn sẽ
bị lỗi, lỗi này là lỗi lập trình, tiến hành sửa như sau:
Trung tâm Đào tạo E-Learning Cơ hội học tập cho mọi người
Lập trình thiết bị di động - Bài 8 Trang 16
Mở Package org.andengine.examples:
trong lớp Class BoundCameraExample.java:
- Dòng số 220, câu lệnh:
final AnimatedSprite face = new AnimatedSprite(pX, pY, this.mBoxFaceTextureRegion,
this.getVertexBufferObjectManager()).animate(100);
chuyển thành:
final AnimatedSprite face = new AnimatedSprite(pX, pY, this.mBoxFaceTextureRegion,
this.getVertexBufferObjectManager());
face.animate(100);
Trong lớp Class HullAlgorithmExample.java:
- Dòng số 11, câu lệnh:
import org.andengine.entity.primitive.vbo.DrawMode;
chuyển thành:
import org.andengine.entity.primitive.DrawMode;
Trong lớp Class SplitScreenExample.java
- Dòng số 179, câu lệnh:
final AnimatedSprite face = new AnimatedSprite(pX, pY, this.mBoxFaceTextureRegion,
this.getVertexBufferObjectManager()).animate(100);
Chuyển thành :
final AnimatedSprite face = new AnimatedSprite(pX, pY, this.mBoxFaceTextureRegion,
this.getVertexBufferObjectManager());
face.animate(100);
Trong lớp Class TextBreakExample.java
- Dòng số 106, câu lệnh :
this.mText = new Text(50, 40, this.mFont, "", 1000, new TextOptions(AutoWrap.LETTERS,
AUTOWRAP_WIDTH, Text.LEADING_DEFAULT, HorizontalAlign.CENTER),
vertexBufferObjectManager);
Chuyển thành :
Trung tâm Đào tạo E-Learning Cơ hội học tập cho mọi người
Lập trình thiết bị di động - Bài 8 Trang 17
this.mText = new Text(50, 40, this.mFont, "", 1000, new TextOptions(AutoWrap.LETTERS,
AUTOWRAP_WIDTH, HorizontalAlign.CENTER, Text.LEADING_DEFAULT),
vertexBufferObjectManager);
Bước 3 : Sử dụng các thư viện trên vào project của mình.
Click vào project cần thêm thư viện, ấn alt + enter hoặc click chuột phải chọn
properties, chọn Java Build Path, chọn tab Projects, chọn Add và thêm thư viện
mà bạn muốn sử dụng kèm vào.
b) Xây dựng chương trình
Các bước thực hiện chương trình:
Bước 1. Tạo 1 project mới tên “TowerOfHanoi”, tên activiy mới này là
“TowerOfHanoiActivity”.
Bước 2. Thêm thư viện AndEngine vào project, Right-click trên project =>
Properties => Android như hình bên dưới, click Add và thêm thư viện AndEngine
vào và click Apply.
Bước 3: Soạn thảo mã lệnh
Trung tâm Đào tạo E-Learning Cơ hội học tập cho mọi người
Lập trình thiết bị di động - Bài 8 Trang 18
Mở TowerOfHanoiActivity.java, thay vì activity này thừa kế từ class Activity,
ta sửa lại để nó thừa kế từ class SimpleBaseGameActivity và thêm vào các
import sau:
import org.andengine.ui.activity.SimpleBaseGameActivity;
import org.andengine.engine.options.EngineOptions;
import org.andengine.entity.scene.Scene;
SimpleBaseActivity cung cấp các phương thức để callback và chứa mã
lệnh để hoạt động với vòng đời của Activity. Mỗi callback cung cấp một
mục đích khác nhau, và do thừa kế từ SimpleBaseActivity nên phải
override lại các method đó.
onCreateEngineOptions: hàm này được gọi khi tạo một instance của engine.
onCreateResources: đây là chức năng sẽ tải tất cả các tài nguyên cần thiết của
Activity vào VRAM.
onCreateScene: hàm này sẽ được gọi khi 2 hàm trên thực hiện xong. Đây là nơi
sẽ khởi tạo các cảnh của game và sử dụng các cấu trúc đã được load vào VRAM.
Thêm đoạn code khai báo các biến sau vào TowerOfHaNoi class
private static int CAMERA_WIDTH = 800;
private static int CAMERA_HEIGHT = 480;
Hai biến trên định nghĩa kích thước của camera mà engine sử dụng.
Thêm các import sau để có thể viết code tạo instance cho engine:
import org.andengine.engine.camera.Camera;
import org.andengine.engine.options.ScreenOrientation;
import org.andengine.engine.options.resolutionpolicy.RatioResolutionPolicy;
Thay thế nội dung của hàm onCreateEngineOptions bằng đoạn code sau:
final Camera camera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
return new EngineOptions(true, ScreenOrientation.LANDSCAPE_FIXED,
new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), camera);
đoạn code trên sẽ tạo một instance của camera, sau đó ta sẽ dùng đối tượng
camera này để tạo đối tượng EngineOption. Các tham số cần để khởi tạo đối
tượng EngineOptions là:
FullScreen: kiểu boolean dùng để xác định engine có được FullScreen hay
không.
Trung tâm Đào tạo E-Learning Cơ hội học tập cho mọi người
Lập trình thiết bị di động - Bài 8 Trang 19
ScreenOrientation: xác định hướng của màn hình khi game chạy.
ResolutionPolicy: xác định độ mở rộng sử dụng tài nguyên khi thay đổi kích
thước màn hình.
Camera: định nghĩa chiều dài và rộng của màn chơi cuối.
Vì Android có rất nhiều thiết bị và kích thước màn hình, nên sẽ không biết
trước kích thước màn hình sẽ được sử dụng. AndEngine đưa ra một giải pháp
duy nhất đó là sẽ mở rộng màn hình của game.
Ví dụ nếu game được thiết kế với độ phân giản 480×320 và được chạy trên màn
hình 800×400, AndEngine sẽ tự động giãn màn hình game ra đến kích thước
720×480 với margin là 80px. Như vậy AndEngine sẽ giữ nguyên tỉ lệ của game.
Bước 4: Load Game Assets vào VRAM
Bạn cần đưa các ảnh của trò chơi vào thư mục assets của project:
ảnh “background.png” ảnh “tower.png”
ảnh “ring1.png” ảnh “ring2.png” ảnh “ring3.png”
Để load các tài nguyên, ta đến method onCreateResources, thay thế nội dung
của hàm hiện tại bằng nội dung sau:
try {
// 1 - Set up bitmap textures
Trung tâm Đào tạo E-Learning Cơ hội học tập cho mọi người
Lập trình thiết bị di động - Bài 8 Trang 20
ITexture backgroundTexture = new
BitmapTexture(this.getTextureManager(), new IInputStreamOpener() {
@Override
public InputStream open() throws IOException {
return getAssets().open("gfx/background.png");
}
});
ITexture towerTexture = new BitmapTexture(this.getTextureManager(),
new IInputStreamOpener() {
@Override
public InputStream open() throws IOException {
return getAssets().open("gfx/tower.png");
}
});
ITexture ring1 = new BitmapTexture(this.getTextureManager(), new
IInputStreamOpener() {
@Override
public InputStream open() throws IOException {
return getAssets().open("gfx/ring1.png");
}
});
ITexture ring2 = new BitmapTexture(this.getTextureManager(), new
IInputStreamOpener() {
@Override
public InputStream open() throws IOException {
return getAssets().open("gfx/ring2.png");
}
});
ITexture ring3 = new BitmapTexture(this.getTextureManager(), new
IInputStreamOpener() {
@Override
public InputStream open() throws IOException {
return getAssets().open("gfx/ring3.png");
}
});
// 2 - Load bitmap textures into VRAM
backgroundTexture.load();
towerTexture.load();
ring1.load();
ring2.load();
ring3.load();
} catch (IOException e) {
Debug.e(e);
}
Sau khi thay đổi nội dung của hàm ở trên bạn cần phải add thêm các import:
import org.andengine.opengl.texture.ITexture;
import org.andengine.opengl.texture.bitmap.BitmapTexture;
import org.andengine.util.adt.io.in.IInputStreamOpener;
import org.andengine.util.debug.Debug;
import java.io.IOException;
import java.io.InputStream;
Trong hàm onCreateResources, ta tạo một đối tượng kiểu ITexture. ITexture là
một interface, và đối tượng được khởi tạo là BitmapTexture, được dùng để load
Trung tâm Đào tạo E-Learning Cơ hội học tập cho mọi người
Lập trình thiết bị di động - Bài 8 Trang 21
bitmap của gam vào VRAM. Đoạn code khởi tạo ITexture ở trên dùng cho tất
cả các tài nguyên download và load tất cả vào VRAM.
Bước 5: Tạo màn của game
Chúng ta thêm import này vào TowerOfHaNoiActivity class:
import org.andengine.entity.sprite.Sprite;
Tiếp theo là thay thế nội dung method onCreateScene bằng các lệnh:
// 1 - Create new scene
final Scene scene = new Scene();
Sprite backgroundSprite = new Sprite(0, 0, this.mBackgroundTextureRegion,
getVertexBufferObjectManager());
scene.attachChild(backgroundSprite);
return scene;
đoạn code ở trên đầu tiên tạo một Scene object, sao đó tạo một Sprite object có
tên backgroundSprite và gắn vào scene. Method này yêu cầu trả về một scene
object. Sprite object là một đối tượng chứa nhiều layers, mỗi layer chứa nhiều
sprites (TextureRegions).
Khi khởi tạo một sprite object cần truyền vào các tham số sau:
xCoordinate: xác định vị trí của sprite th trục X. Hệ thống tọa độ của
AndEngine có trục tọa độ nằm ở vị trí trái-trên của màn hình.
yCoordinate: xác định vị trí của sprite theo trục Y.
TextureRegion: định nghĩa một phần texture của sprite dùng để vẽ chính nó.
VertexBufferObjectManager: Vertex buffer có thể được hiểu như một mảng
lưu có tọa độ của texture. Các tọa độ này được truyền cho OpenGL ES pipeline
và cuối cùng định nghĩa những gì sẽ được vẽ. VertexBufferObjectManager
chứa tất cả các điểm sẽ được vẽ lên màn hình.
Bước 6: Dựng 3 trụ trong game
Thêm 3 biến sau vào TowerOfHaNoiActiviy class:
private Sprite mTower1, mTower2, mTower3;
Thêm đoạn code sau vào hàm onCreateScene (phía trước lệnh return)
// 2 - Add the towers
mTower1 = new Sprite(192, 63, this.mTowerTextureRegion,
getVertexBufferObjectManager());
mTower2 = new Sprite(400, 63, this.mTowerTextureRegion,
getVertexBufferObjectManager());
Trung tâm Đào tạo E-Learning Cơ hội học tập cho mọi người
Lập trình thiết bị di động - Bài 8 Trang 22
mTower3 = new Sprite(604, 63, this.mTowerTextureRegion,
getVertexBufferObjectManager());
scene.attachChild(mTower1);
scene.attachChild(mTower2);
scene.attachChild(mTower3);
Lúc này khi chạy chương trình sẽ thấy giao diện như sau
Bước 7: Thêm các vòng vào trụ
Để tạo các vòng trong, ta cần phải tạo một class thừa kế từ class Sprite.
Đầu tiên, tạo một class có tên Ring trong package com.tutorial.towerofhanoi
thừa kế trực tiếp từ org.andengine.entity.sprite.Sprite
Nội dung của class Ring vừa tạo như sau
private int mWeight;
private Stack mStack; //this represents the stack that this ring
belongs to
private Sprite mTower;
public Ring(int weight, float pX, float pY, ITextureRegion
pTextureRegion, VertexBufferObjectManager
pVertexBufferObjectManager)
{
super(pX, pY, pTextureRegion, pVertexBufferObjectManager);
this.mWeight = weight;
}
public int getmWeight()
{
return mWeight;
}
public Stack getmStack()
{
return mStack;
Trung tâm Đào tạo E-Learning Cơ hội học tập cho mọi người
Lập trình thiết bị di động - Bài 8 Trang 23
}
public void setmStack(Stack mStack)
{
this.mStack = mStack;
}
public Sprite getmTower()
{
return mTower;
}
public void setmTower(Sprite mTower)
{
this.mTower = mTower;
}
Sau khi có class Ring, bây giờ ta cần tạo 3 vòng để thêm vào các trụ. Để làm
được, thêm đoạn code sau vào ngay phía trên lệnh return.
// 3 - Create the rings
Ring ring1 = new Ring(1, 139, 174, this.mRing1,
getVertexBufferObjectManager());
Ring ring2 = new Ring(2, 118, 212, this.mRing2,
getVertexBufferObjectManager());
Ring ring3 = new Ring(3, 97, 255, this.mRing3,
getVertexBufferObjectManager());
scene.attachChild(ring1);
scene.attachChild(ring2);
scene.attachChild(ring3);
Lúc này, khi chạy game, sẽ có giao diện như sau:
Bước 8: Viết mã lệnh xử lý thao tác người chơi
Thêm 3 biến sau vào TowerOfHaNoiActivity class:
private Stack mStack1, mStack2, mStack3;
Chúng ta phải khởi tạo 3 biến trên trong method onCreateResources:
// 4 - Create the stacks
this.mStack1 = new Stack();
Trung tâm Đào tạo E-Learning Cơ hội học tập cho mọi người
Lập trình thiết bị di động - Bài 8 Trang 24
this.mStack2 = new Stack();
this.mStack3 = new Stack();
Khi game chạy, 3 vòng đều phải nằm ở trụ thứ nhất, để làm được điều này,
thêm đoạn code sau vào method onCreateScene:
// 4 - Add all rings to stack one
this.mStack1.add(ring3);
this.mStack1.add(ring2);
this.mStack1.add(ring1);
// 5 - Initialize starting position for each ring
ring1.setmStack(mStack1);
ring2.setmStack(mStack1);
ring3.setmStack(mStack1);
ring1.setmTower(mTower1);
ring2.setmTower(mTower1);
ring3.setmTower(mTower1);
// 6 - Add touch handlers
scene.registerTouchArea(ring1);
scene.registerTouchArea(ring2);
scene.registerTouchArea(ring3);
scene.setTouchAreaBindingOnActionDownEnabled(true);
Ta cần phải ghi đè (override) hàm onAreaTouch của Sprite class, đây là vị trí
sẽ xử lý logic di chuyển của các vòng. Tuy nhiên, khi di chuyển các vòng giữa
các trụ, ta cũng cần phải kiểm tra xem có bị xung đột với logic của game hay
không, có nghĩa là vòng nhỏ phải nằm trên vòng lớn, không được có ngoại lệ.
Để thực hiện việc kiểm tra này, ta thêm vào TowerOfHaNoiActiviy class hàm
sau.
private void checkForCollisionsWithTowers(Ring ring) {
Stack stack = null;
Sprite tower = null;
if (ring.collidesWith(mTower1) && (mStack1.size() == 0 ||
ring.getmWeight() < ((Ring) mStack1.peek()).getmWeight())) {
stack = mStack1;
tower = mTower1;
} else if (ring.collidesWith(mTower2) && (mStack2.size() == 0 ||
ring.getmWeight() < ((Ring) mStack2.peek()).getmWeight())) {
stack = mStack2;
tower = mTower2;
} else if (ring.collidesWith(mTower3) && (mStack3.size() == 0 ||
ring.getmWeight() < ((Ring) mStack3.peek()).getmWeight())) {
stack = mStack3;
tower = mTower3;
} else {
stack = ring.getmStack();
tower = ring.getmTower();
}
ring.getmStack().remove(ring);
if (stack != null && tower !=null && stack.size() == 0) {
ring.setPosition(tower.getX() + tower.getWidth()/2 -
Trung tâm Đào tạo E-Learning Cơ hội học tập cho mọi người
Lập trình thiết bị di động - Bài 8 Trang 25
ring.getWidth()/2, tower.getY() + tower.getHeight() -
ring.getHeight());
} else if (stack != null && tower !=null && stack.size() > 0) {
ring.setPosition(tower.getX() + tower.getWidth()/2 -
ring.getWidth()/2, ((Ring) stack.peek()).getY() -
ring.getHeight());
}
stack.add(ring);
ring.setmStack(stack);
ring.setmTower(tower);
}
Sau đó ta sẽ override lại method onAreaTouch của class Sprite bằng cách thay
thế các dòng khởi tạo Ring ở onCreateSene (3 dòng đầu tiên của #3) bằng đoạn
code khởi tạo sau:
Ring ring1 = new Ring(1, 139, 174, this.mRing1,
getVertexBufferObjectManager()) {
@Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent, float
pTouchAreaLocalX, float pTouchAreaLocalY) {
if (((Ring) this.getmStack().peek()).getmWeight() !=
this.getmWeight())
return false;
this.setPosition(pSceneTouchEvent.getX() - this.getWidth() / 2,
pSceneTouchEvent.getY() - this.getHeight() / 2);
if (pSceneTouchEvent.getAction() == TouchEvent.ACTION_UP) {
checkForCollisionsWithTowers(this);
}
return true;
}
};
Ring ring2 = new Ring(2, 118, 212, this.mRing2,
getVertexBufferObjectManager()) {
@Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent, float
pTouchAreaLocalX, float pTouchAreaLocalY) {
if (((Ring) this.getmStack().peek()).getmWeight() !=
this.getmWeight())
return false;
this.setPosition(pSceneTouchEvent.getX() - this.getWidth() / 2,
pSceneTouchEvent.getY() - this.getHeight() / 2);
if (pSceneTouchEvent.getAction() == TouchEvent.ACTION_UP) {
checkForCollisionsWithTowers(this);
}
return true;
}
};
Ring ring3 = new Ring(3, 97, 255, this.mRing3,
getVertexBufferObjectManager()) {
@Override
public boolean onAreaTouched(TouchEvent pSceneTouchEvent, float
pTouchAreaLocalX, float pTouchAreaLocalY) {
if (((Ring) this.getmStack().peek()).getmWeight() !=
this.getmWeight())
return false;
this.setPosition(pSceneTouchEvent.getX() - this.getWidth() / 2,
Trung tâm Đào tạo E-Learning Cơ hội học tập cho mọi người
Lập trình thiết bị di động - Bài 8 Trang 26
pSceneTouchEvent.getY() - this.getHeight() / 2);
if (pSceneTouchEvent.getAction() == TouchEvent.ACTION_UP) {
checkForCollisionsWithTowers(this);
}
return true;
}
};
Bây giờ chương trình đã hoàn thành. Bạn hãy chạy và thử di chuyển các vòng
giữa các cột.
Chúc Anh/ Chị học tập tốt!
Recommended