C++游戏开发基础课5

1.回顾

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
98
99
100
101
102
#include <iostream>
#include <conio.h>
#include <cstring>
#include <windows.h>
using namespace std;
string map1[10] = {"####################",
"#Y #",
"# #",
"# #",
"# #",
"# #",
"# #",
"# #",
"# X#",
"####################"};
string map2[13] = {"##################################",
"#Y#X #",
"# ############################## #",
"# # #",
"############################## # #",
"# # # #",
"# # ############### #",
"# # V# #",
"# # ############### #",
"# V# #",
"# ############################## #",
"# #",
"##################################"};
void print(string maps[], int size, int x, int y) {
system("cls");
for(int i = 0; i < size; i++) {
for(int j = 0; j < maps[i].size(); j++) {
if(i == y && j == x) {
cout << "Y";
} else {
if(maps[i][j] == 'V') {
cout << "Y";//假装这是出口
} else {
cout << maps[i][j];
}
}
}
cout << endl;
}
return;
}
void move(string maps[], int size) {
int x, y, old_x, old_y;//old_x与old_y记录入口
for(int i = 0; i < size; i++) {
for(int j = 0; j < maps[i].size(); j++) {
if(maps[i][j] == 'Y') {
y = i;
x = j;
old_x = i;
old_y = j;
maps[i][j] = ' ';
break;
}
}
}
while(true) {
print(maps, size, x, y);
char a = getch();
if(a == 'w' || a == 'W') {
if(maps[y - 1][x] != '#') {
y--;
}
} else if(a == 's' || a == 'S') {
if(maps[y + 1][x] != '#') {
y++;
}
} else if(a == 'a' || a == 'A') {
if(maps[y][x - 1] != '#') {
x--;
}
} else if(a == 'd' || a == 'D') {
if(maps[y][x + 1] != '#') {
x++;
}
}
if(maps[y][x] == 'X') {
system("cls");
cout << "你赢了!" << endl;
system("pause");
return;
}
if(maps[y][x] == 'V') {
system("cls");
cout << "你死了!" << endl;
cout << "呃,这个出口可能是陷阱……" << endl;
system("pause");
x = old_x;
y = old_y;//回到入口
}
}
return;
}
int main() {
move(map1, 10);
move(map2, 13);//第二关
return 0;
}

2.更快的刷新

在实现该代码的时候,我们会发现一个问题

在高速移动(一直按方向键)的时候,地图会一直闪烁,让视觉体验非常不好!

这里就需要使用一个新的函数用来移动输入输出光标来覆盖原来的字符而不是用原来的清屏重写

需要注意的是,移动输入输出光标不会清除屏幕,只会使后续的输出定义到新位置,所以在切换地图时要主动加入system(“cls”)

清屏代码太复杂啦,用一个自定义函数简单概括

1
2
3
4
5
6
void setpos(int x, int y) {//x为横坐标,y为纵坐标,窗口左上角是(0,0)
COORD pos;
pos.X = x,pos.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
return;
}

大家在运行完程序后又会发现,光标一直在闪烁,影响视觉美观,这时候又需要一段代码来隐藏光标(不影响输出)

1
2
CONSOLE_CURSOR_INFO cursor_info = {1, 0}; 
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);

3.代码展示

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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#include <iostream>
#include <conio.h>
#include <cstring>
#include <windows.h>
using namespace std;
string map1[10] = {"####################",
"#Y #",
"# #",
"# #",
"# #",
"# #",
"# #",
"# #",
"# X#",
"####################"};
string map2[13] = {"##################################",
"#Y#X #",
"# ############################## #",
"# # #",
"############################## # #",
"# # # #",
"# # ############### #",
"# # V# #",
"# # ############### #",
"# V# #",
"# ############################## #",
"# #",
"##################################"};
void setpos(int x, int y) {//x为横坐标,y为纵坐标
COORD pos;
pos.X = x,pos.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
return;
}
void print(string maps[], int size, int x, int y) {
setpos(0, 0);//移动光标到窗口左上角
//system("cls");
for(int i = 0; i < size; i++) {
for(int j = 0; j < maps[i].size(); j++) {
if(i == y && j == x) {
cout << "Y";
} else {
if(maps[i][j] == 'V') {
cout << "Y";//假装这是出口
} else {
cout << maps[i][j];
}
}
}
cout << endl;
}
return;
}
void move(string maps[], int size) {
system("cls");//主动刷新屏幕,防止上一关的地图还在窗口中
int x, y, old_x, old_y;//old_x与old_y记录入口
for(int i = 0; i < size; i++) {
for(int j = 0; j < maps[i].size(); j++) {
if(maps[i][j] == 'Y') {
y = i;
x = j;
old_x = i;
old_y = j;
maps[i][j] = ' ';
break;
}
}
}
while(true) {
print(maps, size, x, y);
char a = getch();
if(a == 'w' || a == 'W') {
if(maps[y - 1][x] != '#') {
y--;
}
} else if(a == 's' || a == 'S') {
if(maps[y + 1][x] != '#') {
y++;
}
} else if(a == 'a' || a == 'A') {
if(maps[y][x - 1] != '#') {
x--;
}
} else if(a == 'd' || a == 'D') {
if(maps[y][x + 1] != '#') {
x++;
}
}
if(maps[y][x] == 'X') {
system("cls");
cout << "你赢了!" << endl;
system("pause");
return;
}
if(maps[y][x] == 'V') {
system("cls");
cout << "你死了!" << endl;
cout << "呃,这个出口可能是陷阱……" << endl;
system("pause");
x = old_x;
y = old_y;//回到入口
}
}
return;
}
int main() {
CONSOLE_CURSOR_INFO cursor_info = {1, 0};
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
move(map1, 10);
move(map2, 13);//第二关
return 0;
}