BÁO CÁO MÔN HỌC ĐỒ HỌA MÁY TÍNH TÊN ĐỀ TÀI LẬP TRÌNH GAME DI ĐỘNG SỬ DỤNG THƯ VIỆN ĐỒ HỌA Người hướng dẫn: PGS. TS Nguyễn Tấn Khôi NHÓM: 1 Đà Nẵng, 052021 MỤC LỤC DANH MỤC HÌNH VẼ ii 1. CƠ SỞ LÝ THUYẾT 1 1.1. Công cụ phát triển : Framework Flutter và package game Flame 1 1.1.1. Framework Flutter 1 1.1.2. Package hỗ trợ Flame Engine 2 1.2. Cơ sở lý thuyết : Game Loop (Vòng lặp game) 3 1.2.1. Phần Update: 4 1.2.2. Phần Render: 4 1.3. Nhảy trong thể loại game đi cảnh (Platformer Game) 5 2. THIẾT KẾ XÂY DỰNG CHƯƠNG TRÌNH : GAME ANIMAL RUN 7 2.1. Phát biểu bài toán 7 2.1.1. Mô tả đầu vào 7 2.2. Cấu trúc dữ liệu, hoạt động, cấu trúc game 8 2.2.1. Cấu trúc dữ liệu 8 2.2.2. Cấu trúc game 8 2.2.3. Xử lí hoạt động, sự kiện trong game 9 2.3. Tổ chức chương trình 12 2.3.1. Cấu trúc tập tin chương trình và mô tả về những thư mục, tập tin chính. 12 2.3.2. Import thư viện hỗ trợ 13 2.3.3. Tổ chức các tập tin hỗ trợ (hình ảnh, font,…) 13 2.3.4. Tổ chức các tập tin code chính 14 3. KẾT QUẢ THỰC THI 15 3.1. Xuất chương trình ra file apk cho thiết bị Android và cài đặt vào máy 15 3.2. Giao diện chính của trò chơi 16 3.3. Giao diện khi game over và pause game 16 3.4. Nhận xét đánh giá 17 4. KẾT LUẬN VÀ HƯỚNG PHÁT TRIỂN 17 4.1. Kết luận 17 4.2. Hướng phát triển 17 TÀI LIỆU THAM KHẢO 18 PHỤ LỤC …………………………………………………………………………………………………...19 DANH MỤC HÌNH VẼ Hình 1: Tổng quan về kiến trúc của tầng UI và Engine của Flutter 1 Hình 2: Package Flame 2 Hình 3: Game BWO được lập trình từ package Flame dành cho Flutter 2 Hình 4: Mô tả về một vòng lặp game mobile cơ bản 3 Hình 5: Ví dụ minh họa về Phần Update về cấp độ xuất hiện kẻ thù dựa vào số điểm của người chơi 4 Hình 6: Các đối tượng được thêm vào màn hình chơi 4 Hình 7: Các đối tượng được thêm vào sẽ được thêm vào một tập hợp các đối tượng theo thứ tự 5 Hình 8: Thực hiện vẽ các đối tượng, phần render sẽ thực hiện vẽ từng đối tượng từ tập hợp đó 5 Hình 9: Minh họa về thuật toán nhảy, xử lý tính toán 5 Hình 10: Tiến hành cài đặt nhảy vào trong game 6 Hình 11: Tập hình ảnh về nhân vật chính player gồm tập hợp các thứ tự theo hành động: đứng yên, chạy, nhảy, bị đau cho việc tạo hình động 7 Hình 12: Tập hình ảnh về các kẻ thù enemy theo sheet, dùng để tạo hình động trong trò chơi 7 Hình 13: Tập hình ảnh layer dùng để xây dựng ảnh parallax 8 Hình 14: Minh họa về các xếp ảnh parallax gồm các layer 8 Hình 15: Font hỗ trợ Press Start 2P dùng cho font chữ của HUB 8 Hình 16: Cấu trúc dữ liệu OrderedSet kiểu Componet cho việc render componet 8 Hình 17: Cấu trúc của game 9 Hình 18: Event onTapDown kèm với event nhảy trong game 9 Hình 19: Hiệu ứng nhảy của nhân vật player 10 Hình 20: Xử lí sự kiện khi nhân vật tiếp đất 10 Hình 21: Loạt hiệu ứng khi player chạm vào enemy, p1: Xử lí khoảng cách chạm, p2: Sự kiện khi nhân vật bị chạm, p3: Loạt hoạt ảnh của nhân vật khi chạm, p4: Giao diện hub GameOver 11 Hình 22: Cấu trúc tập tin của chương trình 12 Hình 23: Khai báo các thư viện hỗ trợ 13 Hình 24: Thư mục assets dùng để chứa các tập tin hỗ trợ về hình ảnh, font chữ 13 Hình 25: Thư mục lib chứa source code chính của trò chơi 14 Hình 26: Thực hiện câu lệnh flutter build apk để release game ra file apk để cài đặt vào máy 15 Hình 27: Game được cài vào thiết bị Android (Xiaomi Mi 9) 15 Hình 28: Giao diện chính của game 16 Hình 29: Giao diện khi gameover và pause game 16 1. CƠ SỞ LÝ THUYẾT 1.1. Công cụ phát triển : Framework Flutter và package game Flame 1.1.1. Framework Flutter Là framework crossplatform dùng để xây dựng ứng dụng trên thiết bị di động, web, windows với hiệu suất cao, chất lượng tốt cho đa nền tảng do Google phát triển, viết bằng ngôn ngữ Dart, vừa có Ahead of Time của static type language, complier xong mới chạy, vừa có Just In Time như các dynamic type language. Khi lập trình, vừa sử dụng Just In Time để load lại các thay đổi, khi build sản phẩm thì dùng Ahead of Time để tối ưu hiệu năng như việc sử dụng code native. Chính vì điều đó khiến Dart cho một hiệu năng vượt trội. Hình 1: Tổng quan về kiến trúc của tầng UI và Engine của Flutter Lớp Engine của Flutter được xây dựng bằng ngôn ngữ CC++ nên nó cho khả năng tối ưu, tốc độ xử lý đem lại hiệu suất cao chính vì vậy Flutter ngoài phát triển các ứng dụng đa nền tảng còn có thể sử dụng để làm game di động vì sức mạnh từ lớp Engine của nó. Có thể dùng Flutter để làm game. 1.1.2. Package hỗ trợ Flame Engine Flame là một module game engine Flutter cung cấp giải pháp lập trình game bằng Framework Flutter. Tận dụng lợi thế về mặt cấu trúc, sức mạnh hạ tầng cung cấp bởi Flutter nhưng đơn giản hóa câu lệnh cần để xây dựng dự án. Hình 2: Package Flame Cung cấp các thành phần cơ bản cần thiết cho lập trình game như hình ảnh, sprites, sprites sheet, animation và hệ thống gồm component khác nhau. Hình 3: Game BWO được lập trình từ package Flame dành cho Flutter 1.2. Cơ sở lý thuyết : Game Loop (Vòng lặp game) Vòng lặp (Game loop) là một trong yếu tố cực kỳ quan trọng của một trò chơi. Là một tập hợp các câu lệnh để thiết bị chạy đi lặp đi lặp lại Các tựa game thường có một thông số gọi là Khung hình trên giây (FPS), nghĩa ra nếu tựa game của ta chạy ở 60 khung hình trên 1 giây thì thiết bị đang chơi game đó đang thực hiện vòng lặp game 60 lần trên 1 giây. Hiểu đơn giản: 1 khung hình = 1 lần chạy vòng lặp game. Một vòng lặp game dành cho thiết bị di động gồm 2 phần: update và render, ngoài ra đối với game dành cho cả web, desktop gồm 3 phần: resize (cho việc thay đổi kích thước cửa sổ web, desktop), update và render. Trong bài báo cáo này, ta xem xét vòng lặp cho thiết bị di động.
TRƯỜNG ĐẠI HỌC BÁCH KHOA KHOA CÔNG NGHỆ THÔNG TIN BÁO CÁO MƠN HỌC ĐỒ HỌA MÁY TÍNH TÊN ĐỀ TÀI LẬP TRÌNH GAME DI ĐỘNG SỬ DỤNG THƯ VIỆN ĐỒ HỌA Người hướng dẫn: PGS TS Nguyễn Tấn Khôi NHĨM: Đà Nẵng, 05/2021 MỤC LỤC DANH MỤC HÌNH VẼ CƠ SỞ LÝ THUYẾT 1.1 Công cụ phát triển : Framework Flutter package game Flame 1.1.1 Framework Flutter - Là framework cross-platform dùng để xây dựng ứng dụng thiết bị di động, web, windows với hiệu suất cao, chất lượng tốt cho đa tảng Google phát triển, viết ngôn ngữ Dart, vừa có Ahead of Time static type language, complier xong chạy, vừa có Just In Time dynamic type language Khi lập trình, vừa sử dụng Just In Time để load lại thay đổi, build sản phẩm dùng Ahead of Time để tối ưu hiệu việc sử dụng code native Chính điều khiến Dart cho hiệu vượt trội Hình 1: Tổng quan kiến trúc tầng UI Engine Flutter - Lớp Engine Flutter xây dựng ngơn ngữ C/C++ nên cho khả tối ưu, tốc độ xử lý đem lại hiệu suất cao Flutter ngồi phát triển ứng dụng đa tảng cịn sử dụng để làm game di động sức mạnh từ lớp Engine Có thể dùng Flutter để làm game 1.1.2 Package hỗ trợ Flame Engine - Flame module game engine Flutter cung cấp giải pháp lập trình game Framework Flutter Tận dụng lợi mặt cấu trúc, sức mạnh hạ tầng cung cấp Flutter đơn giản hóa câu lệnh cần để xây dựng dự án Hình 2: Package Flame - Cung cấp thành phần cần thiết cho lập trình game hình ảnh, sprites, sprites sheet, animation hệ thống gồm component khác Hình 3: Game BWO lập trình từ package Flame dành cho Flutter 1.2 Cơ sở lý thuyết : Game Loop (Vòng lặp game) - - Vòng lặp (Game loop) yếu tố quan trọng trò chơi Là tập hợp câu lệnh để thiết bị chạy lặp lặp lại Các tựa game thường có thơng số gọi Khung hình giây (FPS), nghĩa tựa game ta chạy 60 khung hình giây thiết bị chơi game thực vịng lặp game 60 lần giây Hiểu đơn giản: khung hình = lần chạy vòng lặp game Một vòng lặp game dành cho thiết bị di động gồm phần: update render, game dành cho web, desktop gồm phần: resize (cho việc thay đổi kích thước cửa sổ web, desktop), update render Trong báo cáo này, ta xem xét vòng lặp cho thiết bị di động Hình 4: Mơ tả vòng lặp game mobile 1.2.1 Phần Update: - Xử lý chuyển động đối tượng nhân vật, kẻ thù, chướng ngại vật, đồ phần khác điếm Hình 5: Ví dụ minh họa Phần Update cấp độ xuất kẻ thù dựa vào số điểm người chơi - Hầu hết kiện xảy đây, ví dụ xử lý kiện, tính tốn kẻ thù bị trúng đạn nhân vật chạm vào kẻ thù 1.2.2 Phần Render: - Là phần vẽ toàn đối tượng có hình, q trình riêng biệt thứ đồng theo liệu, đầu vào Hình 6: Các đối tượng thêm vào hình chơi Hình 7: Các đối tượng thêm vào thêm vào tập hợp đối tượng theo thứ tự Hình 8: Thực vẽ đối tượng, phần render thực vẽ đối tượng từ tập hợp 1.3 Nhảy thể loại game cảnh (Platformer Game) - Đối với thể loại game cảnh nói chung, nhảy kiện thiếu, áp dụng phương trình số biến vật lí tính tồn phần update game loop Hình 9: Minh họa thuật tốn nhảy, xử lý tính tốn - Ban đầu cần xác định vị trí gốc, vận tốc trọng lực khai báo tùy vào game, phần update game loop thực loại kiện tương tự (tiếp nhận kiện chạm vào screen hay joystick, phát - chạm vào đối tượng…) Báo cáo nói game thực nhảy theo trục y Trong khoảng thời điểm game update liên tục từ game loop, nhảy kích hoạt, thuộc tính speedY trừ cho lượng size hình để đối tượng di chuyển theo trục Y để nhảy lên, sau thời gian cộng lượng GRAVITY kèm thời gian update đó, dùng để thực hạ dần độ cao nhảy dựa vào GRAVITY, vị trí Y đối tượng thực cộng từ thuộc tính speedY, đối tượng nhảy lên hạ dần tới tiếp đất (isOnGround) vị trị Y quay vị trí ban đầu tiếp đất Hình 10: Tiến hành cài đặt nhảy vào game THIẾT KẾ XÂY DỰNG CHƯƠNG TRÌNH : GAME ANIMAL RUN 2.1 Phát biểu tốn 2.1.1 Mơ tả đầu vào 2.1.1.1 Tập hình ảnh nhân vật Hình 11: Tập hình ảnh nhân vật player gồm tập hợp thứ tự theo hành động: đứng yên, chạy, nhảy, bị đau cho việc tạo hình động 2.1.1.2 Tập hình ảnh kẻ thù enemy Hình 12: Tập hình ảnh kẻ thù enemy theo sheet, dùng để tạo hình động trị chơi 2.1.1.3 Tập tin đối tượng hỗ trợ Hình 13: Tập hình ảnh layer dùng để xây dựng ảnh parallax Hình 14: Minh họa xếp ảnh parallax gồm layer Hình 15: Font hỗ trợ Press Start 2P dùng cho font chữ HUB 2.2 Cấu trúc liệu, hoạt động, cấu trúc game 2.2.1 Cấu trúc liệu - Game Engine hỗ trợ “Tập hợp có thứ tự” OrderedSet kiểu Componet cho phần render, dùng để vẽ Compent thêm vào BaseGame Hình 16: Cấu trúc liệu OrderedSet kiểu Componet cho việc render componet 2.2.2 Cấu trúc game 10 - icon.png: Dùng để làm icon cho game 2.3.4 Tổ chức tập tin code Hình 25: Thư mục lib chứa source code trò chơi - game_screens: Chức tập tin code liên quan tới screen game model: Dùng để chức tập tin code liên quan tới đối tượng sử dụng lặp lặp lại enemy utils: Dùng để chức tập tin code liên quan tới component, controller, file hỗ trợ xuyên suốt game sprite: player, enemy Thơng số: constant main.dart: Setting kiểu hình, hướng xoay hình, chạy ứng dụng 16 KẾT QUẢ THỰC THI - Do game lập trình tảng Windows nên kết báo cáo lấy từ chương trình chạy thiết bị Android 3.1 Xuất chương trình file apk cho thiết bị Android cài đặt vào máy Hình 26: Thực câu lệnh flutter build apk để release game file apk để cài đặt vào máy Hình 27: Game cài vào thiết bị Android (Xiaomi Mi 9) 17 3.2 Giao diện trị chơi Hình 28: Giao diện game 3.3 Giao diện game over pause game Hình 29: Giao diện gameover pause game 18 3.4 Nhận xét đánh giá - Game chạy tốt hầu hết Android, tượng bị drop FPS, giật lag Đảm bảo enemy xuất theo xếp, cài đặt người lập trình KẾT LUẬN VÀ HƯỚNG PHÁT TRIỂN 4.1 Kết luận - Thực lý thuyết, nguyên lý, tận dụng tốt tài nguyên game engine framework cung cấp Hạn chế: Thiếu menu, nhạc cho game sinh động 4.2 Hướng phát triển - Cập nhật lên cửa hang giao diện tựa game hoàn toàn 19 TÀI LIỆU THAM KHẢO Flame: https://flame-engine.org/docs/#/, https://pub.dev/packages/flame Flutter: https://flutter.dev/docs Jump in Game Dev : https://anonyviet.com/lap-trinh-game-bai-2-trong- luc-be-mat-di-chuyen-va-nhay/ 20 PHỤ LỤC - Do tập dự án lớn, nên cập nhật phần play screen đây, lại up vào link github sinh viên: https://github.com/dungngminh/Animal_Run import 'dart:ui'; import 'package:flame/components/parallax_component.dart'; import 'package:flame/components/text_component.dart'; import 'package:flame/game/game.dart'; import 'package:flame/game/base_game.dart'; import 'package:flame/gestures.dart'; import 'package:flame/position.dart'; import 'package:flame/text_config.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:ninja/utils/enemy_manager.dart'; import 'package:ninja/utils/enemy.dart'; import ' /utils/player.dart'; const double groundHeight = 32; AnimalRun animalRun = AnimalRun(); class AnimalRun extends BaseGame with TapDetector, HasWidgetsOverlay { //player Player _player; ParallaxComponent _parallaxComponent; 21 TextComponent _scoreText; int score; Size _size; EnemyManager _enemyManager; AnimalRun() { //init constructor _parallaxComponent = ParallaxComponent( [ ParallaxImage('layer1.png'), ParallaxImage('layer2.png'), ParallaxImage('layer3.png'), ParallaxImage('layer4.png'), ParallaxImage('layer5.png'), ParallaxImage('layer6.png', fill: LayerFill.none), ], baseSpeed: Offset(100, 0), layerDelta: Offset(20, 0), ); _player = Player(); _enemyManager = EnemyManager(); //Score score = 0; _scoreText = TextComponent( score.toString(), config: TextConfig( fontFamily: 'Arcade', 22 fontSize: 30, color: Colors.white, ), ); //Hub pause addWidgetOverlay('Pause', _buildUI()); //add to screen add(_parallaxComponent); add(_player); add(_enemyManager); add(_scoreText); } @override void onTapDown(TapDownDetails details) { super.onTapDown(details); _player.jump(); } @override void onTapUp(TapUpDetails details) { super.onTapUp(details); } @override void resize(Size size) { super.resize(size); 23 this._size = size; _scoreText.setByPosition(Position( (size.width / 2) - (_scoreText.width / 2.1), size.height * 0.05)); } @override void update(double t) { super.update(t); score += (60 * t).toInt(); _scoreText.text = score.toString(); components.whereType().forEach((element) { if (_player.distance(element) < 45) { _player.hit(); } }); if (_player.heart.value = i) ? Icons.favorite : Icons.favorite_border, color: Colors.red, ), ); return Row(children: life); }, ), ], ), ); } void pauseGame() { pauseEngine(); addWidgetOverlay('HubPause', _pauseMenu()); } Widget _pauseMenu() { return Center( child: Material( color: Color(0x00000000), child: Column( children: [ 26 SizedBox( height: _size.height * 0.8 / 2, ), Text( 'Pause', style: TextStyle( fontFamily: 'Arcade', fontSize: 30, color: Colors.white, ), ), IconButton( alignment: Alignment.center, icon: Icon( Icons.play_arrow_rounded, size: 30, color: Colors.white, ), onPressed: () { resumeGame(); }, ), ], ), ), ); } 27 void resumeGame() { removeWidgetOverlay('HubPause'); resumeEngine(); } void gameOver() { pauseEngine(); addWidgetOverlay('GameOverHub', _gameOverHub()); } Widget _gameOverHub() { return Center( child: Material( color: Color(0x00000000), child: Column( children: [ SizedBox( height: _size.height * 0.8 / 2, ), Text( 'Game Over', style: TextStyle( fontFamily: 'Arcade', fontSize: 50, color: Colors.white, ), 28 ), Text( 'Your score is $score', style: TextStyle( fontFamily: 'Arcade', fontSize: 30, color: Colors.white, ), ), IconButton( alignment: Alignment.center, icon: Icon( Icons.replay, size: 30, color: Colors.white, ), onPressed: () { replay(); resumeGame(); removeWidgetOverlay('GameOverHub'); }, ), ], ), ), ); } 29 void replay() { this.score = 0; _player.heart.value = 1; _enemyManager.reset(); components.whereType().forEach((element) { this.markToRemove(element); }); } } 30 ... đầu tiếp đất Hình 10 : Tiến hành cài đặt nhảy vào game THIẾT KẾ XÂY DỰNG CHƯƠNG TRÌNH : GAME ANIMAL RUN 2 .1 Phát biểu tốn 2 .1. 1 Mơ tả đầu vào 2 .1. 1 .1 Tập hình ảnh nhân vật Hình 11 : Tập hình ảnh... dụng đa tảng cịn sử dụng để làm game di động sức mạnh từ lớp Engine Có thể dùng Flutter để làm game 1. 1.2 Package hỗ trợ Flame Engine - Flame module game engine Flutter cung cấp giải pháp lập. .. game file apk để cài đặt vào máy Hình 27: Game cài vào thiết bị Android (Xiaomi Mi 9) 17 3.2 Giao di? ??n trị chơi Hình 28: Giao di? ??n game 3.3 Giao di? ??n game over pause game Hình 29: Giao di? ??n gameover