# ĐỌC HIỂU CODE MÔN MÃ NGUỒN MỞ - NGUYỄN MINH DƯƠNG_725105048
# Đoạn code chính thực thi trờ chơi
# 1. **Lớp `Component` - Thành phần cơ bản của trò chơi**
Lớp này định nghĩa các thuộc tính chung của một đối tượng trong trò chơi như kích thước, màu sắc, vị trí và phương thức cập nhật (vẽ lên canvas).
## **Thuộc tính**
- `x, y`: Tọa độ của đối tượng trên canvas.
- `width, height`: Kích thước của đối tượng.
- `color`: Màu sắc của đối tượng (áp dụng nếu không phải ảnh).
- `gameArea`: Đối tượng chứa thông tin khu vực chơi.
- `gameContext`: Lấy đối tượng `context` từ `canvas`, cho phép vẽ lên nó.
- `speedX, speedY`: Tốc độ di chuyển của đối tượng.
- `gravity, gravitySpeed`: Ảnh hưởng của trọng lực lên đối tượng.
## **Phương thức**
### `1.Hàm update()`:
- Vẽ hình chữ nhật lên `canvas` dựa vào tọa độ, màu sắc, kích thước.
- ![Uploading file..._8bqk2lbiv]()
- Đây là phương thức `update()` trong lớp `Component`. Nó có nhiệm vụ vẽ một hình chữ nhật đại diện cho đối tượng trên `canvas`.
---
##### **Phân tích từng dòng**
```javascript
this.gameContext.fillStyle = this.color;
```
- Đặt màu nền (`fillStyle`) cho hình chữ nhật bằng giá trị `this.color`.
- `this.color` được truyền vào khi tạo đối tượng, ví dụ: `"red"`, `"#2CB01A"`
---
```javascript
this.gameContext.fillRect(this.x, this.y, this.width, this.height);
```
- Vẽ một hình chữ nhật màu `this.color` lên `canvas` với:
- `this.x`, `this.y`: Tọa độ góc trên bên trái.
- `this.width`, `this.height`: Kích thước của hình chữ nhật.
- Đây là phần nền của đối tượng.
---
```javascript
this.gameContext.strokeStyle = 'black';
```
- Thiết lập màu viền (`strokeStyle`) của hình chữ nhật thành **màu đen**.
---
```javascript
this.gameContext.lineWidth = 10;
```
- Đặt độ dày của viền là **10px**.
---
```javascript
this.gameContext.strokeRect(this.x, this.y, this.width, this.height);
```
- Vẽ viền màu đen quanh hình chữ nhật với độ dày 10px.
---
##### **Tóm tắt hoạt động của `update()`**
1. Vẽ một hình chữ nhật màu (`fillRect`).
2. Vẽ một viền đen xung quanh hình chữ nhật (`strokeRect`).
3. Hình chữ nhật này sẽ đại diện cho các đối tượng như chướng ngại vật.
---
##### **Tại sao cần `strokeRect`?**
- Nếu chỉ có `fillRect()`, hình sẽ không có viền, trông kém nổi bật.
- `strokeRect()` giúp dễ nhìn thấy đối tượng hơn, đặc biệt khi nền có màu tương tự đối tượng.
📝 **Tóm lại**: Phương thức này giúp hiển thị một đối tượng hình chữ nhật có màu nền và viền đen trên `canvas`. 🚀
**--------------------------------------------------------------------------------------------------------------------------------------------------------**
.....................................................................
### `2.Hàm crashWith(otherObj)`:
- Kiểm tra xem đối tượng hiện tại có va chạm với `otherObj` không bằng cách so sánh tọa độ biên của hai đối tượng.
- Đây là **hàm khởi tạo (`constructor`)** của lớp `Component`. Nó chịu trách nhiệm thiết lập các thuộc tính ban đầu cho một đối tượng game.
---
#### Phân tích từng dòng
##### 2.1 Nhận tham số đầu vào
```javascript
constructor({ gameArea, width, height, color, x, y }) {
```
- Hàm khởi tạo nhận một **đối tượng** chứa các thuộc tính:
- `gameArea`: Khu vực trò chơi (`GameArea`).
- `width`, `height`: Kích thước đối tượng.
- `color`: Màu sắc.
- `x`, `y`: Tọa độ ban đầu trên canvas.
**Lưu ý**: Cú pháp `{ gameArea, width, height, ... }` là **destructuring** để trích xuất các giá trị từ một object.
---
##### 2.2 Gán các giá trị đầu vào cho thuộc tính của đối tượng
```javascript
this.x = x;
this.y = y;
this.width = width;
this.color = color;
this.height = height;
```
- Gán các tham số đầu vào cho đối tượng `this` (đối tượng đang được tạo ra).
- `this.x`, `this.y`: Xác định vị trí trên canvas.
- `this.width`, `this.height`: Xác định kích thước đối tượng.
- `this.color`: Xác định màu sắc của đối tượng.
---
##### 2.3 Lưu tham chiếu đến `GameArea`
```javascript
this.gameArea = gameArea;
this.gameContext = gameArea.canvas.getContext('2d');
```
- `this.gameArea = gameArea;`: Lưu tham chiếu đến `GameArea` để sử dụng sau này.
- `this.gameContext = gameArea.canvas.getContext('2d');`:
- Lấy **context 2D** của `canvas`, cho phép vẽ lên canvas.
- Được sử dụng trong `update()` để vẽ hình.
---
##### 2.4 Khởi tạo các thuộc tính liên quan đến chuyển động
```javascript
this.score = 0;
this.speedX = 0;
this.speedY = 0;
this.gravity = 0;
this.gravitySpeed = 0;
```
- `this.score = 0;`: Điểm số ban đầu là `0`.
- `this.speedX = 0;`: Tốc độ di chuyển theo trục `X`.
- `this.speedY = 0;`: Tốc độ di chuyển theo trục `Y`.
- `this.gravity = 0;`: Trọng lực mặc định là `0`, sau này có thể thay đổi.
- `this.gravitySpeed = 0;`: Tốc độ rơi do trọng lực, khởi tạo bằng `0`.
-> **Giải thích về trọng lực (`gravity`)**
- Nếu `gravity > 0`: Đối tượng rơi xuống dần theo thời gian.
- Nếu `gravity < 0`: Đối tượng bay lên (như khi nhấn phím **Space**).
- `gravitySpeed` sẽ tăng dần, tạo hiệu ứng rơi tự nhiên.
-> **Ví dụ sử dụng gravity trong game:**
```javascript
this.gravity = 0.05; // Trọng lực nhỏ để rơi từ từ.
this.gravitySpeed += this.gravity;
this.y += this.gravitySpeed;
```
-> Mỗi lần cập nhật, `gravitySpeed` tăng lên, khiến nhân vật rơi xuống nhanh hơn.
---
##### Tóm tắt
- Hàm `constructor` **khởi tạo** một đối tượng với:
- **Kích thước**, **màu sắc**, **vị trí** trên `canvas`.
- **Tham chiếu đến `GameArea`** để vẽ lên canvas.
- **Tốc độ di chuyển** (`speedX`, `speedY`) và **trọng lực** (`gravity`, `gravitySpeed`).
🚀 **Tóm lại**: Đây là bước đầu tạo ra một **thực thể (entity) di chuyển được** trong trò chơi! 🎮
---
# 2. **Lớp `MyGamePiece` - Đối tượng điều khiển chính (chim)**
Lớp này kế thừa từ `Component` nhưng thay đổi cách hiển thị từ hình chữ nhật sang hình ảnh con chim.
### **Phương thức**
- `constructor(obj)`: Thay vì vẽ một hình chữ nhật, nó tải hình ảnh (`/static/img/convit.png`) vào `this.img`.
- `update()`: Dùng `drawImage` để vẽ hình ảnh thay vì hình chữ nhật.
- `newPos()`: Cập nhật vị trí mới của chim dựa vào trọng lực và tốc độ.
- `checkHitTop()` và `checkHitBottom()`: Kiểm tra xem chim có vượt quá viền trên hoặc viền dưới màn hình không.
---
# 3. **Lớp `TextComponent` - Hiển thị văn bản (điểm số)**
Lớp này kế thừa `Component` nhưng thay vì vẽ hình chữ nhật, nó hiển thị văn bản lên màn hình.
- `update(text)`: Dùng `fillText` để hiển thị điểm số.
---
# 4. **Lớp `GameArea` - Quản lý toàn bộ trò chơi**
Lớp này điều khiển các thành phần trong game, cập nhật màn hình và xử lý logic trò chơi.
### **Thuộc tính**
- `gameRunning`: Trạng thái trò chơi (đang chạy hay dừng).
- `canvas`: Phần tử HTML `canvas` để vẽ trò chơi.
- `context`: Đối tượng để vẽ lên `canvas`.
- `frameNo`: Đếm số frame đã chạy (dùng để tạo chướng ngại vật).
- `myPiece`: Đối tượng chim mà người chơi điều khiển.
- `myScore`: Đối tượng hiển thị điểm số.
- `myObstacles`: Mảng chứa các chướng ngại vật.
### **Phương thức**
#### `start()`
- Kiểm tra nếu trò chơi đã chạy thì không làm gì.
- Ẩn phần giới thiệu (`bird-running`), tắt nhạc intro.
- Chạy nhạc nền (`maplestory_playing.mp3`).
- Ẩn nút `START GAME`, thêm `canvas` vào trang.
- Chạy hàm `updateGameArea()` liên tục mỗi 10ms.
#### `checkCrash()`
- Duyệt qua mảng `myObstacles` để kiểm tra xem chim có va chạm với bất kỳ chướng ngại vật nào không.
#### `updateGameArea()`
- Xóa màn hình (`clearRect`).
- Nếu đủ số frame, tạo một chướng ngại vật mới.
- Cập nhật vị trí của tất cả chướng ngại vật và vẽ lại.
- Cập nhật điểm số.
- Cập nhật vị trí và vẽ lại chim.
- Nếu chim va vào chướng ngại vật, gọi `loseGame()`.
#### `loseGame()`
- Dừng nhạc nền, xóa canvas, ẩn hướng dẫn.
- Hiển thị điểm số của người chơi.
- Gửi điểm lên backend bằng hàm `submitPoint(score)`.
---
# 5. **Xử lý phím (`onkeyup`, `onkeydown`)**
- Khi **bấm phím cách (SPACE)**: Chim bay lên (`gravity = -0.2`).
- Khi **nhả phím cách**: Chim rơi xuống (`gravity = 0.05`).
---
# 6. **Giao diện HTML**
- **Nút "START GAME"**: Gọi `myGameArea.start()`.
- **Hướng dẫn chơi**: Hiển thị cách điều khiển.
- **Phần hiển thị điểm khi thua**: `text-losegame`.
---
### **Tóm tắt chức năng chính**
- **Nhấn SPACE** để chim bay lên.
- **Tự động rơi xuống** khi không nhấn.
- **Tránh chướng ngại vật** để đạt điểm cao.
- Khi **va chạm**, hiển thị điểm và dừng trò chơi.