当前位置:   article > 正文

用C语言写一个简单的飞机大战游戏(用到easyx图形库)_easyx图形库 tool。h

easyx图形库 tool。h

学习内容:1.背景的运动

                  2.飞机爆炸效果

                  3.透明贴图工具

目录

一、需要用到的头文件、全局变量和一些函数、结构体

二、数据初始化以及图片处理

三、主体

四、物体碰撞

五、游戏运行

六、透明贴图工具和定时器


 

一、需要用到的头文件、全局变量和一些函数、结构体

  1. #include<graphics.h>
  2. #include<stdio.h>
  3. #include<easyx.h>
  4. #include<time.h>
  5. #include<stdlib.h>
  6. #include<math.h>
  7. #include<Windows.h>
  8. #include"tool.h"
  9. #pragma comment(lib,"winmm.lib")
  10. #define WIDTH 480
  11. #define HIGHT 700
  12. IMAGE img_bk[2];//背景图
  13. IMAGE img_myplane[2];//玩家飞机
  14. IMAGE img_bullet;//子弹
  15. IMAGE img_enemyplane;//敌机
  16. IMAGE img_enemyboom[4];//敌机爆炸
  17. int bkY[2] = { -700,0 };//两张背景位置
  18. int score = 0;//得分
  19. int enemy_num = 4;//敌机数量
  20. int enemy_add = 0;//敌机需要增加数
  21. //坐标结构体
  22. struct Point
  23. {
  24. int x;
  25. int y;
  26. };
  27. //玩家飞机结构坐标,速度,是否存在
  28. struct Plane
  29. {
  30. int px;
  31. int py;
  32. int speed;
  33. int frame;//用于切换玩家飞机图片
  34. bool exis;
  35. }gamer;
  36. //子弹结构体包括坐标和是否存在(可自行添加子弹种类,速度,方向等属性)
  37. typedef struct Bullet
  38. {
  39. int x;
  40. int y;
  41. bool exis;
  42. Bullet* next;
  43. }mybullet;
  44. mybullet* one_mybullet;
  45. //敌机结构体(可自行添加其他类飞机,boss等)
  46. typedef struct Enemy
  47. {
  48. int posx;//坐标
  49. int posy;
  50. int boom;//爆炸图片帧数
  51. //int type;//飞机类型
  52. bool exis;//是否存活
  53. Enemy* next;
  54. }enemy;
  55. enemy* one_enemy;
  56. void loadImage(); //加载图片
  57. void InitPlayer(Plane* pthis, int x, int y); //初始玩家飞机
  58. void DrawImg(); //绘制图片
  59. void DrawPlayer(Plane* pthis); //绘制玩家飞机
  60. void PlayerMove(); //玩家飞机运动
  61. void RunBk(); //背景运动
  62. void CreateBullet(); //创建子弹
  63. void AddMybullet(); //增加子弹并初始化
  64. void MybulletMove(); //子弹移动
  65. void CreatEnemy(); //创建敌机
  66. void AddEnemy(); //增加敌机并初始化
  67. void EnemyMove(); //敌机移动
  68. void HitEnemy(); //击中敌机
  69. void LoadBoom(); //加载爆炸图片
  70. void AnimalBoom(IMAGE *picture, Enemy* pthis) //飞机爆炸效果
  71. bool overlapationa(enemy* pthis); //判断是否飞机与飞机重叠
  72. bool overlapationb(enemy* pthis); //判断是否子弹与飞机重叠
  73. bool collisiona(enemy* e1, enemy* e2); //判断飞机与飞机是否碰撞
  74. bool collisionb(mybullet* b, enemy* e); //判断飞机与子弹是否碰撞

