Arkanoid là trò chơi “đập gạch” cổ điển được phát triển bằng Java Swing với phong cách hiện đại.
Người chơi điều khiển thanh đỡ (Paddle) để bật bóng phá hủy các khối gạch trên màn hình, thu thập các Power-up (vật phẩm tăng sức mạnh) và vượt qua các màn chơi (Map) có độ khó tăng dần.
Dự án được phát triển theo Lập trình Hướng đối tượng (OOP), áp dụng đầy đủ bốn nguyên lý:
- Đóng gói (Encapsulation)
- Kế thừa (Inheritance)
- Đa hình (Polymorphism)
- Trừu tượng hóa (Abstraction)
Phần này tóm tắt cấu trúc dự án và cung cấp một sơ đồ lớp tổng quát (chỉ các lớp đặc trưng) để dễ hình dung mối quan hệ chính giữa các thành phần.
src/Constant— hằng số và tài nguyên (kích thước, ảnh, âm thanh paths).src/entity— các đối tượng trong game (tất cả kế thừaEntity).src/game— engine/scene/GUI:GameEngine,GamePanel,Scenevà cácscenes/*(Menu/GameScene/Pause/GameOver/Win).src/manager— singleton quản lý:BlockManager,PowerUpManager,MapManager,SoundManager.
Xem full HD tại: Xem tại đây
classDiagram
class Scene
class GamePanel
class GameScene
class GameEngine
class Entity
class Ball
class Paddle
class Block
class BlockManager
class PowerUp
class PowerUpManager
class MapManager
class SoundManager
Scene <|-- GameScene
GamePanel --> Scene : contains
GameEngine --> GamePanel : updates / drives loop
GameScene --> Entity : uses
Entity <|-- Ball
Entity <|-- Paddle
Entity <|-- Block
Entity <|-- PowerUp
GameScene --> BlockManager : renders / checks win
BlockManager --> Block : manages
GameScene --> PowerUpManager : spawns / updates
PowerUpManager --> PowerUp : manages
GameScene --> MapManager : loads maps
GameScene --> SoundManager : play sounds
%% notes
class Scene{
+paintComponent()
+setupKeyBindings()
}
class Entity{
+x
+y
+width
+height
+update()
+render()
}
Ghi chú: sơ đồ trên nhằm minh họa luồng dữ liệu và phụ thuộc chính — không liệt kê mọi lớp nhỏ (ví dụ các loại Block/PowerUp cụ thể được coi là các triển khai con của Block/PowerUp).
| Nguyên lý | Ứng dụng trong dự án |
|---|---|
| Encapsulation (Đóng gói) | Các thuộc tính như x, y, velocityX, velocityY được khai báo private, truy cập qua getter/setter. |
| Inheritance (Kế thừa) | BlockBedrock, BlockBomb, BlockLucky kế thừa từ Block. Tương tự các lớp PowerUp kế thừa từ PowerUp cha. |
| Polymorphism (Đa hình) | Phương thức activate() và deactivate() được ghi đè ở từng loại PowerUp với hiệu ứng riêng. |
| Abstraction (Trừu tượng hóa) | Entity và Scene là lớp trừu tượng định nghĩa hành vi chung (update(), render()). |
| Design Pattern | Sử dụng Singleton Pattern trong các lớp MapManager, BlockManager, SoundManager. |
Phần này mô tả ngắn gọn kiến trúc OverlayScene — cơ chế dùng để hiển thị các lớp phủ UI như Pause, GameOver, Win mà không làm xáo trộn logic game core.
Ý tưởng chính:
GamePanellàm container chính và chứaScenehiện tại (thường làGameScene).GameScenevẽ game world (entities, blocks, power-ups). Khi game không ở trạng thái chơi (paused/gameover/win),GameScenevẽ một lớp phủ (translucent overlay) và gọirender()của overlay tương ứng.- Mỗi overlay (Pause, GameOver, Win) là một module chịu trách nhiệm cho UI của trạng thái đó: tạo
JButton, xử lýActionListener, và cung cấp hai phương thức chính:addButtonsToPanel(JPanel panel)— thêm các nút vào panel khi overlay cần hiển thị (có kiểm trabutton.getParent() != panelđể tránh thêm trùng).render(Graphics g)— vẽ bất kỳ nội dung overlay không phải là JButton (ví dụ tiêu đề, hướng dẫn) và gọibutton.setBounds(...)để định vị nút.
Thiết kế này có các ưu điểm:
- Tách biệt: logic game (vật lý, cập nhật) không bị lẫn với UI overlay.
- Đơn giản để mở rộng: thêm overlay mới chỉ cần tuân theo contract trên.
Lifecycle / flow ngắn:
- GameScene phát hiện trạng thái thay đổi (ví dụ ball chết → GAMEOVER).
- GameScene gọi
GameOver.getInstance().addButtonsToPanel(this). - Trong
paintComponent, GameScene vẽ lớp phủ mờ rồi gọiGameOver.render(g)để đặt bounds cho các nút. - Khi chuyển scene hoặc reset, GameScene loại bỏ các nút overlay khỏi panel (ví dụ thông qua một hàm
RemoveAllButton()).
Ghi chú kỹ thuật ngắn:
- Để
button.setBounds(...)có hiệu lực,GameScenedùng layout null (setLayout(null)) vàsetPreferredSize(...)cho kích thước cố định. - Overlay thường được triển khai theo pattern singleton trong repo để giữ một bộ nút duy nhất và tránh tạo/xóa nhiều lần.
Phần này chỉ tập trung vào kiến trúc OverlayScene; các chi tiết như cách reset entity hoặc xử lý key bindings được mô tả ở các phần khác của README hoặc trong mã nguồn.
| Họ và Tên | Nhiệm vụ |
|---|---|
| Đỗ Minh Hiếu | - BlockManager, MapManager, PowerUpManager, SoundManager - Menu, Map, Pause - JUnit tester |
| Nguyễn Quốc Huy | - Multi-threading - Code base - GameScene, GameOver, Win |
| Nguyễn Mạnh Đức | - Paddle - PowerUp - Block |
| Lương Minh Dương | - Ball - Physics |
- Ngôn ngữ: Java 17
- Giao diện: Java Swing
- Đa luồng: Thread + Timer
- IDE: IntelliJ IDEA / VsCode
- Quản lý mã nguồn: GitHub
- Âm thanh: WAV / MP3 (SoundManager)
- Hình ảnh, âm thanh lấy từ: https://www.minecraft.net/en-us