C语言C++图形库 | 您所在的位置:网站首页 › eup游戏画面 › C语言C++图形库 |
这一节中,我们来做一款经典小游戏,贪吃蛇。先看看最终效果图
在开始之前,我们把窗体创建好。 创建一个800 * 600的窗体。这一次我们使用默认的原点和坐标轴:原点在窗体左上角,X轴正方向向右,Y轴正方向向下。背景色设置为RGB(164, 225, 202),最后调用cleardevice函数,使用背景色清空整个窗体。 #include #include int main() { initgraph(800, 600); // 设置背景色 setbkcolor(RGB(164, 225, 202)); // 使用背景色清空窗体 cleardevice(); getchar(); closegraph(); return 0; } 1. 定位网格将整个800 * 600的窗体,水平分隔为20等分,垂直分隔为15等分,作为整个游戏的网格坐标系统。在上图中,蛇用5格白色的矩形表示。食物用黄色的一格矩形表示。 这样,蛇的每一格身体坐标为: (5, 7) (4, 7) (3, 7) (2, 7) (1, 7) 食物的坐标为: (12, 7) 为了方便观察,把窗体用线段画上上述网格。网格每一格的宽度设为40像素,用符号常量NODE_WIDTH表示。 #define NODE_WIDTH 40 竖向线段先绘制竖向的线段。 竖向线段中,起始点y坐标固定为0,终止点y坐标固定为600。 每条线段的起始点与终止点的x坐标一致,且随着线段不同而变化。 设线段条数从0开始计数。 第0条线段: 起始点、终止点的x坐标为0。 第10条线段: 起始点、终止点的x坐标为10 * NODE_WIDTH。 第20条线段: 起始点、终止点的x坐标为20 * NODE_WIDTH。 观察各线段起始点终止点坐标,可以总结出规律: 第n条线段:起始点(n * NODE_WIDTH, 0)、终止点(n * NODE_WIDTH, 600)。且x坐标的范围为[0, 800]。 // 竖线 for (int x = 0; x D E C B A for (int i = length - 1; i > 0; i--) { snake[i] = snake[i - 1]; } // 根据方向,确定下一个头节点 node newHead; newHead = snake[0]; if (direction == eUp) { newHead.y--; } else if (direction == eDown) { newHead.y++; } else if (direction == eLeft) { newHead.x--; } else // right { newHead.x++; } // 更新头节点 // D E C B A ---> D E C B N snake[0] = newHead; } int main() { initgraph(800, 600); // 设置背景色 setbkcolor(RGB(164, 225, 202)); // 使用背景色清空窗体 cleardevice(); // 蛇节点坐标 node snake[100] = { {5, 7}, {4, 7}, {3, 7}, {2, 7}, {1, 7} }; // 蛇节点长度 int length = 5; while (1) { // 清空整个窗体 cleardevice(); // 绘制网格 paintGrid(); // 绘制蛇节点 paintSnake(snake, length); // 休眠500ms Sleep(500); // 向右移动蛇节点 snakeMove(snake, length, eRight); } getchar(); closegraph(); return 0; } 4. 控制移动方向现在,程序开始后蛇会向右移动,接下来,加入用键盘来控制蛇的移动方向的功能。 键盘交互功能如下: 按下w键,蛇向上移动 按下s键,蛇向下移动 按下a键,蛇向左移动 按下d键,蛇向右移动 在主函数中声明一个枚举变量d,初始为向右移动。 // 移动方向 enum direction d = eRight;将d传递给snakeMove函数的第三个参数。snakeMove函数的第三个参数可以根据方向设置新蛇头的位置。若蛇需要更改移动方向,只要更改枚举变量d即可。 // 枚举变量d,控制蛇的移动方向 snakeMove(snake, length, d);与之前的键盘交互一样,使用_getch与_kbhit函数配合,可以获取键盘输入且不会导致程序阻塞。使用这两个函数别忘了包含头文件#include 。获取到键盘输入后,通过传入枚举变量指针pD,修改变量枚举值。 // 键盘输入改变direction void changeDirection(enum direction* pD) { // 检查输入缓存区中是否有数据 if (_kbhit() != 0) { // _getch函数获取输入缓存区中的数据 char c = _getch(); // 判断输入并转向 switch (c) { case 'w': // 向上移动 *pD = eUp; break; case 's': // 向下移动 *pD = eDown; break; case 'a': // 向左移动 *pD = eLeft; break; case 'd': // 向右移动 *pD = eRight; break; } } }这里还需要注意一个问题,蛇不能后退,如果新的方向与原方向相反,那么按键无效。 // 键盘输入改变direction void changeDirection(enum direction* pD) { // 检查输入缓存区中是否有数据 if (_kbhit() != 0) { // _getch函数获取输入缓存区中的数据 char c = _getch(); // 判断输入并转向 switch (c) { case 'w': // 向上移动 if (*pD != eDown) *pD = eUp; break; case 's': // 向下移动 if (*pD != eUp) *pD = eDown; break; case 'a': // 向左移动 if (*pD != eRight) *pD = eLeft; break; case 'd': // 向右移动 if (*pD != eLeft) *pD = eRight; break; } } }主函数中,在snakeMove函数前调用changeDirection函数检查是否有键盘输入,若有输入且非回头方向的输入,则改变方向枚举变量d。新的方向枚举变量d传入snakeMove函数后,即可使用新方向设置新蛇头的位置,实现蛇改变移动方向功能。 // 蛇节点坐标 node snake[100] = { {5, 7}, {4, 7}, {3, 7}, {2, 7}, {1, 7} }; // 蛇节点长度 int length = 5; enum direction d = eRight; while (1) { cleardevice(); paintGrid(); paintSnake(snake, length); Sleep(500); // 获取键盘输入并将方向存储到变量d changeDirection(&d); // 根据变量d的方向移动蛇节点 snakeMove(snake, length, d); } 现阶段代码: #include #include #include #define NODE_WIDTH 40 // 节点 typedef struct { int x; int y; }node; // 绘制网格 // 横线(0, y), (800, y) 0 D E C B A for (int i = length - 1; i > 0; i--) { snake[i] = snake[i - 1]; } // 根据方向,确定下一个头节点 node newHead; newHead = snake[0]; if (direction == eUp) { newHead.y--; } else if (direction == eDown) { newHead.y++; } else if (direction == eLeft) { newHead.x--; } else // right { newHead.x++; } // 更新头节点 // D E C B A ---> D E C B N snake[0] = newHead; } // 键盘输入改变direction void changeDirection(enum direction* pD) { // 检查输入缓存区中是否有数据 if (_kbhit() != 0) { // _getch函数获取输入缓存区中的数据 char c = _getch(); // 判断输入并转向 switch (c) { case 'w': // 向上移动 if (*pD != eDown) *pD = eUp; break; case 's': // 向下移动 if (*pD != eUp) *pD = eDown; break; case 'a': // 向左移动 if (*pD != eRight) *pD = eLeft; break; case 'd': // 向右移动 if (*pD != eLeft) *pD = eRight; break; } } } // 绘制食物 /* (x * NODE_WIDTH, y * NODE_WIDTH) @----------- | | | | | | | | | | -----------@ ((x + 1) * NODE_WIDTH, (y + 1) * NODE_WIDTH) */ void paintFood(node food) { int left, top, right, bottom; left = food.x * NODE_WIDTH; top = food.y * NODE_WIDTH; right = (food.x + 1) * NODE_WIDTH; bottom = (food.y + 1) * NODE_WIDTH; setfillcolor(YELLOW); solidrectangle(left, top, right, bottom); setfillcolor(WHITE); } // 随机创建食物 node createFood(node* snake, int length) { node food; while (1) { food.x = rand() % (800 / NODE_WIDTH); food.y = rand() % (600 / NODE_WIDTH); int i; for (i = 0; i // 限制snake节点最大长度 if (length E E D C B for (int i = length - 1; i > 0; i--) { snake[i] = snake[i - 1]; } // 下一个头节点 node newHead; newHead = snake[0]; if (direction == eUp) { newHead.y--; } else if (direction == eDown) { newHead.y++; } else if (direction == eLeft) { newHead.x--; } else // right { newHead.x++; } // 更新头节点 // E D C B A ---> F E D C B snake[0] = newHead; //for (int i = 0; i |
CopyRight 2018-2019 实验室设备网 版权所有 |