0
0
Lập trình
Admin Team
Admin Teamtechmely

Xây dựng Tetris từ đầu bằng C++ và SFML

Đăng vào 6 ngày trước

• 6 phút đọc

Hướng dẫn xây dựng trò chơi Tetris từ đầu bằng C++ và SFML

Chào mừng bạn đến với hướng dẫn chi tiết về cách xây dựng trò chơi Tetris từ đầu bằng C++ và SFML. Bài viết này sẽ giúp bạn hiểu rõ hơn về cách hoạt động của trò chơi, từ việc tạo ra các hình khối đến việc quản lý logic trò chơi. Hãy cùng bắt đầu nhé!

Giới thiệu về Tetris

Tetris là một trò chơi kinh điển mà ở đó, các hình khối (tetrominós) rơi xuống từ trên cao và bạn cần sắp xếp chúng sao cho không còn dòng nào bị thiếu. Mục tiêu là cố gắng không để các khối chồng lên nhau đến tận đỉnh. Một số tính năng nổi bật của trò chơi:

  • Các hình khối rơi xuống và có thể di chuyển sang trái, phải hoặc xoay
  • Khi một dòng được lấp đầy, nó sẽ biến mất và bạn sẽ nhận được điểm
  • Trò chơi kết thúc khi các khối vượt qua đỉnh màn hình

Trò chơi Tetris không chỉ thú vị mà còn là một công cụ tuyệt vời để học lập trình, với nhiều khái niệm như mảng hai chiều, phát hiện va chạm, và xử lý dữ liệu.

Cấu trúc của trò chơi

1. Mô hình hóa các hình khối

Tetrominós là các hình dạng được tạo thành từ 4 ô vuông. Dưới đây là 7 hình dạng chính của tetrominós:

Tên hình khối Hình dạng
I ████
J ██

L

██
O ██
██
S ██
██
T ███
Z ██
██

Mỗi hình khối có thể được đại diện bằng các chỉ số trong một mảng 4x4. Điều này giúp chúng ta dễ dàng quản lý vị trí của chúng trong không gian trò chơi.

2. Cấu trúc trường chơi

Trường chơi là nơi các hình khối sẽ rơi xuống. Ta có thể hình dung nó như một bảng ô vuông, trong đó mỗi ô có thể là trống (0) hoặc đã được lấp đầy (1 đến 7):

cpp Copy
const int M = 20;  // Chiều cao của trường chơi
const int N = 10;  // Chiều rộng của trường chơi
int field[M][N] = {0};  // Khởi tạo trường chơi với tất cả ô trống

3. Các hình khối đang hoạt động

Mỗi hình khối sẽ được lưu trữ với các thông tin về vị trí của chúng:

cpp Copy
struct Point {
    int x, y;  // Tọa độ của từng ô trong hình khối
};
Point a[4], b[4];  // a = vị trí hiện tại, b = vị trí trước đó

Các cơ chế chính của trò chơi

1. Kiểm tra va chạm

Một trong những chức năng quan trọng nhất là kiểm tra xem một hình khối có nằm ngoài giới hạn của trường chơi hay không:

cpp Copy
bool check() {
    for (int i = 0; i < 4; i++) {
        if (a[i].x < 0 || a[i].x >= N || a[i].y >= M) return false;
        else if (field[a[i].y][a[i].x]) return false;
    }
    return true;  // Di chuyển hợp lệ
}

2. Di chuyển ngang

Khi người chơi nhấn phím để di chuyển hình khối, ta lưu trữ vị trí hiện tại và kiểm tra xem di chuyển có hợp lệ hay không:

cpp Copy
for (int i = 0; i < 4; i++) {
    b[i] = a[i];  // Lưu lại vị trí cũ
    a[i].x += dx;  // Di chuyển sang vị trí mới
}
if (!check()) {
    for (int i = 0; i < 4; i++) {
        a[i] = b[i];  // Quay lại vị trí cũ nếu không hợp lệ
    }
}

3. Xoay hình khối

Xoay hình khối là một phần quan trọng trong trò chơi và có thể được thực hiện thông qua phép toán ma trận:

cpp Copy
if (rotate) {
    Point p = a[1];  // Giả định hình khối thứ hai là tâm xoay
    for (int i = 0; i < 4; i++) {
        int x = a[i].y - p.y;
        int y = a[i].x - p.x;
        a[i].x = p.x - x;
        a[i].y = p.y + y;
    }
    if (!check()) {
        for (int i = 0; i < 4; i++) {
            a[i] = b[i];
        }
    }
}

4. Rơi tự động

Hệ thống thời gian sẽ tự động làm cho hình khối rơi xuống theo chu kỳ:

cpp Copy
float timer = 0, delay = 0.3;  // Thời gian giữa các lần rơi
if (timer > delay) {
    for (int i = 0; i < 4; i++) {
        b[i] = a[i];
        a[i].y += 1;  // Di chuyển xuống dưới
    }
    if (!check()) {
        for (int i = 0; i < 4; i++) {
            field[b[i].y][b[i].x] = colorNum;  // Ghi hình khối vào trường chơi
        }
        // Tạo hình khối mới
        colorNum = 1 + rand() % 7;
        int n = rand() % 7;
        for (int i = 0; i < 4; i++) {
            a[i].x = figures[n][i] % 2;
            a[i].y = figures[n][i] / 2;
        }
    }
    timer = 0;  // Đặt lại bộ đếm thời gian
}

Xóa dòng hoàn chỉnh

Khi một dòng hoàn chỉnh được tạo thành, chúng ta cần xóa nó ra khỏi trường chơi:

cpp Copy
int k = M - 1;  // Vị trí ghi
for (int i = M - 1; i > 0; i--) {  // Đọc từ dưới lên
    int count = 0;
    for (int j = 0; j < N; j++) {
        if (field[i][j]) count++;
        field[k][j] = field[i][j];  // Sao chép dòng
    }
    if (count < N) k--;
}

Tạo hình khối ngẫu nhiên

Khi một hình khối được cố định, chúng ta tạo ra một hình khối mới ngẫu nhiên:

cpp Copy
colorNum = 1 + rand() % 7;  // Màu ngẫu nhiên
int n = rand() % 7;  // Hình khối ngẫu nhiên
for (int i = 0; i < 4; i++) {
    a[i].x = figures[n][i] % 2;
    a[i].y = figures[n][i] / 2;
}

Kiểm tra Game Over

Trò chơi sẽ kết thúc khi không còn chỗ cho hình khối mới:

cpp Copy
if (!check()) {
    // Game Over
}

Kết luận

Xây dựng trò chơi Tetris bằng C++ và SFML không chỉ là một bài học về lập trình mà còn giúp bạn hiểu rõ các khái niệm cơ bản trong phát triển game. Hãy thử nghiệm và cải tiến trò chơi của bạn với các tính năng mới như điểm số, cấp độ khó, hoặc hệ thống dự đoán hình khối tiếp theo. Chúc bạn thành công!

Câu hỏi thường gặp

1. Tôi có thể sử dụng ngôn ngữ nào để phát triển Tetris?
Bạn có thể sử dụng bất kỳ ngôn ngữ lập trình nào, nhưng C++ và SFML là một sự lựa chọn tuyệt vời.

2. Có thể thêm âm thanh vào trò chơi không?
Có, bạn có thể sử dụng thư viện âm thanh của SFML để thêm âm thanh vào trò chơi.

3. Làm thế nào để tôi có thể cải thiện trò chơi này?
Bạn có thể thêm tính năng điểm số, cấp độ khó, hoặc hệ thống pause để làm cho trò chơi thú vị hơn.

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào