Với đề tài số 1 là Xây dựng một game nhập vai đơn giản SimpleRPG. Đề tài này cho ta cái nhìn tổng quát nhất về Lập trình hướng đối tượng. Nó cho ta biết cách xây dựng và thiết kế các đối tượng, liên kết chúng với nhau lại như thế nào và cách để hoàn thiện một chương trình là như thế nào.
Khảo sát đặc tả yêu cầu bài toán
Mô tả yêu cầu bài toán
Người chơi điều khiển nhân vật trên bản đồ được lưu trữ trong cấu trúc dữ liệu như mảng hai chiều, với mỗi ô đại diện cho các dạng địa hình khác nhau như đất, cỏ, và nước Trên bản đồ, có quái vật di chuyển và cả nhân vật người chơi đều có chỉ số xác định tình trạng và thể lực như HP, MP, Attack, Defense và Speed Người chơi có thể tấn công quái vật và sử dụng kỹ năng đặc biệt, trong khi quái vật cũng có khả năng tấn công người chơi Ngoài ra, người chơi có thể di chuyển giữa các bản đồ khác nhau (M0, M1, M2 ) hoặc hướng tới kết thúc trò chơi tại vùng END.
Biểu đồ Use Case
1.2.1 Biểu đồ use case tổng quan
1.2.2 Biểu đồ use case phân rã mức 2
Đặc tả Use Case
Start Đưa người chơi vào chơi game
Level Chọn mức độ chơi game dễ hoặc khó
Character Chọn nhân vật để chơi game
Help Hướng dẫn chơi game
STT Thực hiện Hành động
1 User Ấn vào button Start
2 System Hiển thị giao diện
STT Thực hiện Hành động
1 User Ấn vào button Level
2 System Hiển thị giao diện
3 User Chọn 1 trong level: easy và hard
4 System Đưa về giao diện ban đầu
STT Thực hiện Hành động
1 User Ấn vào button Character
2 System Hiển thị giao diện choose
4 System Đưa về giao diện ban đầu
STT Thực Hiện Hành động
1 User Ấn vào button Help
2 System Hiển thị giao diện hướng dẫn chơi
3 User Ấn vào button Restart
4 System Đưa về giao diện ban đầu
Phân tích thiết kế bài toán
Biểu đồ trình tự
Mô tả chi tiết về Use Case Play Game
- Khi bắt đầu chương trình, người chơi sẽ được đưa đến màn hình MenuState có 4 nút chọn:
• Choose : Chọn nhân vật (có 5 nhân vật để người chơi tùy chọn)
• Level : Chọn độ khó cho Game (có 2 mức độ : Easy và Hard)
Bắt đầu trò chơi bằng cách khởi động và thiết lập các đặc tính của nhân vật cùng với mức độ khó Nếu người chơi không thực hiện các cài đặt này, hệ thống sẽ tự động tạo nhân vật là Gao White với mức độ dễ.
- Sau khi Start Game, hệ thống sẽ chuyển sang giao diện chơi game Người chơi có thể nhấn các nút W, A, S, D để di chuyển; nhấn các nút mũi tên Up,
Down, Left, Right để tấn công bằng cách phi đao
Khi người chơi tấn công thành công vào quái vật, họ sẽ nhận được điểm MP Nếu điểm MP lớn hơn 0, tính năng tấn công bằng cầu lửa với sức sát thương cao sẽ được kích hoạt Tuy nhiên, khi cầu lửa bắn trúng quái vật, điểm MP sẽ không được tăng thêm và mỗi lần sử dụng cầu lửa sẽ làm giảm điểm MP.
Trò chơi bao gồm 3 màn chơi, trong đó quái vật khi bị tiêu diệt sẽ rơi ra các vật phẩm Có hai loại vật phẩm: vật phẩm tăng máu và vật phẩm mở màn mới Đối với màn 1 và màn 2, người chơi chỉ cần thu thập đủ số lượng vật phẩm để mở màn mới Đến màn 3, nhân vật cần tấn công và đánh bại Boss để giành chiến thắng.
Khi nhân vật chết hoặc thắng sẽ có 2 lựa chọn : chơi lại hoặc thoát game.
Biểu đồ lớp
Giới thiệu về các class trong biểu đồ
• Game: có chức năng khởi tạo cho các đối tượng quản lý các đổi tượng khác trong chương trình, là lớp cơ sở
• Display: có chức năng tạo ra Frame với các thuộc tính như tên frame, chiều dài, chiều rộng frame
• Handler: tạo ra các phương thức getter, setter cho các đối tượng quan trọng, giúp cho việc quản lý và phát triển chương trình một cách dễ dàng hơn
• GameCamera: có chức năng giữ cho nhân vật luôn ở chính giữa màn hình khi hiển thị
• AudioPlayer: có chức năng quản lý và thêm các hiệu ứng âm thanh cho game
- KeyManager: có chức năng quản lý các ký tự cần dùng từ bàn phím nhập vào
- mouseManager: có chức năng quản lý các hoạt động của chuột như click, vị trí
MenuState là chức năng hiển thị menu trạng thái, cho phép người chơi lựa chọn Nó được khởi tạo và chạy ngay trong lớp Game, đảm bảo rằng đây là trạng thái đầu tiên xuất hiện khi người chơi khởi động chương trình.
Sau khi hoàn tất việc khởi tạo các giá trị cụ thể cho đối tượng và tham khảo hướng dẫn trong Menu, người chơi chỉ cần nhấn nút Start để chương trình chuyển sang lớp tiếp theo, đó là GameState.
Các lớp trên đều là thành phần có vai trò tạo nên lớp Game cơ sở
Giới thiệu về các class trong biểu đồ
• GameState: có chức năng khởi tạo World cho Game và có thể gọi đến
GameState1 nếu đã đáp ứng đủ các yêu cầu của GameState (sang màn mới)
World có vai trò quan trọng trong việc khởi tạo và quản lý các đối tượng trong game, bao gồm Player, Monster, ObjectRPG (như cây cối, xe cộ), Sword và Item (vật phẩm rớt ra khi tiêu diệt Monster) Ngoài ra, World còn quản lý các đối tượng như EntityManager và ItemManager, đồng thời đọc và hiển thị bản đồ từ file txt trong đường dẫn.
• EntityManager: có chức năng quản lý các đối tượng kế thừa từ lớp Entity
• ItemManager: có chức năng quản lý các đối tượng Item
Giới thiệu về các class trong biểu đồ
• Entity: lớp trừu tượng của tất cả vật thể trong chương trình, thể hiện các thao tác cơ bản của một vật thể
• Creature: lớp trừu tượng, thể hiện các thao tác cơ bản của các đối tượng thuộc package Character
Người chơi (Player), được kế thừa từ Creature, có khả năng khởi tạo các thuộc tính riêng Người chơi có thể lựa chọn các nhân vật khác nhau từ menu, và các phương thức cho phép người chơi di chuyển dựa trên dữ liệu từ bàn phím, đồng thời áp dụng các thuật toán va chạm phù hợp.
Các Player được chọn lựa:
Monster, kế thừa từ Creature, có vai trò quan trọng trong việc khởi tạo các thuộc tính cho bản thân Nó bao gồm các phương thức cho phép Monster di chuyển với độ dời ngẫu nhiên Khi nhân vật bước vào khu vực của Monster, thuật toán tìm kiếm sẽ được kích hoạt, đồng thời áp dụng các thuật toán va chạm phù hợp.
Xuất hiện ở tất cả các map
Monster rơi ra vật phẩm tăng hp
Monster có thể rơi ra 1 trong 3 vật phẩm
• Weapon: lớp trừu tượng, thể hiện các thao tác cơ bản của các đối tượng thuộc package Weapon
Sword1, kế thừa từ Sword, có khả năng tạo ra vũ khí bình thường và điều khiển chuyển động của kiếm theo dữ liệu từ bàn phím Khi va chạm với Monster, Sword1 sẽ trừ máu của đối thủ và đồng thời tăng điểm ma pháp (mp) cho người chơi.
Sword2, kế thừa từ Sword, có khả năng tạo ra vũ khí đặc biệt giúp kiếm di chuyển linh hoạt dựa trên dữ liệu từ bàn phím Khi va chạm với quái vật, Sword2 gây ra sát thương cao hơn Sword1 và làm giảm máu của quái vật, đồng thời tiêu tốn điểm ma thuật (mp) của người chơi.
Monster có thể rơi ra một trong 2 vật phẩm
Xuất hiện ở map2 và map3
Monster xuất hiện trong map3
Giữ cờ winFlag, nếu giết được quái vật này sẽ thắng
• StaticEntity: lớp trừu tượng, thể hiện các thao tác cơ bản của các đối tượng thuộc pakage StaticEntity
- ObjectRPG: (kế thừa từ StaticEntity) có chức năng khởi tạo các đối tượng không di chuyển như cây cối, xe cộ, nhà cửa,
Gate là một đối tượng kế thừa từ StaticEntity, có nhiệm vụ khởi tạo cổng dịch chuyển Cổng này được đặt tại các vị trí nhất định và có khả năng chuyển đổi bản đồ khi người chơi đáp ứng đủ các điều kiện quy định trong từng GameState khác nhau.
• EntityManager: lớp quản lý các đối tượng kế thừa từ Entity, có các phương thức hiển thị và kiểm tra va chạm giữa các vật thể
2.2.2 Biểu đồ các lớp và package liên quan
• Package Graphics: xử lý các hình ảnh ban đầu liên quan đến đồ họa
- GameCamera: có chức năng giữ cho nhân vật luôn ở chính giữa màn hình khi hiển thị
- Animation: hiển thị liên tục các hình ảnh với tốc độ speed tạo chuyển động chân thực của các vật thể
- LoadImage: load ảnh từ đường dẫn vào game
- SpriteSheet: trả lại các ảnh load từ LoadImage, cung cấp phương thức crop để cắt ảnh
- Asset: cung cấp tất cả các ảnh dùng cho giao diện đồ họa của Game
Sử dụng các phương thức và đối tượng của 2 lớp SpriteSheet và LoadImage để cắt và chỉnh sửa ảnh
• Package State: cung cấp các State cho chương trình chạy
- MenuState, ChooseState, LevelState, LooseState, HelpState,
WinState, kế thừa từ State, mang đến một giao diện người dùng trực quan với nền tảng và các nút điều hướng, giúp người chơi dễ dàng tương tác và chuyển đổi giữa các State.
GameState, GameState1 và GameState2, được kế thừa từ State, cung cấp giao diện trò chơi chính cho ba bản đồ khác nhau Các cổng Gate có nhiệm vụ điều hướng giữa các GameState, trong khi các phương thức loose và win giúp chuyển đổi giữa GameState và các State khác, cụ thể là WinState và LooseState.
Tile được xây dựng dựa trên nguyên lý lát gạch, trong đó mỗi Tile tương ứng với một viên gạch Class Tile có chức năng khởi tạo nhiều viên gạch với các ID khác nhau Phương thức mặc định isSolid của class này trả về false, nhưng nếu isSolid trả về true, điều đó có nghĩa là Creature không thể đi qua viên gạch đó.
Các lớp như bound, Brick1, Brick2, Grass1, Grass2, v.v được kế thừa từ Tile, cho phép người dùng thiết lập hình ảnh cho từng viên gạch Đồng thời, chúng cũng ghi đè phương thức isSolid để xác định khả năng đi qua của từng loại gạch một cách riêng biệt.
Mỗi Item trong trò chơi có khả năng khởi tạo mới tương ứng với từng loại Monster khác nhau, mang đến những chức năng đa dạng như tăng cường máu hoặc cung cấp các vật phẩm đặc biệt.
Vật phẩm thường, hiện ra trong mọi map nếu giết được Buffalo Monster
Cộng hp cho Player: hp (+80)
Các vật phẩm đặc biệt
Sau khi nhặt sẽ được lưu vào Inventory, có thể mở ra xem tùy ý
- ItemManager: Quản lý các Item với các phương thức thêm, xóa Item
- UIObject: lớp trừu tượng, thể hiện các chức năng cơ bản cho những class kế thừa từ UIObject như tạo đối tượng mới, phương thức onClick
- UIImageButton: (kế thừa từ UIObject) có khả năng khởi tạo các
Button với hình ảnh từ đường dẫn, cung cấp phương thức nhận biết khi Click chuột, điều hướng đến các State khác nhau
- UIBackGround: (kế thừa từ UIObject)có khả năng khởi tạo
- ClickListener: cung cấp phương thức Click cho các class sử dụng
- UIManager: quản lý các đối tượng thuộc package UI với các phương thức như lập một List UIObject và thêm các UIObject
Utils cung cấp phương thức tải file từ đường dẫn đã chỉ định, nhằm tạo thành mảng Tile và hiển thị trên màn hình game, được thực hiện trong lớp World Đồng thời, Utils cũng bao gồm phương thức chuyển đổi từ chuỗi String sang các kiểu số nguyên int.
- AudioClip: lớp trừu tượng, thể hiện các chức năng cơ bản cho những class kế thừa như tạo đối tượng mới và getVolume
- SoundClip: (kế thừa từ AudioClip): tạo hiệu ứng âm thanh cho Game
- MusicClip: (kế thừa từ AudioClip): tạo hiệu ứng âm thanh cho Game
- AudioPlayer: quản lý các đối tượng kế thừa từ AudioPlayer.
Thiết kế chi tiết Pakage và Class
Lớp game tạo ra “xương sống” cho chương trình, tạo ra các đối tượng quản lý các thành phần khác của game
Các biến title, width, height quy định những thông số cho display(chiều dài, độ rộng, tên của Frame)
Trong lập trình trò chơi, biến "running" được sử dụng để xác định trạng thái hoạt động của chương trình; nếu "running" = false, chương trình sẽ thoát Phương thức "display" tạo ra khung cho trò chơi, trong khi "menuState" thiết lập một menu ban đầu cho người chơi lựa chọn "keyManager" và "mouseManager" lần lượt quản lý đầu vào từ bàn phím và chuột Để giữ cho nhân vật ở trung tâm khung hình, "gameCamera" được sử dụng "audioPlayer" đảm nhiệm việc quản lý hiệu ứng âm thanh, còn "handler" giúp tổ chức các thành phần như key, mouse, audio và entity một cách dễ sử dụng Hàm "init()" khởi tạo các đối tượng đã khai báo, "tick()" cập nhật thông số cho tất cả các đối tượng, và "render()" hiển thị chúng trên màn hình theo trạng thái hiện tại Cuối cùng, "run()" là vòng lặp chính để quản lý hoạt động của trò chơi, "start()" đặt "running" = true để bắt đầu chương trình, trong khi "stop()" thiết lập "running" = false để dừng chương trình.
State là một lớp trừu tượng trong lập trình game, với biến isMap xác định loại GameState đang hoạt động, phục vụ cho việc tạo quái trong lớp World Nó bao gồm các phương thức trừu tượng tick() và render(), cùng với các phương thức setState(State) để chuyển đổi giữa các trạng thái và getState() để lấy trạng thái hiện tại.
MenuState kế thừa từ lớp State, tạo ra giao diện menu cho ứng dụng Đối tượng uiManager thuộc lớp UIManager được sử dụng để quản lý các thành phần giao diện người dùng như nền và nút bấm Trong lớp này, uiManager chịu trách nhiệm quản lý nền của MenuState cùng với các nút tương ứng Phương thức tick() được ghi đè từ lớp State, nhằm cập nhật các thông số mới cho MenuState.
- Nếu chọn Start -> new GameState
- Nếu chọn Level -> new LevelState
- Nếu chọn Character -> new ChooseState
- Nếu chọn Help -> new HelpState render(Graphics): hiển thị ra màn hình trạng thái hiện tại của State
GameState inherits from State and is responsible for managing the World object, which creates and loads all essential components of the game, including players, monsters, static entities, and the map.
Biến Color quy định loại nhân vật được chọn trong ChooseState Biến mustHaveItem là biến tĩnh xác định số lượng vật phẩm mà nhân vật cần sở hữu để chuyển sang bản đồ mới UiManager quản lý nút hiển thị Inventory Phương thức tick() được ghi đè từ State, cho phép chuyển sang map2 nếu thu thập đủ vật phẩm bằng cách thiết lập trạng thái mới (setState(new GameState1)), và nếu nhân vật chết, sẽ chuyển sang LooseState Phương thức render(Graphics) hiển thị trạng thái hiện tại của GameState trên màn hình.
GameState1 kế thừa từ State, chứa map2, được gọi sau khi nhân vật đáp ứng được các điều kiện ở GameState
World: đối tượng thuộc lớp World, tạo ra và load tất cả các thành phần trong game chính thức như: player, monster, static entity, map,
Biến color quy định loại nhân vật được chọn ở ChooseState, trong khi mustHaveItem là biến static xác định số lượng vật phẩm cần thiết để chuyển sang bản đồ mới UiManager quản lý nút hiển thị Inventory Phương thức tick() được ghi đè từ State, cho phép người chơi chuyển sang map3 nếu thu thập đủ vật phẩm bằng cách gọi setState(new GameState2); nếu nhân vật chết, trò chơi sẽ chuyển sang LooseState Cuối cùng, phương thức render(Graphics) hiển thị trạng thái hiện tại của GameState1 trên màn hình.
GameState2 kế thừa từ State, chứa map3, được gọi sau khi nhân vật đáp ứng được các điều kiện ở GameState1
World: đối tượng thuộc lớp World, tạo ra và load tất cả các thành phần trong game chính thức như: player, monster, static entity, map,
Trong trò chơi, màu sắc xác định loại nhân vật được chọn tại ChooseState Phương thức tick() được ghi đè từ State, nếu người chơi tiêu diệt Boss, điều này sẽ đạt điều kiện chiến thắng và chuyển sang trạng thái WinState Phương thức render(Graphics) sẽ hiển thị trạng thái hiện tại của GameState2 trên màn hình.
In the World class, the spawnX and spawnY variables define the player's spawn location on the map The tiles array, a two-dimensional structure, holds the map information converted to integers Several timing variables, including lastAttackTimer, timeCounter, attackCoolDown, and attackTimer, regulate the lifespan of weapons used in the makeBullet() method The isShoot variable determines whether a weapon can be created, allowing it to be instantiated only when isShoot is false Additionally, the entityManager maintains a list of entities added to the World.
ItemManager: List Item được thêm vào World
The Constructor initializes the World with a specified path to a text file containing the map, character type, player HP, and MP The tick() method updates the statistics for all objects managed by the World The render(Graphics) function displays the current state of the World on the screen, drawing the map based on data received from the getTile function The makeBullet(float, float) method creates a new weapon at the given x and y coordinates The loadWorld(String) method reads the map file from the specified path, converting the values from String to int Finally, the getTile(int, int) function returns the Tile corresponding to the ID of the value Tile[x][y].
An Entity serves as an abstract class that defines key properties for objects in a system It includes bounds, represented as rectangles for each object, which are essential for collision detection algorithms The 'active' variable determines the object's existence; if set to false, the object is removed from the environment Key methods include tick(), render(), and die(), which are abstract and must be implemented in derived classes The method checkEntityCollision(int, int) returns true if two entities collide, and false otherwise Additionally, getCollisionBounds(float, float) provides the bounding square of a specific object.
Creature là một lớp trừu tượng trong lập trình game, với phương thức collisionWithTile(int, int) trả về true nếu Tile tại vị trí (x, y) là solid Phương thức moveX() đảm bảo rằng nhân vật không thể di chuyển ngang qua các Tile solid, trong khi moveY() thực hiện điều tương tự cho chuyển động dọc Cuối cùng, phương thức move() tổng quát hóa việc ngăn chặn nhân vật đi qua các Tile solid.
The Player class inherits from the Creature class and includes properties such as animDown, animUp, animLeft, and animRight for animation of movements It features an mp variable to manage the Player's mana and an Inventory object to store and display special items consumed by the character The constructor initializes a new Player object at coordinates (x, y) with a specified character color, health, and mana The getInput() method captures keyboard input to set the Player's movement, while postRender() is responsible for drawing the Inventory The getHpBar() and getMpBar() methods return BufferedImages representing the Player's health and mana, respectively Lastly, getCurrentAnimationFrame() provides a BufferedImage of the Player's visual state at a specific moment.
Inventory is a component of the Player Class that creates a List Item to track items collected by the player across various states, displaying these items through the Inventory Table The active variable determines the visibility of the Inventory Table; if active is set to false, it will not be displayed, and vice versa The inventoryItem is a list of items that need to be managed and shown The constructor initializes a new Inventory object, while the tick() method updates the active status The addItem() function adds a new item to the Inventory, increasing the count if the item already exists Finally, the render() method displays the Inventory when active is true, showing the stored items in each slot of the Inventory Table.
The Monster class inherits from the Creature class and utilizes various animation methods such as animDown, animUp, animLeft, and animRight to create movement animations Key variables like lastMove, moveCoolDown, and moveTimer manage timing and define the seconds before each random movement occurs Additionally, the variable 'r' represents the radius of the area where the monster begins to employ its search algorithm.
Constructor tạo đối tượng Monster tại tọa độ (x, y) với các thông số chiều rộng, chiều cao, loại quái, lượng máu và vật phẩm đi kèm Hàm checkPlayer() dùng để kiểm tra xem Monster có va chạm với Player không, từ đó trừ máu cho Player getInput() sẽ ngẫu nhiên xác định độ dịch chuyển của Monster; nếu nhân vật bước vào khu vực của Monster với bán kính r, thuật toán tìm kiếm sẽ được thực hiện Hàm getHpBar() trả về một BufferedImage tương ứng với lượng máu hiện tại, trong khi getCurrentAnimationFrame() cung cấp hình ảnh trạng thái của Player tại một thời điểm nhất định Cuối cùng, getType() trả về một số nguyên tương ứng với loại quái đã được tạo ra.
Công nghệ và thuật toán sử dụng
Ngôn ngữ lập trình và các nền tảng công nghệ
Nhóm phát triển game 2D nhập vai Gao Ranger đã quyết định sử dụng ngôn ngữ lập trình Java, với lý do "viết một lần, chạy mọi nơi" Java hoạt động lý tưởng trên tất cả các thiết bị và hệ điều hành có cài đặt Java Runtime Environment Được biết đến như một ngôn ngữ lập trình hướng đối tượng mạnh mẽ, Java sở hữu hệ thống thư viện mã nguồn mở phong phú cùng cú pháp rõ ràng, dễ hiểu, giúp việc viết, biên dịch và gỡ lỗi trở nên đơn giản hơn Những ưu điểm này đã thúc đẩy nhóm chọn Java kết hợp với công cụ lập trình IntelliJ cho dự án của mình.
Để lập trình game Gao Ranger bằng ngôn ngữ Java, dự án đã sử dụng nền tảng hiển thị giao diện 2D trên hệ điều hành Windows.
Java AWT (Abstract Window Toolkit) là một API dùng để phát triển ứng dụng GUI trong Java Mặc dù không hiện đại và tối ưu như Java Swing hay JavaFX, nhóm em quyết định sử dụng Java AWT cho bài tập lớn do các tutorial trên YouTube đã cũ và chủ yếu tập trung vào việc làm game 2D Thêm vào đó, dự án còn sử dụng Java để nâng cao tính năng và hiệu suất.
Swing để vẽ khung nền giao diện cùng các thư viện khác như: java.io, java.util, graphics, javax.imageio, javax.sound, java.net
Các bộ thư viện này cung cấp nhiều tính năng và phương thức đã được xây dựng sẵn, giúp đơn giản hóa công việc lập trình phần mềm một cách đáng kể.
Kỹ thuật, cấu trúc dữ liệu và thuật toán
Trong game 2D Gao Ranger, kỹ thuật lập trình hướng đối tượng và xử lý dữ liệu đầu vào là rất quan trọng Để xây dựng giao diện và tính năng hoàn chỉnh, cần phân tích và thiết kế các tính năng cần thiết Học lập trình hướng đối tượng giúp phát triển tư duy phân tích thiết kế hệ thống phần mềm, chia nhỏ tính năng thành các package và class, từ đó tăng năng suất làm việc và dễ dàng quản lý mã nguồn Sử dụng ngôn ngữ Java, lập trình hướng đối tượng giảm bớt khó khăn trong việc thực thi phần mềm, cho phép chuyển đổi ý tưởng thành giao diện thực tế dễ dàng Trong dự án này, các tính chất của kỹ thuật hướng đối tượng như Encapsulation, Inheritance, Overriding và Polymorphism được áp dụng một cách hiệu quả.
Dự án sử dụng kỹ thuật xử lý dữ liệu đầu vào từ hình ảnh để tạo ra giao diện hình ảnh với bản đồ và nhân vật trong game, cho phép chuyển động và tương tác vật lý Để tạo hiệu ứng động, hình ảnh của các đối tượng được vẽ liên tục lên màn hình, thay đổi frame của nhân vật mỗi lần vẽ, mang lại cảm giác di chuyển hoặc tấn công.
Một kỹ thuật quan trọng trong game là sử dụng hệ tọa độ để thực hiện các phép toán Nhờ vào tọa độ, chúng ta có thể kiểm tra va chạm giữa nhân vật và vật thể, xác định vị trí của nhân vật trên bản đồ, cũng như vẽ tất cả các đối tượng lên màn hình một cách chính xác theo vị trí của chúng.
Trong mã nguồn phần mềm, các lập trình viên thường sử dụng nhiều cấu trúc dữ liệu và thuật toán cơ bản như biến, cấu trúc lặp for, foreach, và cấu trúc rẽ nhánh if/else Đặc biệt, cấu trúc ArrayList (List trong Java) được sử dụng phổ biến Về mặt giải thuật, thuật toán va chạm (checkEntityCollision) và thuật toán tìm kiếm đường đi là những thuật toán nổi bật nhất.
Thuật toán va chạm trong game nhằm kiểm tra va chạm vật lý giữa các thực thể, ngăn cản chúng đi xuyên qua nhau và ảnh hưởng đến bước di chuyển Thuật toán này cũng được áp dụng trong các cuộc tấn công của nhân vật Dữ liệu dạng Rectangle được sử dụng để tạo hình chữ nhật ẩn cho nhân vật và các thực thể tĩnh như cây cối Khi hai Rectangle giao nhau, hàm intersects cho phép xác định liệu chúng có chạm nhau hay không, từ đó ngăn cản nhân vật đi vào vùng đó hoặc va chạm với nhân vật khác Ngoài ra, khi Rectangle của nhân vật chạm vào Rectangle của quái, nhân vật sẽ bị trừ máu, và tương tự, khi Rectangle của vũ khí va chạm với quái, quái sẽ bị trừ máu.
Ý tưởng của thuật toán tìm kiếm dựa trên phương thức tìm kiếm đơn giản, bắt đầu bằng việc xác định khoảng cách giữa người chơi và quái vật Nếu khoảng cách này nhỏ hơn giá trị R (bán kính tìm kiếm của quái), quái sẽ phân tích hướng đi và di chuyển về phía người chơi Khi đó, nếu khoảng cách hoành độ lớn hơn tung độ, quái sẽ di chuyển theo phương ngang; ngược lại, nếu khoảng cách tung độ lớn hơn hoành độ, quái sẽ di chuyển theo phương thẳng Giá trị xMove và yMove được sử dụng để biểu diễn phương di chuyển, với giá trị lớn hơn 0 cho biết di chuyển sang phải (xuống) và ngược lại Đối với di chuyển theo phương ngang, nếu hoành độ của quái lớn hơn hoành độ của người, quái sẽ di chuyển sang trái; nếu tung độ của quái lớn hơn tung độ của người, quái sẽ di chuyển lên bằng cách giảm yMove, và ngược lại Trong quá trình di chuyển, quái vẫn phải tuân thủ các yếu tố va chạm.
Xây dựng chương trình minh họa
Kết quả chương trình minh hoạ
Kết quả đạt được bao gồm việc phát triển kỹ năng làm việc nhóm, nâng cao khả năng phân tích, thiết kế và vẽ sơ đồ mô tả đề bài Bên cạnh đó, người học còn phát triển tư duy lập trình hướng đối tượng và lập trình đồ họa thông qua ngôn ngữ Java, đồng thời cải thiện các kỹ năng thiết kế đồ họa cho game.
Bài viết này tập trung vào những chức năng chính của trò chơi, bao gồm khả năng tạo và hiển thị bản đồ cùng các nhân vật, triển khai thuật toán tìm đường giúp quái vật tự động xác định lộ trình ngắn nhất để giao tranh, lựa chọn các nhân vật phù hợp, và phân chia game thành hai cấp độ: dễ và khó.
Giao diện chương trình
• Giao diện khi bấm vào Help (hướng dẫn chơi):
• Giao diện khi bấm vào Character (Click chuột để chọn nhân vật):
• Giao diện khi bấm vào Level (Chọn mức độ dễ, khó):
• Bấm vào Start để bắt đầu chơi game: o Game gồm có 3 map:
▪ Map 1: Khu vực công viên
▪ Khi thu thập đủ item và di chuyển đến cổng dịch chuyển ở cuối map thì sẽ chuyển sang map 2
Kiểm tra item bằng cách nhấn vào inventory ở góc trên bên phải
▪ Khi thu thập đủ item ở map 2 thì khi đi đến cổng chính của bệnh viện sẽ được chuyển qua map 3
▪ Game Over: Khi thua, màn hình sẽ hiển thị ảnh Game over cùng với hai lựa chọn là Restart (trở về Menu) và exit
▪ Sau khi đánh bại boss thì ảnh win hiện lên:
Trong game, các nhân vật và thực thể được thiết kế theo phong cách pixel art, phản ánh các hoạt động cơ bản Người chơi sẽ điều khiển 5 nhân vật khác nhau, trong khi đó, game cũng có các quái vật và boss để tạo thêm thử thách.
Kiểm thử các chức năng đã thực hiện
Các chức năng đã xây dựng trong chương trình:
• Di chuyển và phát hiện va chạm
• Hệ thống tấn công, HP mà Mana của người chơi và quái
• Game over và Win game
4.3.1 Chức năng: Di chuyển và phát hiện va chạm
• Việc di chuyển của nhân vật tốt, mượt mà, không mắc lỗi nhận bàn phím (lưu ý tắt Unikey hoặc chuyển sang tiếng anh)
• Lỗi nhân vật hiện lên trước các StaticEntity khác (render order)
Thuật toán va chạm dựa trên hình chữ nhật (Rectangle) giúp phát hiện va chạm giữa các vật thể Tuy nhiên, đối với những vật thể không phải hình chữ nhật hoặc có hình dạng phức tạp, sẽ xuất hiện những khoảng trống mà người chơi không thể di chuyển vào Chẳng hạn, người chơi có thể di chuyển đến mép của đài phun nước vì vị trí này nằm trong hình chữ nhật.
4.3.2 Chức năng: Hệ thống tấn công, HP, Mana của người chơi và quái
• Hệ thống tấn công hoạt động khá ổn định Khi người chơi hết mana thì không dùng được tấn công đặc biệt
Quái tấn công trừ máu hiệu quả nhưng đơn giản, chỉ cần chạm vào nhân vật để gây mất máu Tuy nhiên, đôi khi quái có thể chạm vào nhân vật mà không làm mất máu Mức độ dễ sẽ giảm thiểu HP mất mát của người chơi, trong khi mức độ khó sẽ làm mất nhiều HP hơn.
4.3.3 Chức năng: Game over và win game
Khi người chơi hết HP, màn hình Game Over sẽ hiển thị cùng với âm thanh đặc trưng, kèm theo hai tùy chọn: Restart để trở về Menu hoặc Exit Game để thoát.
Upon defeating the boss, a celebratory image accompanied by victory music will appear, offering options to return to the menu for a restart or to exit the game.
Kết luận và hướng phát triển
SimpleRPG là một trò chơi đang trong quá trình hoàn thiện và phát triển, vì vậy không thể tránh khỏi một số lỗi kỹ thuật trong quá trình thực hiện Tuy nhiên, đội ngũ phát triển đã thường xuyên kiểm thử và khắc phục lỗi ngay khi phát hiện Sau một thời gian, nhóm đã đưa ra một số kết luận và định hướng phát triển tiếp theo.
+ Chương trình cơ bản có đầy đủ chức năng một game cơ bản như tấn công, di chuyển qua map, thu thập vật phẩm
+ Giao diện dễ nhìn, chất lượng tốt
+ Tương tác tốt với người dùng
Game sử dụng nền tảng Java AWT có giao diện Java với mã GUI gốc của hệ điều hành, do đó sẽ không hoạt động đồng nhất trên tất cả các hệ thống Mã nguồn hiện tại chưa được tối ưu hóa.
+ Một số chức năng chưa hoàn thiện
Với những Ưu điểm và Nhược điểm trên, nhóm đã có một vài hướng phát triển mới cho Game đó là:
- Xử lí tối ưu phần giao diện, hình ảnh
- Thêm chướng ngoại vật khác
- Thêm tính năng tấn công của Boss với nhân vật
Nhóm chúng em đã nỗ lực hết mình, với tất cả các thành viên tích cực hoàn thành nhiệm vụ và không ai lười biếng Bài tập lớn này đã giúp chúng em tích lũy kiến thức, làm việc nhóm và thức đêm để sửa lỗi, nghiên cứu tính năng mới nhằm mang lại sản phẩm tốt hơn Mặc dù game đã khá hoàn thiện, nhóm vẫn muốn phát triển thêm để đáp ứng nhu cầu giải trí cao hơn và hướng đến nhiều đối tượng người chơi.