二、数据初始化以及图片处理

  1. //初始化数据
  2. void InitData()
  3. {
  4. mciSendString("open music/bgm1.mp3 alias bkmusic", NULL, 0, NULL);
  5. mciSendString("play bkmusic repeat", NULL, 0, NULL);
  6. initgraph(WIDTH, HIGHT,SHOWCONSOLE);//图形窗口
  7. InitPlayer(&gamer, (getwidth() - img_myplane->getwidth()) / 2, getheight() / 2 + img_myplane->getheight());
  8. CreateBullet();
  9. CreatEnemy();
  10. loadImage();
  11. }
  12. //加载图片资源
  13. void loadImage()
  14. {
  15. loadimage(img_bk + 0, "images/background1.png");//加载背景图片
  16. loadimage(img_bk + 1, "images/background2.png");//加载背景图片
  17. loadimage(img_myplane + 0, "images/me1.png");//加载玩家飞机
  18. loadimage(img_myplane + 1, "images/me2.png");//加载玩家飞机
  19. loadimage(&img_bullet, "images/bullet1.png");//加载玩家子弹
  20. loadimage(&img_enemyplane, "images/enemy1.png");//加载敌机图片
  21. LoadBoom();
  22. }
  23. //加载敌机爆炸效果(可以给多个飞机做接口,只演示一种飞机爆炸)
  24. void LoadBoom()
  25. {
  26. for (int i = 0; i <= 3; i++)
  27. {
  28. char fileName[30] = {0};
  29. sprintf(fileName, "images/enemy1_down%d.png", i);
  30. loadimage(&img_enemyboom[i], fileName);
  31. }
  32. }
  33. //敌机爆炸效果(避免使用循环语句、会出现卡顿现象)
  34. void AnimalBoom(IMAGE *picture, Enemy* pthis)
  35. {
  36. if (pthis->exis == false && timer(20, 3))//控制帧率
  37. {
  38. drawImg(pthis->posx, pthis->posy, &picture[pthis->boom] );
  39. if (pthis->boom == 3)//当三张爆炸图片全部显示完之后,归零
  40. {
  41. pthis->boom = 0;
  42. pthis->exis = true;
  43. //当创建的敌机与其他敌机重叠时,重新创建,直至不重合
  44. do
  45. {
  46. pthis->posx = rand() % (getheight() / 2);
  47. pthis->posy = -img_enemyplane.getheight();
  48. } while ( overlapationa(pthis));
  49. }
  50. else
  51. {
  52. pthis->boom++;//用于切换下一张图片
  53. }
  54. }
  55. }
  56. //让背景连续滚动(用两张上下连接的背景图,循环运动)
  57. void RunBk()
  58. {
  59. putimage(0, bkY[0], &img_bk[0]);
  60. putimage(0, bkY[1], &img_bk[1]);//打印出背景图片
  61. if (timer(50, 1))
  62. {
  63. bkY[0] ++;
  64. bkY[1] ++;
  65. if (bkY[0] >= 700)
  66. {
  67. bkY[0] = -700;
  68. }
  69. else if (bkY[1] >= 700)
  70. {
  71. bkY[1] = -700;
  72. }
  73. }
  74. }
  75. //绘制图片
  76. void DrawImg()
  77. {
  78. RunBk();//背景滚动
  79. DrawPlayer(&gamer);//打印玩家飞机图片
  80. //打印子弹
  81. mybullet* bt = one_mybullet->next;
  82. while (bt != NULL&&bt->exis == true)
  83. {
  84. drawImg(bt->x, bt->y, &img_bullet);
  85. //printf("%d %d\n", bt->x, bt->y);
  86. bt = bt->next;
  87. }
  88. //打印敌机
  89. enemy* et = one_enemy->next;
  90. while (et != NULL)
  91. {
  92. if (et->exis == true)//飞机不存在时打印爆炸图片
  93. {
  94. drawImg(et->posx, et->posy, &img_enemyplane);
  95. }
  96. else
  97. {
  98. AnimalBoom(img_enemyboom, et);
  99. }
  100. et=et->next;
  101. }
  102. //显示得分
  103. setcolor(BLACK);
  104. settextstyle(25, 0, "黑体");
  105. TCHAR s[5];
  106. _stprintf(s,_T("%d"),score);
  107. outtextxy(20, 20, s);
  108. setbkmode(0);
  109. }

