当前位置:   article > 正文

C语言实现推箱子 (数据库连接+项目打包发布)_c语言打包游戏

c语言打包游戏

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6Zy46YGT5bCP5piO,size_20,color_FFFFFF,t_70,g_se,x_16

    小时候都玩过推箱子这个经典的小游戏,它伴随着我们的童年,带给我们了许多的乐趣。今天呢小编为大家分享一下使用C语言来完成推箱子游戏。以及如何将游戏与数据库连接和项目的打包发布。

    下面是完成之后的效果展示:

①项目打包后我们会获得一个安装程序,点击安装程序就能将推箱子游戏安装在电脑上。这时候也可以将安装程序发给朋友安装试玩(因为时间原因没有做登录页面)

9b5091ce3a484531ac98f9fe033caa8e.gif

 ②游戏内效果,一共设计了四种地图,感兴趣的朋友可以继续在自己的数据库中添加地图。

aada0b539c204d22a1c1653d50d2a80b.gif ​下面我按照 推箱子游戏实现 → 数据库连接 → 程序打包 的路线分享本次项目 

一、推箱子游戏源码(可直接拷贝运行)

游戏图片下载(将图片与代码放在同一文件夹下)。图片下载https://download.csdn.net/download/qq_54169998/81551789这里为分享的源码是以文档做数据结构。下面我会介绍与MySQL相连

  1. #include<graphics.h>
  2. #include<iostream>
  3. #include<stdlib.h>
  4. #include<string>
  5. #include<conio.h>
  6. #include<fstream>
  7. #include<sstream>
  8. using namespace std;
  9. #define LINE 48
  10. #define COLUMN 48
  11. #define RATIO 40
  12. #define SCREEN_WIDTH 740
  13. #define SCREEN_HEIGHT 500
  14. #define START_X 50
  15. #define START_Y 75
  16. #define KEY_UP 'W'
  17. #define KEY_LEFT 'A'
  18. #define KEY_RIGHT 'D'
  19. #define KEY_DOWN 'S'
  20. #define KEY_OUT 'Q'
  21. #define GAME_AGAIN 'R'
  22. #define MAX_RETRY_TIMES 4
  23. #define BG_IMAGE -1
  24. #define isValid(next_pos) next_pos.x > 0 && next_pos.x < LINE && next_pos.y>0 && next_pos.y < COLUMN
  25. #define USERS "users.txt"
  26. #define LEVELS "levels.txt"
  27. #define ROUND 4
  28. typedef enum _PROPS {
  29. WALL, //墙
  30. FLOOR, //地板
  31. BOX_DES,//箱子目的地
  32. MAN, //小人
  33. BOX, //箱子
  34. HIT, //箱子命中目标
  35. MAN_DES, //人站在目标上
  36. VECTOR //通关图片
  37. }PROPS;
  38. typedef enum _DIRECTION {
  39. UP,
  40. DOWN,
  41. LEFT,
  42. RIGHT
  43. }DIRECTION;
  44. typedef struct _POS {
  45. int x; //小人所在二维数组的行数
  46. int y; //小人所在二维数组的列数
  47. }POS;
  48. typedef struct _userinfo {
  49. //这里将字符串初始为空
  50. _userinfo() :id(0), username(""), password(""), level_id(0) {};
  51. _userinfo(int _id, string _username, string _password, int _level_id) :id(_id), username(_username), password(_password), level_id(_level_id) {};
  52. int id; // 用户id
  53. string username;
  54. string password; // 密码
  55. int level_id;
  56. }userinfo;
  57. typedef struct _levelinfo {
  58. _levelinfo() :id(0), name(""), map_row(0), map_column(0), map_data(""), next_level(0) {};
  59. _levelinfo(int _id, string _name, int _map_row, int _map_column, string _map_data, int _next_level) :id(_id), name(_name), map_row(_map_row), map_column(_map_column), map_data(_map_data), next_level(_next_level) {};
  60. int id; // 关卡id
  61. string name; // 关卡名字
  62. int map_row; // 地图行数
  63. int map_column; //地图列数
  64. string map_data; // 二维地图数据
  65. int next_level; //下一关卡id
  66. }levelinfo;
  67. levelinfo game_data[4];
  68. struct _POS man;
  69. IMAGE images[9];
  70. int map[LINE][COLUMN] = { 0 };
  71. /******************************
  72. * 功能:数据重置,当数据文档错乱时可调用此函数一次将数据重装
  73. * 输入:
  74. * 无
  75. *
  76. * 返回值:
  77. * 无
  78. *****************************/
  79. void resetting_data() {
  80. levelinfo levels[ROUND] = { {1,"小试牛刀→第一关",8,10,"-1,0,0,0,0,0,0,0,-1,-1|-1,0,2,2,2,2,1,0,-1,-1|0,0,0,2,2,2,4,0,0,0|0,1,1,4,0,4,1,4,1,0|0,1,4,4,1,1,0,4,1,0|0,1,1,1,3,0,1,1,1,0|0,0,0,0,1,1,1,0,0,0,|-1,-1,-1,0,0,0,0,0,-1,-1",2},
  81. {2,"绝地强者→第二关",6,6,"0,0,0,0,0,0|0,2,2,1,1,0|0,4,4,1,3,0|0,2,1,4,0,0|0,1,1,1,0,-1|0,0,0,0,0,-1",3},
  82. {3,"天外强人→第三关",8,10,"-1,-1,0,0,0,0,0,0,-1,-1|0,0,0,1,1,1,0,0,0,0|0,1,1,1,4,1,4,1,1,0|0,1,4,1,1,1,4,1,3,0|0,0,0,4,4,0,0,0,0,0,|-1,-1,0,1,1,2,2,0,-1,-1|-1,-1,0,2,2,2,2,0,-1,-1|-1,-1,0,0,0,0,0,0,-1,-1",4},
  83. {4,"死而复生→BOSS关",8,8,"-1,0,0,0,0,0,0,-1|-1,0,2,1,2,2,0,-1|-1,0,2,1,4,2,0,-1|0,0,0,1,1,4,0,0|0,1,4,1,1,4,1,0|0,1,0,4,0,0,1,0|0,1,1,1,3,1,1,0|0,0,0,0,0,0,0,0",0}
  84. };
  85. ofstream ofs;
  86. ofs.open(LEVELS, ios::out);
  87. for (int i = 0; i < ROUND; ++i) {
  88. stringstream str_stream;
  89. str_stream << levels[i].id << " " << levels[i].name << " " << levels[i].map_row << " " << levels[i].map_column << " " << levels[i].map_data << " " << levels[i].next_level << endl;
  90. ofs << str_stream.str();
  91. }
  92. ofs.close();
  93. ofs.open(USERS, ios::out);
  94. userinfo user = { 1,"Jack","123456" ,1 };
  95. stringstream str;
  96. str << user.id << " " << user.username << " " << user.password << " " << user.level_id;
  97. ofs << str.str();
  98. ofs.close();
  99. }
  100. /******************************
  101. * 功能:地图数据加载
  102. * 输入:
  103. * 无
  104. *
  105. * 返回值:
  106. * 无
  107. *****************************/
  108. void load_data() {
  109. ifstream ifs;
  110. ifs.open(LEVELS);
  111. int index = 0;
  112. while (index < ROUND) {
  113. string line;
  114. getline(ifs, line);
  115. //cout << line << endl;
  116. int _id;
  117. char _name[64];
  118. int _map_row;
  119. int _map_column;
  120. char _map_data[2304];
  121. int _next_level_id;
  122. levelinfo info;
  123. sscanf_s(line.c_str(), "%d %s %d %d %s %d", &_id, _name, (unsigned int)sizeof(_name), &_map_row, &_map_column, _map_data, (unsigned int)sizeof(_map_data), &_next_level_id);
  124. game_data[index] = { _id,_name,_map_row,_map_column,_map_data,_next_level_id };
  125. index++;
  126. }
  127. }
  128. /******************************
  129. *功能:通过用户名和密码获取用户信息
  130. * 输入:
  131. * user - 用户信息结构体
  132. *
  133. * 返回值:
  134. * 获取成功返回true,失败false
  135. *****************************/
  136. bool fetch_user_info(userinfo& user) {
  137. ifstream ifs;
  138. ifs.open(USERS);
  139. if (!ifs) {
  140. return false;
  141. }
  142. string line;
  143. while (1) {
  144. getline(ifs, line);
  145. int _id;
  146. char _username[64];
  147. char _password[64];
  148. int _level_id;
  149. sscanf_s(line.c_str(), "%d%s%s%d", &_id, _username, (unsigned int)sizeof(_username), _password, (unsigned int)sizeof(_password), &_level_id);
  150. if (_username == user.username && _password == user.password) {
  151. user.id = _id;
  152. user.level_id = _level_id;
  153. return true;
  154. }
  155. if (ifs.eof()) {
  156. break;
  157. }
  158. }
  159. return false;
  160. }
  161. /*********************************
  162. *功能:根据关卡id获取完整的关卡信息(如:地图,下一关等)
  163. * 输入:
  164. * level - 保存关卡信息的结构体
  165. * level_id - 获取关卡id
  166. * 返回值:
  167. * 0 - 查找结果为空(用户已通关)
  168. * 1 - 查找成功
  169. *********************************/
  170. bool fetch_level_info(levelinfo& level, int level_id) {
  171. if (level_id == 0) {
  172. return false;
  173. }
  174. else {
  175. level = game_data[level_id - 1];
  176. return true;
  177. }
  178. }
  179. /******************************
  180. *功能:将获得的关卡数据转换到map地图数组中
  181. * 输入:
  182. * level - 关卡数据
  183. * map - 二维地图数组
  184. *
  185. * 返回值:
  186. * false - 转换失败
  187. * true - 转换成功
  188. *****************************/
  189. bool transform_map_db2array(levelinfo& level, int map[][COLUMN]) {
  190. if (level.map_row > LINE || level.map_column > COLUMN) {
  191. printf("地图过大,请重新设置\n");
  192. return false;
  193. }
  194. if (level.map_data.length() < 1) {
  195. printf("地图数据有误,请重新设置!\n");
  196. return false;
  197. }
  198. long long start = 0, end = 0;
  199. int row = 0, column = 0;
  200. do {
  201. /******************************
  202. *find返回size_t类型值,size_t在64位下是8字节长度,因此这里把start和end设置成long long类型(不设置会有“数据丢失”警告)。当然也可以简单粗暴的修改警告设置
  203. ******************************/
  204. end = level.map_data.find('|', start);
  205. if (end == -1) {
  206. end = level.map_data.length();
  207. }
  208. //合法性检查,结束时end=level.map_data.length,start=end+1
  209. if (start >= end)
  210. break;
  211. string line = level.map_data.substr(start, end - start);
  212. // 对行数据进行解析:0,1,0,1,1,1,1,1,1,1,0,0
  213. char* next_token = NULL;
  214. //line转为const char*(C语言中的字符串),strtok_s会修改line里的值,按照某个特定字符,所以需要将line.c_str()转为char *
  215. // strtok_s第一个参数是要劈开的字符串(要求是一个char *类型的);第二个参数是按某个字符劈开(会把“,”逗号变成‘\0’结束符,也就是说会修改原来字符串,所以要把原来的const char*转为char*);第三个参数是这个接口
  216. // 需要的,用来做定位功能,
  217. char* item = strtok_s((char*)line.c_str(), ",", &next_token);
  218. column = 0;
  219. //printf("%p", next_token);
  220. //::system("pause");
  221. //如果某行数据个数多余这个地图列数,控制只读取level.map_column-1个
  222. while (item && column < level.map_column) {
  223. map[row][column] = atoi(item);
  224. column++;
  225. //再使用strtok_s接口第一个参数可以写NULL,应该是next_token参数上一次做定位功能时已经记录了要劈开字符串给的某个位置
  226. item = strtok_s(NULL, ",", &next_token);
  227. }
  228. //合法性检查
  229. if (column < level.map_column) { // 某行的数据个数小于这个地图的列数
  230. printf("地图数据解析出错,终止!\n");
  231. return false;
  232. }
  233. row++;
  234. //列数多余的话直接舍弃
  235. if (row >= level.map_row) {
  236. break;
  237. }
  238. start = end + 1;
  239. } while (1 == 1);
  240. //列数多余则直接报错
  241. if (row < level.map_row) {
  242. printf("地图行数少于设定,终止!");
  243. return false;
  244. }
  245. return true;
  246. }
  247. /******************************
  248. *功能:更新用户游戏进度信息
  249. * 输入:
  250. * user - 用户信息
  251. * next_level_id - 游戏进度
  252. *
  253. * 返回值:
  254. * 获取成功返回true,失败false
  255. *****************************/
  256. bool update_user_level(userinfo& user, int next_level_id) {
  257. ifstream ifs;
  258. ifs.open(USERS);
  259. if (!ifs) {
  260. return false;
  261. }
  262. int user_index = 1;
  263. string strFileData = "";
  264. while (1) {
  265. if (user_index == user.id) {
  266. {string temp;
  267. getline(ifs, temp); }
  268. user_index++;
  269. continue;
  270. }
  271. if (ifs.eof()) {
  272. break;
  273. }
  274. string line;
  275. getline(ifs, line);
  276. strFileData += line;
  277. strFileData += '\n';
  278. }
  279. ifs.close();
  280. stringstream str_stream;
  281. str_stream << user.id << " " << user.username << " " << user.password << " " << next_level_id << endl;
  282. strFileData += str_stream.str();
  283. ofstream ofs;
  284. ofs.open(USERS);
  285. ofs.flush();
  286. ofs << strFileData;
  287. ofs.close();
  288. user.level_id = next_level_id;
  289. return true;
  290. }
  291. /*****************************
  292. * 功能:判断游戏是否结束
  293. * 输入:
  294. * 无
  295. * 输出:
  296. * true - 未结束
  297. * flase - 结束
  298. *****************************/
  299. bool isGameOver() {
  300. for (int i = 0; i < LINE; ++i) {
  301. for (int j = 0; j < COLUMN; ++j) {
  302. if (map[i][j] == BOX_DES)
  303. return false;
  304. }
  305. }
  306. return true;
  307. }
  308. /*****************************
  309. * 功能:加载游戏结束图片
  310. * 输入:
  311. * 无
  312. * 输出:
  313. * 无
  314. *****************************/
  315. void show_over() {
  316. cleardevice();
  317. IMAGE game_over;
  318. loadimage(&game_over, _T("gameover.png"), SCREEN_WIDTH, SCREEN_HEIGHT, true);
  319. putimage(0, 0, &game_over);
  320. }
  321. /*****************************
  322. * 功能:在指定位置更改地图信息 显示指定图片
  323. * 输入:
  324. * next_pos - 指定位置
  325. * prop - 指定图片
  326. * 输出:
  327. * 无
  328. *****************************/
  329. void changeMap(POS* next_pos, PROPS prop) {
  330. map[next_pos->x][next_pos->y] = prop;
  331. putimage(START_X + next_pos->y * RATIO, START_Y + next_pos->x * RATIO, &images[prop]);
  332. }
  333. /*****************************
  334. * 功能:在指定位置显示指定图片
  335. * 输入:
  336. * next_pos - 指定位置
  337. * prop - 指定图片
  338. * 输出:
  339. * 无
  340. *****************************/
  341. void changeMap2(POS* next_pos, PROPS prop) {
  342. putimage(START_X + next_pos->y * RATIO, START_Y + next_pos->x * RATIO, &images[prop]);
  343. }
  344. /*****************************
  345. * 功能:控制小人向指定方向移动
  346. * 输入:
  347. * direct - 指定方向
  348. * 输出:
  349. * 无
  350. *****************************/
  351. void gameControl(DIRECTION direct) {
  352. POS next_pos = man;
  353. POS next_next_pos = man;
  354. switch (direct) {
  355. case UP:
  356. next_pos.x--;
  357. next_next_pos.x -= 2;
  358. break;
  359. case DOWN:
  360. next_pos.x++;
  361. next_next_pos.x += 2;
  362. break;
  363. case LEFT:
  364. next_pos.y--;
  365. next_next_pos.y -= 2;
  366. break;
  367. case RIGHT:
  368. next_pos.y++;
  369. next_next_pos.y += 2;
  370. break;
  371. }
  372. //宏展开next_pos.x > 0 && next_pos.x < LINE && next_pos.y>0 && next_pos.y < COLUMN
  373. // 人的前方是地板
  374. if (isValid(next_pos) && map[next_pos.x][next_pos.y] == FLOOR) {
  375. //人的脚下是目的地
  376. if (map[man.x][man.y] == BOX_DES) {
  377. changeMap(&next_pos, MAN);
  378. changeMap2(&man, BOX_DES);
  379. }
  380. else {
  381. changeMap(&man, FLOOR);
  382. changeMap(&next_pos, MAN);
  383. }
  384. man = next_pos;
  385. }
  386. // 人的前方是箱子
  387. else if (isValid(next_next_pos) && map[next_pos.x][next_pos.y] == BOX) {
  388. if (map[next_next_pos.x][next_next_pos.y] == FLOOR) { // 箱子的前方是地板
  389. changeMap(&next_next_pos, BOX);
  390. changeMap(&next_pos, MAN);
  391. if (map[man.x][man.y] == BOX_DES) {
  392. changeMap(&man, BOX_DES);
  393. }
  394. else {
  395. changeMap(&man, FLOOR);
  396. }
  397. man = next_pos;
  398. }
  399. else if (map[next_next_pos.x][next_next_pos.y] == BOX_DES) { // 箱子前面是目的地
  400. changeMap(&next_next_pos, HIT);
  401. changeMap(&next_pos, MAN);
  402. if (map[man.x][man.y] == BOX_DES) {
  403. changeMap(&man, BOX_DES);
  404. }
  405. else {
  406. changeMap(&man, FLOOR);
  407. }
  408. man = next_pos;
  409. }
  410. }
  411. //前方是目的地
  412. else if (isValid(next_pos) && map[next_pos.x][next_pos.y] == BOX_DES) {
  413. //小人脚下也是目的地
  414. if (map[man.x][man.y] == BOX_DES) {
  415. changeMap2(&next_pos, MAN_DES);
  416. changeMap(&man, BOX_DES);
  417. }
  418. else {
  419. changeMap(&man, FLOOR);
  420. changeMap2(&next_pos, MAN_DES);
  421. }
  422. man = next_pos;
  423. }
  424. //前方是箱子命中点
  425. else if (isValid(next_pos) && map[next_pos.x][next_pos.y] == HIT) {
  426. if (map[next_next_pos.x][next_next_pos.y] == FLOOR) { // 箱子的前方是地板
  427. changeMap(&next_next_pos, BOX);
  428. changeMap(&next_pos, BOX_DES);
  429. changeMap2(&next_pos, MAN_DES);
  430. //人的脚下是目的地
  431. if (map[man.x][man.y] == BOX_DES) {
  432. changeMap(&man, BOX_DES);
  433. }
  434. else {
  435. changeMap(&man, FLOOR);
  436. }
  437. man = next_pos;
  438. }
  439. else if (map[next_next_pos.x][next_next_pos.y] == BOX_DES) { // 箱子前面是目的地
  440. changeMap(&next_next_pos, HIT);
  441. changeMap(&next_pos, BOX_DES);
  442. changeMap2(&next_pos, MAN_DES);
  443. //人的脚下是目的地
  444. if (map[man.x][man.y] == BOX_DES) {
  445. changeMap(&man, BOX_DES);
  446. }
  447. else {
  448. changeMap(&man, FLOOR);
  449. }
  450. man = next_pos;
  451. }
  452. }
  453. }
  454. /*****************************
  455. * 功能:用户登录
  456. * 输入:
  457. * user - 用户信息
  458. * 输出:
  459. * false - 登录失败
  460. * true - 登录成功
  461. *****************************/
  462. bool login(userinfo& user) {
  463. int times = 0;
  464. bool ret = false;
  465. do {
  466. cout << "请输入用户名:";
  467. cin >> user.username;
  468. cout << "请输入密码:";
  469. cin >> user.password;
  470. ret = fetch_user_info(user);
  471. times++;
  472. if (times >= MAX_RETRY_TIMES)
  473. break;
  474. if (ret == false) {
  475. cout << "登录失败,请重新输入!" << endl;
  476. }
  477. } while (!ret);
  478. return ret;
  479. }
  480. /*****************************
  481. * 功能:加载游戏素材
  482. * 输入:
  483. * 无
  484. * 输出:
  485. * 无
  486. *****************************/
  487. void init_graph() {
  488. initgraph(SCREEN_WIDTH, SCREEN_HEIGHT);
  489. loadimage(&images[WALL], _T("wall_right.bmp"), RATIO, RATIO, true);
  490. loadimage(&images[FLOOR], _T("floor.bmp"), RATIO, RATIO, true);
  491. loadimage(&images[BOX_DES], _T("des.bmp"), RATIO, RATIO, true);
  492. loadimage(&images[MAN], _T("man.bmp"), RATIO, RATIO, true);
  493. loadimage(&images[BOX], _T("box.jpg"), RATIO, RATIO, true);
  494. loadimage(&images[HIT], _T("box_des.jpg"), RATIO, RATIO, true);
  495. loadimage(&images[MAN_DES], _T("man_des.bmp"), RATIO, RATIO, true);
  496. loadimage(&images[VECTOR], _T("vector.png"), 6 * RATIO, 6 * RATIO, true);
  497. }
  498. /*****************************
  499. * 功能:显示指定地图
  500. * 输入:
  501. * level - 指定地图
  502. * 输出:
  503. * 无
  504. *****************************/
  505. void show_images(levelinfo& level) {
  506. cleardevice(); // 每次贴图清屏一下
  507. IMAGE bg_img;
  508. //图片的宽,高最后一个参数“是否拉伸”
  509. loadimage(&bg_img, _T("bgimage.png"), SCREEN_WIDTH, SCREEN_HEIGHT, true);
  510. putimage(0, 0, &bg_img);
  511. for (int i = 0; i < level.map_row; ++i) {
  512. for (int j = 0; j < level.map_column; ++j) {
  513. if (map[i][j] == MAN) {
  514. man.x = i;
  515. man.y = j;
  516. }
  517. if (map[i][j] == BG_IMAGE)
  518. continue;
  519. putimage(START_X + j * RATIO, START_Y + i * RATIO, &images[map[i][j]]);
  520. }
  521. }
  522. const char* str = level.name.c_str();
  523. setbkmode(TRANSPARENT);
  524. setfont(RATIO, 0, _T("华文楷体"));
  525. setcolor(WHITE);
  526. outtextxy(200, 25, str);
  527. }
  528. /*****************************
  529. * 功能:载入PNG图并去透明部分
  530. * 输入:
  531. * 无
  532. * 输出:
  533. * 无
  534. *****************************/
  535. void drawAlpha(IMAGE* picture, int picture_x, int picture_y) //x为载入图片的X坐标,y为Y坐标
  536. {
  537. // 变量初始化
  538. DWORD* dst = GetImageBuffer(); // GetImageBuffer()函数,用于获取绘图设备的显存指针,EASYX自带
  539. DWORD* draw = GetImageBuffer();
  540. DWORD* src = GetImageBuffer(picture); //获取picture的显存指针
  541. int picture_width = picture->getwidth(); //获取picture的宽度,EASYX自带
  542. int picture_height = picture->getheight(); //获取picture的高度,EASYX自带
  543. int graphWidth = getwidth(); //获取绘图区的宽度,EASYX自带
  544. int graphHeight = getheight(); //获取绘图区的高度,EASYX自带
  545. int dstX = 0; //在显存里像素的角标
  546. // 实现透明贴图 公式: Cp=αp*FP+(1-αp)*BP , 贝叶斯定理来进行点颜色的概率计算
  547. for (int iy = 0; iy < picture_height; iy++)
  548. {
  549. for (int ix = 0; ix < picture_width; ix++)
  550. {
  551. int srcX = ix + iy * picture_width; //在显存里像素的角标
  552. int sa = ((src[srcX] & 0xff000000) >> 24); //0xAArrggbb;AA是透明度
  553. int sr = ((src[srcX] & 0xff0000) >> 16); //获取RGB里的R
  554. int sg = ((src[srcX] & 0xff00) >> 8); //G
  555. int sb = src[srcX] & 0xff; //B
  556. if (ix >= 0 && ix <= graphWidth && iy >= 0 && iy <= graphHeight && dstX <= graphWidth * graphHeight)
  557. {
  558. dstX = (ix + picture_x) + (iy + picture_y) * graphWidth; //在显存里像素的角标
  559. int dr = ((dst[dstX] & 0xff0000) >> 16);
  560. int dg = ((dst[dstX] & 0xff00) >> 8);
  561. int db = dst[dstX] & 0xff;
  562. draw[dstX] = ((sr * sa / 255 + dr * (255 - sa) / 255) << 16) //公式: Cp=αp*FP+(1-αp)*BP ; αp=sa/255 , FP=sr , BP=dr
  563. | ((sg * sa / 255 + dg * (255 - sa) / 255) << 8) //αp=sa/255 , FP=sg , BP=dg
  564. | (sb * sa / 255 + db * (255 - sa) / 255); //αp=sa/255 , FP=sb , BP=db
  565. }
  566. }
  567. }
  568. }
  569. /*****************************
  570. * 功能:载入“恭喜通关”图片
  571. * 输入:
  572. * 无
  573. * 输出:
  574. * 无
  575. *****************************/
  576. void promot_over() {
  577. setbkmode(TRANSPARENT);
  578. drawAlpha(&images[VECTOR], 250, 130); // 载入PNG图并去透明部分
  579. Sleep(1100);
  580. }
  581. /*****************************
  582. * 功能:休眠
  583. * 输入:
  584. * interval - 休眠时间
  585. * 输出:
  586. * 无
  587. *****************************/
  588. void wait(int interval) {
  589. int count = interval / 10;
  590. for (int i = 0; i < count; ++i) {
  591. Sleep(10);
  592. if (_kbhit())
  593. return;
  594. }
  595. }
  596. /*****************************
  597. * 功能:游戏控制
  598. * 输入:
  599. * level - 挡墙关卡数据
  600. * user - 用户信息
  601. * 输出:
  602. * 无
  603. *****************************/
  604. void game_operation(levelinfo& level, userinfo& user) {
  605. bool quit = false;
  606. do {
  607. //判断是否有按键按下
  608. if (_kbhit()) {
  609. //无缓冲读取
  610. char ch = _getch();
  611. if (ch == KEY_UP) {
  612. gameControl(UP);
  613. }
  614. else if (ch == KEY_DOWN) {
  615. gameControl(DOWN);
  616. }
  617. else if (ch == KEY_LEFT) {
  618. gameControl(LEFT);
  619. }
  620. else if (ch == KEY_RIGHT) {
  621. gameControl(RIGHT);
  622. }
  623. else if (ch == GAME_AGAIN) {
  624. fetch_level_info(level, user.level_id);
  625. transform_map_db2array(level, map);
  626. show_images(level);
  627. }
  628. else if (ch == KEY_OUT) {
  629. closegraph();
  630. exit(0);
  631. }
  632. if (isGameOver()) {
  633. //更新用户下一关关卡信息(用户通关后直接跳转下一关)
  634. update_user_level(user, level.next_level);
  635. quit = true;
  636. }
  637. }
  638. wait(100);
  639. } while (quit == false);
  640. }
  641. /*****************************
  642. * 功能:根据“由用户ID获取关卡数据”的返回结果进行判断
  643. * 输入:
  644. * result - 返回结果(-1:获取失败 0:用户已通关 1:获取成功)
  645. * level - 关卡数据
  646. * user - 用户信息
  647. * 输出:
  648. * 无
  649. *****************************/
  650. void judge_by_result(levelinfo& level, userinfo& user) {
  651. show_over();
  652. do {
  653. //判断是否有按键按下
  654. if (_kbhit()) {
  655. //无缓冲读取
  656. char ch = _getch();
  657. if (ch == KEY_OUT) {
  658. closegraph();
  659. exit(0);
  660. }
  661. else if (ch == GAME_AGAIN) {
  662. if (!update_user_level(user, 1)) {
  663. std::system("pause");
  664. closegraph();
  665. exit(0);
  666. }
  667. break;
  668. }
  669. }
  670. Sleep(50);
  671. } while (1);
  672. fetch_level_info(level, user.level_id);
  673. }
  674. int main() {
  675. //作为数据初始化,只需运行一次
  676. resetting_data();
  677. load_data();
  678. //用户身份验证
  679. userinfo user;
  680. levelinfo level;
  681. if (!login(user)) {
  682. cout << "登录失败,请重新登录!" << endl;
  683. ::system("pause");
  684. exit(-1);
  685. }
  686. init_graph();
  687. //循环(读取关卡→用户操作)
  688. do {
  689. //根据用户信息加载关卡数据
  690. if (!fetch_level_info(level, user.level_id)) {
  691. judge_by_result(level, user);
  692. }
  693. //将关卡数据数据转换到map游戏地图中
  694. transform_map_db2array(level, map);
  695. //加载游戏图片
  696. show_images(level);
  697. //小人移动
  698. game_operation(level, user);
  699. //恭喜通关
  700. promot_over();
  701. } while (1);
  702. std::system("pause");
  703. closegraph();
  704. return 0;
  705. }

目录

一、推箱子游戏源码(可直接拷贝运行)

二、C语言推箱子游戏实现

1.地图初始化 init_graph( ) + show_images( )

2.地图表示

3.设计操作框架

推荐阅读
相关标签