游戏效果的展示
游戏玩法:玩家(坤坤)把箱子(篮球)推到目的地(篮框),然后篮筐变成鸡,鸡你太美, 便是胜利,
运用的知识点(必看)
1.学会easyx库的使用
2.利用数组绘制地图,再利用枚举,表示游戏元素。
还有对三维数组的了解与掌握
3.函数的构造和调用
4.循环和判断语句
5**.bool类型(C++中会有介绍)**
不会easyx库的,可以去看一下我之前写的文章,推箱子这个项目不算是很复杂,非常的适合初学者上手。
代码的讲解
游戏地图的实现
地图的初始化
enum Mine { space, wall, destination, box, player, }; int level = 0; int map[3][10][10] = { { {0, 0, 0, 1, 1, 1 ,1 ,1, 0, 0}, {0, 0, 0, 1, 0, 0 ,2 ,1, 0, 0}, {0, 0, 0, 1, 0, 3 ,0 ,1, 0, 0}, {0, 1, 1, 1, 0, 0 ,0 ,1, 1, 1}, {0, 1, 0, 2, 3 ,4 ,3, 0, 2, 1}, {0, 1, 1, 1, 0, 3 ,0 ,1, 1, 1}, {0, 0, 0, 1, 0, 2 ,0 ,1, 0, 0}, {0, 0, 0, 1, 0, 0 ,0 ,1, 0, 0}, {0, 0, 0, 1, 1, 1 ,1 ,1, 0, 0}, {0, 0, 0, 0, 0, 0 ,0 ,0, 0, 0}, }, { {1, 1, 1, 1, 1, 1 ,1 ,1, 1, 1}, {1, 2, 0, 0, 0, 0 ,0 ,0, 0, 1}, {1, 0, 0, 0, 0, 0 ,3 ,0, 1, 0}, {1, 0, 0, 3, 0, 0 ,0 ,0, 0, 1}, {1, 0, 0, 3, 0 ,4 ,0, 0, 0, 1}, {1, 0, 0, 0, 0, 0 ,1 ,0, 0, 1}, {1, 2, 1, 1, 0, 0 ,1 ,0, 2, 1}, {1, 1, 1, 0, 1, 0 ,1 ,0, 1, 0}, {0, 0, 0, 0, 1, 0 ,1 ,0, 1, 0}, {0, 0, 0, 0, 1, 1 ,1 ,1, 0, 0}, }, { {0, 0, 0, 1, 1, 1 ,1 ,0, 0, 0}, {0, 0, 1, 0, 0, 0 ,0 ,1, 0, 0}, {0, 1, 0, 3, 0, 3 ,0 ,0, 1, 0}, {1, 2, 0, 0, 0, 0 ,1 ,0, 0, 1}, {1, 1, 1, 1, 2 ,0 ,1, 0, 0, 1}, {1, 0, 0, 1, 1, 1 ,1 ,0, 0, 1}, {1, 2, 0, 0, 0, 4 ,0 ,0, 0, 1}, {0, 1, 0, 0, 3, 0 ,3 ,0, 1, 0}, {0, 0, 1, 0, 0, 0 ,2 ,1, 0, 0}, {0, 0, 0, 1, 1, 1 ,1 ,0, 0, 0}, } };
推箱子这个游戏共有5个元素
这里采用枚举列举出来
0 代表空地, 1代表墙, 2代表目的地(篮筐), 3代表箱子(篮球), 4代表玩家(坤坤)当然还有一种情况,当篮球在篮筐时候,就变成鸡了
这里采用了三维数组,
游戏地图是有二维数组构成,一关的话是二维数组,如果想要增加游戏关卡的话,就需要用到三维数组,这里我只写了3关,如果你有兴趣,可以自行添加下一个关卡.
同时这里定义了一个level, 它代表着关卡数
地图图片的加载
void IoadImge() { for (int i = 0; i < 6; i++) { char str[20] = ""; sprintf_s(str, "./images/%d.bmp", i); loadimage(image_all + i, str, 64, 64); } }
这里主要是运用easyx库, 当然要先定义图片, 定义图片的代码我把它跟头文件放在一起的,这函数里便没有。
1、先定义一个字符串数组
2、sprintf()函数,主要起到拼接字符串的作用。
3.加载图片,loadiomage()函数里的64,是指的图片的大小,也就是图片素材的大小
地图图片的放置
oid drawmap() { for (int i = 0; i < 10; ++i) { for (int j = 0; j < 10; ++j) { int x = j * 64; int y = i * 64; switch (map[level][i][j]) { case space: //printf(" "); putimage(x, y, image_all); break; case wall: //printf("▓ "); putimage(x, y, image_all + 1); break; case destination: //printf("☆"); putimage(x, y, image_all + 2); break; case box: //printf("□"); putimage(x, y, image_all + 3); break; case player: //printf("♀"); putimage(x, y, image_all + 4); break; case box + destination: //printf("★"); putimage(x, y, image_all + 5); break; case player + destination: //printf("♂"); putimage(x, y, image_all + 4); break; } } printf("\n"); } }
1.这里 x, y 算的是坐标,图片的大小为60,行与列分别*64,便是坐标的大小
2.主要是用switch语句加上for嵌套循环,对各个元素,分别putimage()
这里多了一种情况,当篮球被推到篮筐时, 这里贴了一张照片,它2就变成了一只鸡
也就是鸡你太美。
人物和箱子的移动(重点)
void playgame() { int i = 0, j = 0; for (i = 0; i < 10; i++) { for (j = 0; j < 10; j++) { if (map[level][i][j] == player || map[level][i][j] == player + destination) { goto end; //break跳出一层循环,用 goto end; end:; 跳出所有的循环 } } } end:; int key = _getch(); switch (key) { case 'w': // 上 case 'W': case 72: if (map[level][i - 1][j] == space || map[level][i - 1][j] == destination) { map[level][i - 1][j] += player; map[level][i][j] -= player; } else { if (map[level][i - 1][j] == box || map[level][i - 1][j] == box + destination) { if (map[level][i - 2][j] == space || map[level][i - 2][j] == destination) { map[level][i - 2][j] += box; map[level][i - 1][j] = map[level][i - 1][j] - box + player; map[level][i - 1][j] -= player; } } } break; case 's': // 下 case 'S': case 80: if (map[level][i + 1][j] == space || map[level][i + 1][j] == destination) { map[level][i + 1][j] = map[level][i + 1][j] + player; map[level][i][j] = map[level][i][j] - player; } else { if (map[level][i + 1][j] == box || map[level][i + 1][j] == box + destination) { if (map[level][i + 2][j] == space || map[level][i + 2][j] == destination) { map[level][i + 2][j] = map[level][i + 2][j] + box; map[level][i + 1][j] = map[level][i + 1][j] - box + player; map[level][i + 1][j] = map[level][i + 1][j] - player; } } } break; case 'a': // 左 case 'A': case 75: if (map[level][i][j - 1] == space || map[level][i][j - 1] == destination) { map[level][i][j - 1] += player; map[level][i][j] -= player; } else { if (map[level][i][j - 1] == box || map[level][i][j - 1] == box + destination) { if (map[level][i][j - 2] == space || map[level][i][j - 2] == destination) { map[level][i][j - 2] += box; map[level][i][j - 1] = map[level][i][j - 1] - box + player; map[level][i][j - 1] -= player; } } } break; case 'd': // 右 case 'D': case 77: if (map[level][i][j + 1] == space || map[level][i][j + 1] == destination) { map[level][i][j + 1] += player; map[level][i][j] -= player; } else { if (map[level][i][j + 1] == box || map[level][i][j + 1] == box + destination) { if (map[level][i][j + 2] == space || map[level][i][j + 2] == destination) { map[level][i][j + 2] += box; map[level][i][j + 1] = map[level][i][j + 1] - box + player; map[level][i][j + 1] -= player; } } } break; } } bool deduce_suc-cess() { for (int a = 0; a < 10; a++) { for (int b = 0; b < 10; b++) { if (map[level][a][b] == box) { return false; } } } return true; }
人物的移动主要是通过数组的移动来实现的
第一步:在数组中找到 player 和 player + destination 这两种情况, 多层循环跳出这里用了 goto语句(break只跳出一层)
通过按键盘,控制坤坤移动
这里讲解下坤坤上移,其他方向移动,原理是一样的,只是方向不一样。
这里采用Switch语句
键盘中上移的键有3种, W, w, 以及键盘右边向上移动的键(72)****(键盘右边表示方向的键都可以用特定数字来表示, 向上72, 向下80, 向左75, 向右77)
移动前,要思考一个问题,
坤坤前面是空地可以移动, 坤坤前面是前面是篮筐可以移动,坤坤前面是墙不能够移动,
坤坤前面是篮球而篮球前面是空地可以移动, 坤坤前面是篮球而篮球前面是篮筐可以移动
坤坤前面是篮球而篮球前面是空地则不能够移动
注意:坤坤推篮球的时候, 先是篮球先动, 坤坤不动,篮球动了,坤坤前面有空地,然后坤坤再动。
if (map[level][i - 1][j] == space || map[level][i - 1][j] == destination)
//坤坤前面是空地可以移动, 坤坤前面是前面是篮筐可以移动.
那么
map[level][i - 1][j] += player; //向上移动, 前面的位置+个player
map[level][i][j] -= player;// 向上移动 前面的位置- 一个player
if (map[level][i - 1][j] == box || map[level][i - 1][j] == box + destination)// 坤坤前面是篮球或者坤坤前面是篮球加篮筐(鸡)
{
if (map[level][i - 2][j] == space || map[level][i - 2][j] == destination)//坤坤前面(篮球或者鸡)的前面是空地或者坤坤前面(篮球或者鸡)的前面是篮筐也是可以移动的
}
这里主要实现坤坤推着篮球移动(你也可以理解为坤坤开始将要进行三步上篮的操作了)
map[level][i - 2][j] += box; //篮球前面移动一个单位, 前面那个位置出现了篮球,自然前面那个位置+个篮球
map[level][i - 1][j] = map[level][i - 1][j] - box + player;篮球原来的位置 - 个篮球,坤坤前面移动一个单位,则坤坤前面的位置加一个坤坤
map[level][i - 1][j] -= player; ://坤坤推篮球的时候, 先是篮球先动, 坤坤不动,篮球动了,坤坤前面有空地,然后坤坤再动。
所以为实现坤坤推篮球的时候不移动这个位置,前面这个位置加了一个坤坤,这个位置再减去一个坤坤。,
当然如果你想实现坤坤跟篮球一起移动, 你可以在坤坤原来这个位置减去一个坤坤
游戏结束的判断
bool deduce_success() { for (int a = 0; a < 10; a++) { for (int b = 0; b < 10; b++) { if (map[level][a][b] == box) { return false; } } } return true; }
游戏的判断这里采用boole类型,两种返回结果,
(游戏成功返回return true, 游戏失败返回return false)
游戏结束的标志是:地图上都没有篮球,因为篮球都被坤坤推到篮筐里了, 变成了鸡
如果地图上篮球,那么就return false
else if 那么就return true
音乐的播放
vmciSendString("open 1.mp3", 0, 0, 0); mciSendString("play 1.mp3", 0, 0, 0);
俗话说没有音乐的游戏,是没有灵魂的
所以我特意去找了一些鸡哥的音乐
播放音乐的步骤很简单
如果代码不懂
看我之前写的博客easyx库的介绍
头文件以及全局变量
#include<stdio.h> // 推箱子的几个元素; #include<stdlib.h> // 0 空地 1 墙 2 目的地 3 箱子 4 玩 5 箱子在目的地 6 玩家在目的地 #include<conio.h> //_getch()函数的头文件 //用_getch函数,如果用getchar(),次移动要回车键 // 上 72 下 80 左75 右77 #include<graphics.h> // 使用第三方库easyx #include<mmsystem.h> #pragma comment(lib, "winmm.lib") IMAGE image_all[6]; // 用数组存储图片
main函数
int main() { mciSendString("open 1.mp3", 0, 0, 0); mciSendString("play 1.mp3", 0, 0, 0); //cols 长 lines宽 //system("mode con cols=25 lines=15"); initgraph(640, 640); IoadImge(); while (1) { //system("cls"); drawmap(); /*playmusic();*/ if (deduce_success()) { level++; if (level > 2) { setbkmode(TRANSPARENT); settextcolor(RED); settextstyle(50, 0, "行楷"); outtextxy(100, 400, "你赢了,恭喜通关\n"); outtextxy(60, 300, "快看我鸡你太美,唱跳rap\n"); //printf("你赢了"); //printf("不愧是地表最强的人!!!!!!"); //printf("恭喜通关!!!!!!"); break; } } playgame(); } getchar(); return 0; }
这里需要注意的主函数中
游戏结束判断的那部分代码
这个关过了就 level就++
这里通关了,我也采用了easyx库的操作,
自己打印了一些字, 当然你也可以自己修改
游戏源码和图片素材领取(百度网盘)
**家人们游戏源码和图片素材都在这里,可以自行领取
链接:https://pan.baidu.com/s/1qGGIeKPUAr5GY8xEhej47Q?pwd=2222
提取码:2222
–来自百度网盘超级会员V1的分享
你们的三连真的对我很重要,后续我会创作出更多的优质博客