三、主体

玩家、子弹和敌机的初始化,增加数量和运动等

  1. //飞机初始化
  2. void InitPlayer(Plane* pthis,int x,int y)
  3. {
  4. pthis->px = x;
  5. pthis->py = y;
  6. pthis->exis = true;
  7. pthis->frame = 0;
  8. }
  9. //绘制玩家飞机,(让玩家飞机有运动效果)
  10. void DrawPlayer(Plane* pthis)
  11. {
  12. drawImg(pthis->px, pthis->py, img_myplane + pthis->frame);//打印玩家飞机
  13. pthis->frame = (pthis->frame + 1) % 2;
  14. }
  15. //玩家飞机移动
  16. void PlayerMove()//用鼠标移动玩家飞机
  17. {
  18. int startclock = clock();
  19. MOUSEMSG m;//鼠标结构体
  20. while (MouseHit())
  21. {
  22. m = GetMouseMsg();
  23. if (m.uMsg == WM_MOUSEMOVE)
  24. {
  25. gamer.px = m.x - img_myplane->getwidth() / 2;
  26. gamer.py = m.y - img_myplane->getheight() / 2;
  27. }
  28. }
  29. if (timer(200,0) )
  30. {
  31. AddMybullet();
  32. }
  33. }
  34. //创建玩家飞机子弹
  35. void CreateBullet()
  36. {
  37. one_mybullet = (mybullet*)malloc(sizeof(mybullet));
  38. if (one_mybullet == NULL)
  39. {
  40. return;
  41. }
  42. else
  43. {
  44. one_mybullet->next = NULL;
  45. }
  46. }
  47. //加载子弹
  48. void AddMybullet()
  49. {
  50. mybullet* pnew = (mybullet*)malloc(sizeof(mybullet));
  51. if (pnew == NULL)
  52. {
  53. return;
  54. }
  55. else
  56. {
  57. pnew->next = NULL;
  58. pnew->x = gamer.px + 51;
  59. pnew->y = gamer.py ;
  60. pnew->exis = true;
  61. pnew->next = one_mybullet->next;
  62. one_mybullet->next = pnew;
  63. }
  64. }
  65. //让玩家子弹移动
  66. void MybulletMove()
  67. {
  68. mybullet* P1 = one_mybullet->next;
  69. mybullet* P2 = one_mybullet;
  70. for (; P1 != NULL; P1 = P1->next)
  71. {
  72. if (P1->y <= 0 || P1->exis == false)//当子弹越界或者死亡时,释放掉子弹
  73. {
  74. P2->next = P1->next;
  75. free(P1);
  76. return;
  77. }
  78. else
  79. {
  80. P1->y -= 9;
  81. }
  82. P2 = P1;
  83. }
  84. }
  85. //创建敌机
  86. void CreatEnemy()
  87. {
  88. one_enemy = (enemy*)malloc(sizeof(enemy));
  89. if (one_enemy == NULL)
  90. {
  91. return;
  92. }
  93. one_enemy->next = NULL;
  94. }
  95. 增加敌机并初始化
  96. void AddEnemy()
  97. {
  98. //srand((unsigned int)time(NULL));
  99. enemy* ep= (enemy*)malloc(sizeof(enemy));
  100. if (ep == NULL)
  101. {
  102. return;
  103. }
  104. ep->next = NULL;
  105. ep->exis = true;
  106. ep->boom = 0;
  107. ep->next = one_enemy->next;
  108. one_enemy->next = ep;
  109. do
  110. {
  111. ep->posx = rand() % (getheight() / 2);
  112. ep->posy = -img_enemyplane.getheight() / 2;
  113. } while (ep->next != NULL &&overlapationa(ep));//创建的飞机不与其他飞机重叠,否则重新生成
  114. }
  115. // 敌机移动
  116. void EnemyMove()
  117. {
  118. srand((unsigned int)time(NULL));
  119. enemy* pt = one_enemy->next;
  120. while (pt)
  121. {
  122. if (pt->posy >= getheight())
  123. {
  124. do
  125. {
  126. pt->posx = rand() % (getheight() / 2);
  127. pt->posy = -img_enemyplane.getheight();
  128. } while (overlapationa(pt));
  129. }
  130. else
  131. {
  132. pt->posy += 2;
  133. }
  134. pt = pt->next;
  135. }
  136. }

