Chúng ta tiếp tục công việc của mình chứ ?
Như bài 1 mình đã hướng dẫn cho các bạn tạo tất cả những biến để sử dụng trong game và giải thích ý nghĩa của từng biến .
Hôm nay chúng ta sẽ phân thích sơ qua về game và chức năng game cần có để khai báo trước các hàm và sau đó sẽ đi từng bước giải quyết các hàm đó .
Chúng ta cùng phân tích hướng làm nhé :
Ta có 2 bảng :
– 1 bảng chính thể hiện các object của game gồm 24 dòng và 10 cột . Ta sẽ chỉ thể hiện ra màn hình 20 dòng thôi còn 4 dòng kia thì không . Tại sao thế ? Vì khi ta tạo 1 object mới để rơi xuống ta sẽ tạo ở khoảng 4 dòng trên cùng . Và người chơi sẽ không thấy cho đến khi nó rơi xuống dần lộ ra .
– 1 bảng Next thể hiện những object tiếp theo sẽ được cho vào màn chơi khi object hiện tại bị chết .
Ở trong bảng sẽ là các con số :
– 0 : thể hiện ở ô này không có gì
– 1 : thể hiện ở ô này có 1 object chết (Là object đã rơi xuống hết cỡ không thể rơi chuyển thành object chết)
– 2->8 : sẽ thể hiện 7 loại hình khối khắc nhau như dưới đây .

