Samxander's home

You shall see the difference now that we are back again!

0%

基于OpenGL的迷宫小游戏

基于OpenGL库,我使用C语言编写了一个简单的迷宫游戏。游戏具有以下特点:

  • 具有简单的图形化界面,使得与用户间有一定的的交互性。
  • 有两张地图可供选择,玩家需在 60 秒内通过键盘上的 W A S D 移动,走到目标点。
  • 是我的C语言大作业

游戏界面如下:

Maze1

Maze2

源代码如下:

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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
#include <GL/glut.h>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>

// 定义迷宫大小和时间限制
#define MAZE_WIDTH 10
#define MAZE_HEIGHT 10
#define TILE_SIZE 40
#define TIME_LIMIT 60

// 定义多个迷宫地图
int maze1[MAZE_HEIGHT][MAZE_WIDTH] = {
{1, 1, 1, 1, 1, 0, 1, 0, 1, 1},
{1, 1, 1, 0, 1, 0, 1, 0, 1, 0},
{1, 1, 1, 0, 1, 1, 1, 0, 1, 1},
{1, 0, 1, 0, 0, 0, 1, 0, 1, 0},
{1, 0, 1, 0, 1, 1, 1, 0, 1, 1},
{1, 0, 1, 1, 1, 0, 0, 0, 0, 0},
{1, 0, 0, 0, 1, 1, 1, 0, 1, 0},
{1, 0, 1, 1, 1, 0, 1, 0, 1, 0},
{1, 0, 0, 0, 1, 1, 0, 0, 1, 0},
{1, 0, 1, 1, 1, 1, 1, 1, 1, 1}
};

// 第二个迷宫地图
int maze2[MAZE_HEIGHT][MAZE_WIDTH] = {
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 1, 1, 1, 1, 0, 0, 1},
{1, 0, 1, 0, 0, 0, 1, 0, 0, 1},
{1, 0, 1, 0, 1, 0, 1, 1, 0, 1},
{1, 0, 1, 0, 1, 0, 0, 0, 0, 1},
{1, 0, 1, 0, 1, 1, 1, 0, 0, 1},
{1, 0, 0, 0, 0, 0, 1, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
};

// 存储所有的迷宫地图
// 声明一个指向二维数组的指针数组mazes,每个元素是一个指向二维数组的指针,数组大小为numMazes
int (*mazes[])[MAZE_HEIGHT][MAZE_WIDTH] = {&maze1, &maze2};
int numMazes = sizeof(mazes) / sizeof(mazes[0]);

// 当前选择的迷宫地图索引
int selectedMazeIndex = 0;

// 玩家起始位置
int playerX = 1, playerY = 1;

// 用于存储玩家按键
int keyPress = 0;

// 0: 未开始, 1: 游戏中, 2: 游戏胜利, 3: 游戏失败
int gameState = 0;

// 记录游戏开始时间
struct timeval startTime;

// 目标点坐标
int targetX = MAZE_WIDTH - 2;
int targetY = MAZE_HEIGHT - 2;

// 绘制单个迷宫格
//x和y为坐标,r为红色,g为绿色,b为蓝色
void drawTile(int x, int y, float r, float g, float b) {
glColor3f(r, g, b);
glBegin(GL_QUADS);

// 绘制一个四边形
glVertex2i(x, y);
glVertex2i(x + TILE_SIZE, y);
glVertex2i(x + TILE_SIZE, y + TILE_SIZE);
glVertex2i(x, y + TILE_SIZE);
glEnd();
}

// 绘制整个迷宫
void drawMaze() {
int (*maze)[MAZE_HEIGHT][MAZE_WIDTH] = mazes[selectedMazeIndex];
for (int y = 0; y < MAZE_HEIGHT; ++y)
{
for (int x = 0; x < MAZE_WIDTH; ++x)
{
if ((*maze)[y][x] == 0)
{
// 墙壁是黑色的
drawTile(x * TILE_SIZE, y * TILE_SIZE, 0.0f, 0.0f, 0.0f);
}
else
{
// 路径是白色的
drawTile(x * TILE_SIZE, y * TILE_SIZE, 1.0f, 1.0f, 1.0f);
}
}
}
}

// 绘制玩家
void drawPlayer()
{
// 玩家是红色的
drawTile(playerX * TILE_SIZE, playerY * TILE_SIZE, 1.0f, 0.0f, 0.0f);
}

// 绘制目标点
void drawTarget()
{
// 目标点是绿色的
drawTile(targetX * TILE_SIZE, targetY * TILE_SIZE, 0.0f, 1.0f, 0.0f);
}

// 显示游戏剩余时间
void displayTime()
{
//声明一个timeval结构体变量currentTime,用于存储当前时间
struct timeval currentTime;

// 调用mingw_gettimeofday函数获取当前时间
mingw_gettimeofday(&currentTime, NULL);

// 计算经过的秒数
long secondsElapsed = currentTime.tv_sec - startTime.tv_sec;

// 计算剩余时间
int remainingTime = TIME_LIMIT - (int)secondsElapsed;

// 定义一个字符数组timeText,用于存储时间文本
char timeText[16];

// 格式化时间文本
sprintf(timeText, "Time left: %02d", remainingTime);

// 设置文本颜色为红色
glColor3f(1.0f, 0.0f, 0.0f);

// 设置文本位置
glRasterPos2i(10, 10);

for (int i = 0; timeText[i]!= '\0'; i++)
{
// 逐个绘制字符
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, timeText[i]);
}
}

// 处理键盘输入
void processKeys(unsigned char key, int x, int y)
{
if (gameState == 1)
{
// 下移
if (key == 's' || key == 'S')
{
if (playerY > 0 && (*mazes[selectedMazeIndex])[playerY - 1][playerX] == 1)
{
playerY--;
}
}
else if (key == 'w' || key == 'W')
{
// 上移
if (playerY < MAZE_HEIGHT - 1 && (*mazes[selectedMazeIndex])[playerY + 1][playerX] == 1)
{
playerY++;
}
}
else if (key == 'a' || key == 'A')
{
// 左移
if (playerX > 0 && (*mazes[selectedMazeIndex])[playerY][playerX - 1] == 1)
{
playerX--;
}
}
else if (key == 'd' || key == 'D')
{
// 右移
if (playerX < MAZE_WIDTH - 1 && (*mazes[selectedMazeIndex])[playerY][playerX + 1] == 1)
{
playerX++;
}
}

// 检查是否到达目标点
if (playerX == targetX && playerY == targetY)
{
gameState = 2;
}
// 检查是否超过时间限制
struct timeval currentTime;
mingw_gettimeofday(&currentTime, NULL);

// 时间耗尽,游戏失败
if (currentTime.tv_sec - startTime.tv_sec >= TIME_LIMIT)
{
gameState = 3;
}

// 请求重绘
glutPostRedisplay();
}
}

// 显示函数
void display() {
glClear(GL_COLOR_BUFFER_BIT);

if (gameState == 0)
{
// 显示游戏开始界面
// 设置文本颜色为黑色
glColor3f(0.0f, 0.0f, 0.0f);
// 居中显示
glRasterPos2i(MAZE_WIDTH * TILE_SIZE / 2 - 100, MAZE_HEIGHT * TILE_SIZE / 2);
char startText[] = "Press 'S' to Start. Choose map: 1-2";
for (int i = 0; startText[i]!= '\0'; i++)
{
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, startText[i]);
}

}
else if (gameState == 1)
{
// 绘制迷宫
drawMaze();

// 绘制玩家
drawPlayer();

// 绘制目标点
drawTarget();
displayTime();

}
else if (gameState == 2)
{
// 显示游戏胜利界面
glColor3f(0.0f, 0.0f, 0.0f);
glRasterPos2i(MAZE_WIDTH * TILE_SIZE / 2 - 100, MAZE_HEIGHT * TILE_SIZE / 2);
char winText[] = "Congratulations! You Win!";
for (int i = 0; winText[i]!= '\0'; i++)
{
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, winText[i]);
}

}
else if (gameState == 3)
{
// 显示游戏失败界面
// 设置文本颜色为黑色
glColor3f(0.0f, 0.0f, 0.0f);

// 居中显示
glRasterPos2i(MAZE_WIDTH * TILE_SIZE / 2 - 100, MAZE_HEIGHT * TILE_SIZE / 2);
char loseText[] = "Time Out! You Lose!";
for (int i = 0; loseText[i]!= '\0'; i++)
{
glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18, loseText[i]);
}
}

glFlush();
// 刷新缓冲区
glutSwapBuffers();
// 交换缓冲区
}


// 初始化函数
void init()
{
// 背景色为白色
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);

// 设置正投影矩阵
glOrtho(0, MAZE_WIDTH * TILE_SIZE, 0, MAZE_HEIGHT * TILE_SIZE, -1, 1);
}


// 处理游戏开始界面键盘输入,输入S或s开始游戏(不过有缓冲,需要等几秒按S才有用)
void processStartKeys(unsigned char key, int x, int y)
{
if (gameState == 0)
{
if (key == '1')
{
selectedMazeIndex = 0;
}
else if (key == '2')
{
selectedMazeIndex = 1;
}
if (key =='s' || key == 'S')
{
gameState = 1;
glutDisplayFunc(display);
glutKeyboardFunc(processKeys);

// 记录游戏开始时间
mingw_gettimeofday(&startTime, NULL);
}
}
}


// 主函数
int main(int argc, char** argv)
{

// 初始化GLUT库
glutInit(&argc, argv);

// 设置显示模式为双缓冲和RGB颜色模式
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);

// 设置窗口大小
glutInitWindowSize(MAZE_WIDTH * TILE_SIZE, MAZE_HEIGHT * TILE_SIZE);

// 创建窗口(其中的maze game为窗口名称)
glutCreateWindow("maze game");

init();
// 初始显示游戏开始界面
glutDisplayFunc(display);
glutKeyboardFunc(processStartKeys);

// 进入主循环
glutMainLoop();
return 0;
}
Insist on writing original high-quality articles. Your support is my biggest motivation.