四、物体碰撞

  1. //击中敌机
  2. void HitEnemy()
  3. {
  4. enemy* e = NULL;
  5. mybullet* b = NULL;
  6. e = one_enemy->next;
  7. while (e != NULL)
  8. {
  9. if (e->exis == false)
  10. {
  11. e = e->next;
  12. continue;
  13. }
  14. b = one_mybullet->next;
  15. while (b != NULL)
  16. {
  17. if (b->exis == true && collisionb(b, e))
  18. {
  19. score++;
  20. e->exis = false;
  21. b->exis = false;
  22. }
  23. else
  24. {
  25. b = b->next;
  26. continue;
  27. }
  28. b = b->next;
  29. }
  30. e = e->next;
  31. }
  32. }
  33. //用碰撞物体的四个点的任意点判断是否在被碰撞物范围内
  34. //判断飞机与飞机是否碰撞
  35. bool collisiona(enemy* e1,enemy* e2 )
  36. {
  37. struct Point ap[4] =
  38. {
  39. {e1->posx,e1->posy},
  40. {e1->posx,e1->posy+img_enemyplane.getheight()},
  41. {e1->posx+img_enemyplane.getwidth(),e1->posy},
  42. { e1->posx + img_enemyplane.getwidth() ,e1->posy + img_enemyplane.getheight() }
  43. };
  44. for (int i = 0; i < 4; i++)
  45. {
  46. if (ap[i].x >= e2->posx&&ap[i].x <= e2->posx + img_enemyplane.getwidth() &&
  47. ap[i].y >= e2->posy&&ap[i].y <= e2->posy + img_enemyplane.getwidth())
  48. {
  49. return true;
  50. }
  51. }
  52. return false;
  53. }
  54. //判断子弹与飞机是否碰撞
  55. bool collisionb(mybullet* b, enemy* e)
  56. {
  57. const struct Point ap[4] =
  58. {
  59. { b->x ,b->y },
  60. { b->x,b->y + img_bullet.getheight() },
  61. { b->x + img_bullet.getwidth(),b->y },
  62. { b->x + img_bullet.getwidth() ,b->y + img_bullet.getheight() }
  63. };
  64. for (int i = 0; i < 4; i++)
  65. {
  66. if (ap[i].x >= e->posx&&ap[i].x <= e->posx + img_enemyplane.getwidth() &&
  67. ap[i].y >= e->posy&&ap[i].y <= e->posy + img_enemyplane.getwidth())
  68. {
  69. return true;
  70. }
  71. }
  72. return false;
  73. }
  74. //判断飞机与飞机是否重叠(避免生成飞机堆叠)
  75. bool overlapationa(enemy* pthis)
  76. {
  77. enemy* a = NULL;
  78. a = one_enemy->next;
  79. while (a != NULL)
  80. {
  81. if (pthis == a || a->exis == false)
  82. {
  83. a = a->next;
  84. continue;
  85. }
  86. if (collisiona(pthis, a))
  87. {
  88. return true;
  89. }
  90. a = a->next;
  91. }
  92. return false;
  93. }
  94. bool overlapationb(enemy* pthis)
  95. {
  96. mybullet* a = NULL;
  97. a = one_mybullet->next;
  98. while (a != NULL)
  99. {
  100. if (collisionb(a, pthis))
  101. {
  102. return true;
  103. }
  104. a = a->next;
  105. }
  106. return false;
  107. }