Hình ảnh . Nguồn : Google.com
Và ta bắt đầu khai báo trước 1 loạt các hàm sẽ dùng trên hàm main :
Hàm này gọi ra thì ta sẽ bắt đầu màn chơi
1
|
void ingameScene(SysGame * sysGame);
|
Hàm nhận và xử lý tín hiệu người dùng cụ thể là phím bấm
1
|
void input(SysGame * sysGame);
|
Hàm vẽ ra màn hình
1
|
void render(SysGame * sysGame);
|
Hàm update trạng thái của game
1
|
void update(SysGame * sysGame);
|
Hàm dùng để điều khiển object . Hàm này sẽ kiểm tra object có thể rơi nữa hay không , đã đầy 1 dòng chưa để thực hiện việc ăn điểm , vv..vv
1
|
void controlObject(SysGame * sysGame);
|
Hàm này điều khiển cấp độ game như kiểm tra xem đạt bao điểm rồi thì tăng tốc độ rơi lên
1
|
void controlLevel(SysGame * sysGame);
|
Hàm này được gọi để thực hiện chuyển tất cả các object này trên board ở trạng thái còn sống (>=2) thì chuyển sang trạng thái chết(=1)
1
|
void changeStatusBoard(SysGame * sysGame);
|
Hàm này được gọi thì các object nào trên màn hình còn sống(>=2) sẽ di chuyển xuống 1 hàng
1
|
void moveObject( int row,SysGame * sysGame);
|
Hàm này sẽ được gọi kiểm tra xem object còn sống(>=2) có thể di chuyển snag trái hoặc sang phải được không . Nếu được thì di chuyển còn không thì thôi
1
2
|
void moveLeftObject(SysGame * sysGame);
void moveRightObject(SysGame * sysGame);
|
Hàm này được gọi thì sẽ thực hiện sinh ngẫu nhiên 1 object vào bảng Next
1
|
void randomNextObject(SysGame * sysGame);
|
Hàm này được gọi để kiểm tra xem object có thể xoay được không . Nếu được thì xoay còn không thì thôi
1
|
void rotateObject(SysGame * sysGame);
|
Hàm này sẽ hiện điểm số khi người chơi thua cuộc và lời cảm ơn
1
|
void showScore(SysGame * sysGame);
|
Hàm này được gọi để reset các thông số game về từ đầu để chuẩn bị cho người chơi 1 ván chơi mới
1
|
void resetGame(SysGame * sysGame);
|
Vì tránh rườm ra mất thời gian của các bạn nên mình sẽ đi vào thực hiện ingame luôn còn mainmenu các bạn tự làm cho chính mình nhé .
Sau khi khai báo hết các hàm trên ta bắt tay vào code trong hàm main :
Ta khai báo 1 biến struct kiểu Sysgame như bài 1 đã định nghĩa và thực hiện gắn thông số ban đầu cho chúng :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
SysGame sysGame;
// Khoi tao ca gia tri ban dau cho struc System Game
sysGame.level = 1;
// Khoi tao bien score luu diem cua nguoi choi
sysGame.score = 0;
// Khoi tao bien luu gia tri neu quyet dinh chay cho vong lap game
sysGame.playIngame = 1;
// Khoi tao bien luu gia tri khi duong dung nhan phim xuong thi chuyen sang trang thai roi nhanh
sysGame.statusSpeedMove = 0;
// Khoi tao bien luu trang thai rotate cua object
sysGame.statusRotate = 0;
// Khoi tao bien statusGame luu trang thai cua game
sysGame.statusGame = 0;
// Khoi tao bien timeLevel luu so thoi gian delay giua 1 update
sysGame.timeLevel = 500;
|
Sau đó ta thực hiện 1 vòng lặp để gắn tất cả các giá trị cho board chính = 0
1
2
3
4
5
6
7
8
|
int i,a;
for (i = 0; i < MAX_ROW ; i++)
{
for (a = 0; a < MAX_COL ; a++)
{
sysGame.board[i][a] = 0; // Web hiện lỗi
}
}
|
Và gọi hàm randomNextObject để tạo ngẫu nhiên object cho vào bảng Next Object
1
2
|
// Chay ham de tao ngau nhien object trong board NO
randomNextObject(&sysGame);
|
Và ta chạy luôn hàm ingameScene() để vào chơi luôn
Ta sẽ có tất cả như sau :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
#include
#include
// Khoi tao 3 hang so luu buoc diem thuong , so luong dong va cot nhieu nhat
const int BONUS_SCORE = 100;
const int MAX_ROW = 24;
const int MAX_COL = 10;
typedef struct
{
// Khoi tao 1 mang 2 chieu la moi truong cho cac object trong game
int board[24][10];
// Khoi tao 1 mang 2 chieu luu nhung object se xuat hien
int boardNO[4][4];
// Khoi tao bien level luu level hien tai nguoi choi dang choi
int level;
// Khoi tao bien score luu diem cua nguoi choi
int score;
// Khoi tao bien luu gia tri neu quyet dinh chay cho vong lap game
int playIngame;
// Khoi tao bien luu gia tri khi duong dung nhan phim xuong thi chuyen sang trang thai roi nhanh
int statusSpeedMove;
// Khoi tao bien luu trang thai rotate cua object
int statusRotate;
// Khoi tao bien statusGame luu trang thai cua game
int statusGame;
// Khoi tao bien timeLevel luu so thoi gian delay giua 1 update
int timeLevel;
} SysGame;
void ingameScene(SysGame * sysGame);
void input(SysGame * sysGame);
void render(SysGame * sysGame);
void update(SysGame * sysGame);
void controlObject(SysGame * sysGame);
void controlLevel(SysGame * sysGame);
void changeStatusBoard(SysGame * sysGame);
void moveObject( int row,SysGame * sysGame);
void moveLeftObject(SysGame * sysGame);
void moveRightObject(SysGame * sysGame);
void randomNextObject(SysGame * sysGame);
void rotateObject(SysGame * sysGame);
void showScore(SysGame * sysGame);
void resetGame(SysGame * sysGame);
int main( int argc, char *argv[])
{
// Khoi tao 1 struct luu cac gia tri he thong cua game
SysGame sysGame;
// Khoi tao ca gia tri ban dau cho struc System Game
sysGame.level = 1;
// Khoi tao bien score luu diem cua nguoi choi
sysGame.score = 0;
// Khoi tao bien luu gia tri neu quyet dinh chay cho vong lap game
sysGame.playIngame = 1;
// Khoi tao bien luu gia tri khi duong dung nhan phim xuong thi chuyen sang trang thai roi nhanh
sysGame.statusSpeedMove = 0;
// Khoi tao bien luu trang thai rotate cua object
sysGame.statusRotate = 0;
// Khoi tao bien statusGame luu trang thai cua game
sysGame.statusGame = 0;
// Khoi tao bien timeLevel luu so thoi gian delay giua 1 update
sysGame.timeLevel = 500;
// Khoi tao bien cho vong lap
int i,a;
for (i = 0; i < MAX_ROW ; i++)
{
for (a = 0; a < MAX_COL ; a++)
{
sysGame.board[i][a] = 0;// Web hiện lỗi
}
}
// Chay ham de tao ngau nhien object trong board NO
randomNextObject(&sysGame);
ingameScene(&sysGame);
system ( "PAUSE" );
return 0;
}
|
Ở trên sử dung 2 hàm giờ ta sẽ bắt tay vào code từng hàm .
Đầu tiên là ham randomNextObject() :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
/*
Ham tao ngau nhien khuon mau cac object cho vao board NO
INPUT con tro struct sysGame
RETURN none
*/
void randomNextObject(SysGame *sysGame)
{
// Khoi tao bien luu gia tri ngau nhien
int randomType;
// Khoi tao bien vong lap
int i,a;
// Chuyen trang thai rotate ve 0
(*sysGame).statusRotate = 0;
srand ( time (NULL));
// Sinh 1 so ngau nhien tu 0 den 6 luu vao bien randomType
randomType = rand ()%7;
// Xoa tat ca phan tu board NO
for (i = 0; i < 4; i++)
{
for (a = 0; a < 4; a++)
{
(*sysGame).boardNO[i][a] = 0; // Web hiện lỗi
}
}
// Xac dinh kieu va luu vao board NO
if (randomType == 0)
{
(*sysGame).boardNO[0][1] = 2;
(*sysGame).boardNO[1][1] = 2;
(*sysGame).boardNO[2][1] = 2;
(*sysGame).boardNO[3][1] = 2;
}
if (randomType == 1)
{
(*sysGame).boardNO[2][1] = 3;
(*sysGame).boardNO[3][0] = 3;
(*sysGame).boardNO[3][1] = 3;
(*sysGame).boardNO[3][2] = 3;
}
if (randomType == 2)
{
(*sysGame).boardNO[2][0] = 4;
(*sysGame).boardNO[2][1] = 4;
(*sysGame).boardNO[3][1] = 4;
(*sysGame).boardNO[3][2] = 4;
}
if (randomType == 3)
{
(*sysGame).boardNO[1][1] = 5;
(*sysGame).boardNO[2][1] = 5;
(*sysGame).boardNO[3][1] = 5;
(*sysGame).boardNO[3][2] = 5;
}
if (randomType == 4)
{
(*sysGame).boardNO[1][2] = 6;
(*sysGame).boardNO[2][2] = 6;
(*sysGame).boardNO[3][2] = 6;
(*sysGame).boardNO[3][1] = 6;
}
if (randomType == 5)
{
(*sysGame).boardNO[2][1] = 7;
(*sysGame).boardNO[2][2] = 7;
(*sysGame).boardNO[3][1] = 7;
(*sysGame).boardNO[3][2] = 7;
}
if (randomType == 6)
{
(*sysGame).boardNO[3][0] = 8;
(*sysGame).boardNO[3][1] = 8;
(*sysGame).boardNO[2][1] = 8;
(*sysGame).boardNO[2][2] = 8;
}
}
|
Như các bạn thấy đơn giản thôi . Ta sẽ tạo 1 số ngẫu nhiên từ 0-6 và tùy vào giá trị đó ta thây đổi số để vẽ các hình tương ứng vào boardNO .
Tiếp theo ta sẽ đi thẳng vào hàm ingameScene luôn để nhanh chóng . Mình sẽ đi rất nhanh nhưng các bạn phần nào không hiểu nên dưng lại xem xét kỹ đến khi hiểu thì thôi nhé .
Hàm ingameScene() :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
void ingameScene(SysGame *sysGame)
{
// Khoi tao 2 bien dung de tinh toan thoi gian update
int timeRe,timeRe2;
// Khoi tao bien checktime va checkloop dung nhu mot flag
int checkTime = 0;
// Khoi tao 2 bien dung de tinh toan thoi gian render
int timeRender,timeRender2;
// Khoi tao bien checkloop dung nhu mot flag
int checkLoop = 0;
// Khoi tao bien timeDur luu so thoi gian delay giua 1 khung hinh
int timeDur = 50;
while ((*sysGame).playIngame!=0)
{
// Goi ham thuc hien nhan tin hieu tu ban phim
input(sysGame);
// Thuc hien kiem tra thoi gian . cu sau khoang delay moi thuc hien render 1 lan
if (checkLoop == 0)
{
timeRender = clock ();
timeRender2 = clock ();
checkLoop = 1;
}
else
{
timeRender2 = clock ();
if (timeRender2 - timeRender >= timeDur)
{
checkLoop = 0;
// Thuc hien ve ra man hinh
render(sysGame);
}
}
// Kiem tra neu trang thai game la dang chay
if ((*sysGame).statusGame == 0)
{
// Neu trang thai di chuyen = 0 thi thuc hien buoc nhay cham
// Nguoc lai thi thuc hien buoc nhay nhanh
if ((*sysGame).statusSpeedMove == 0)
{
// Thuc hien kiem tra thoi gian . cu sau khoang delay moi thuc hien update 1 lan
if (checkTime == 0)
{
timeRe = clock ();
timeRe2 = clock ();
checkTime = 1;
}
else
{
timeRe2 = clock ();
if (timeRe2 - timeRe >= (*sysGame).timeLevel)
{
checkTime = 0;
// Thuc hien update logic cua game
update(sysGame);
}
}
}
else
{
// Thuc hien update logic cua game
update(sysGame);
}
}
}
showScore(sysGame);
}
|
Trong hàm này như các bạn thấy ra sẽ làm 1 vòng lặp vô tận cho đến khi biến playInGame = 0 thì thoát khỏi vòng lặp và chạy hàm showScore()
1
2
3
4
5
|
while ((*sysGame).playIngame!=0)
{
// Su kien game o day
}
showScore();
|
Tiếp theo trong vòng lặp ta sẽ thực hiện hàm input() đầu tiên để nhận giá trị của người dùng
1
2
|
// Goi ham thuc hien nhan tin hieu tu ban phim
input(sysGame);
|
Sau đó ta thực hiện 1 vào tính toán nhỏ để sau 1 khoảng thời gian timeDur thì thực hiện hàm render() vẽ ra màn hình 1 lần
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
// Thuc hien kiem tra thoi gian . cu sau khoang delay moi thuc hien render 1 lan
if (checkLoop == 0)
{
timeRender = clock ();
timeRender2 = clock ();
checkLoop = 1;
}
else
{
timeRender2 = clock ();
if (timeRender2 - timeRender >= timeDur)
{
checkLoop = 0;
// Thuc hien ve ra man hinh
render(sysGame);
}
}
|
Tiếp theo ra sẽ kiểm tra xem game có ở trạng thái PLAY hay ở PAUSE . Nếu PLAY ta sẽ kiểm tra tiêp xem trang thái di chuyển của object là bình thường hay là trạng thái rơi nhanh (Khi người chơi nhấn nút xuống) . Nếu bình thường thì sau 1 khoảng thời gian timeLevel thì thực hiện việc update trạng thái game 1 lần . Nếu ở trạng thai rơi nhanh thì cho update chạy nhiều nhất có thể .
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
if ((*sysGame).statusGame == 0)
{
// Neu trang thai di chuyen = 0 thi thuc hien buoc nhay cham
// Nguoc lai thi thuc hien buoc nhay nhanh
if ((*sysGame).statusSpeedMove == 0)
{
// Thuc hien kiem tra thoi gian . cu sau khoang delay moi thuc hien update 1 lan
if (checkTime == 0)
{
timeRe = clock ();
timeRe2 = clock ();
checkTime = 1;
}
else
{
timeRe2 = clock ();
if (timeRe2 - timeRe >= (*sysGame).timeLevel)
{
checkTime = 0;
// Thuc hien update logic cua game
update(sysGame);
}
}
}
else
{
// Thuc hien update logic cua game
update(sysGame);
}
}
|
OK . Và đó là xong hàm ingameScene() . Trong hàm này ta sử dụng 3 hàm nữa là input(), render() ,update() .
Ta sẽ bắt đầu lần lượt code từng hàm đó trong bài thứ 3 các bạn nhé .
Còn hết bài này ta đã cơ bản tạo ra 1 vòng lặp game vô tận và điều khiển tốc độ render và update theo ý mình rồi .