五、游戏运行

  1. //运行游戏
  2. void RunGame()
  3. {
  4. BeginBatchDraw();//防止闪屏
  5. if (enemy_add <= enemy_num)//可以设计关卡来增加敌机数量
  6. {
  7. AddEnemy();
  8. enemy_add++;
  9. }
  10. DrawImg();
  11. PlayerMove();
  12. MybulletMove();
  13. HitEnemy();
  14. EnemyMove();
  15. int startTime = clock();
  16. int frameTime = clock() - startTime;
  17. if (1000 / 60 - frameTime > 0)
  18. {
  19. Sleep(1000 / 30 - frameTime);//控制运行速度
  20. }
  21. EndBatchDraw();//结束绘制
  22. }
  23. //====================================== 主程序===============================
  24. //主程序
  25. int main()
  26. {
  27. InitData();
  28. while (true)
  29. {
  30. RunGame();
  31. }
  32. getchar();
  33. closegraph();
  34. return 0;
  35. }

六、透明贴图工具和定时器

drawImg()用于贴无背景图片与putimage()相似

  1. #pragma once
  2. #include<easyx.h>
  3. void drawImg(int x, int y, IMAGE *src);
  4. void drawImg(int x, int y,int dstw, int dstH, IMAGE *src, int srcX, int srcY);
  5. void drawImg(int x, int y, IMAGE *src)
  6. {
  7. DWORD* pwin = GetImageBuffer();
  8. DWORD* psrc = GetImageBuffer(src);
  9. int win_w = getwidth();
  10. int win_h = getheight();
  11. int src_w = src->getwidth();
  12. int src_h = src->getheight();
  13. int real_w = (x + src_w > win_w) ? win_w - x : src_w;
  14. int real_h = (y + src_h > win_h) ? win_h - y: src_h;
  15. if (x < 0) { psrc += -x; real_w -= -x; x = 0; }
  16. if (y < 0) { psrc += (src_w*-y); real_h -= -y; y = 0; }
  17. pwin +=(win_w*y + x);
  18. for (int iy = 0; iy < real_h; iy++)
  19. {
  20. for (int ix = 0; ix < real_w; ix++)
  21. {
  22. byte a = (byte)(psrc[ix] >> 24);
  23. if (a > 100)
  24. {
  25. pwin[ix] = psrc[ix];
  26. }
  27. }
  28. pwin += win_w;
  29. psrc += src_w;
  30. }
  31. }
  32. void drawImg(int x, int y, int dstW, int dstH, IMAGE* src, int srcX, int srcY)
  33. {
  34. DWORD* pwin = GetImageBuffer();
  35. DWORD* psrc = GetImageBuffer(src);
  36. int win_w = getwidth();
  37. int win_h = getheight();
  38. int src_w = src->getwidth();
  39. int src_h = src->getheight();
  40. int real_w = (x + dstW> win_w) ? win_w - x : dstW;
  41. int real_h = (y + dstH > win_h) ? win_h - y : dstH;
  42. if (x < 0) { psrc += -x; real_w -= -x; x = 0; }
  43. if (y < 0) { psrc += (dstW*-y); real_h -= -y; y = 0; }
  44. pwin += (win_w*y + x);
  45. for (int iy = 0; iy < real_h; iy++)
  46. {
  47. for (int ix = 0; ix < real_w; ix++)
  48. {
  49. byte a = (byte)(psrc[ix + srcX + srcY*src_w] >> 24);
  50. if (a > 100)
  51. {
  52. pwin[ix] = psrc[ix + srcX + srcY*src_w];
  53. }
  54. }
  55. pwin += win_w;
  56. psrc += src_w;
  57. }
  58. }
  59. //定时器
  60. bool timer(int ms, int id)
  61. {
  62. static int start[5];
  63. int end = clock();
  64. if (end - start[id] >= ms)
  65. {
  66. start[id] = end;
  67. return true;
  68. }
  69. return false;
  70. }

总结:实现的内容比较简单,冗余,仅用于学习参考,有兴趣的可以自行添加更多功能,多动手才能有更多的进步哟。

素材:链接:https://pan.baidu.com/s/1XDbXx3C83kyyzkQZL3mmiQ 
提取码:65qv

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号