从零到有的游戏开发(visual studio 2022 + easyx.h)

打印 上一主题 下一主题

主题 1621|帖子 1621|积分 4863



   弁言

  本文章适用于C语言初学者把握基本的游戏开发
我将用详细的步骤引领大家怎样开发属于本身的游戏。
作者温馨提示:不要以为开发游戏很难,一些基本的游戏逻辑其实很简单,
关于游戏的开发情况也不用担心,我会详细说明怎样设置开发情况,下载链接我也会列出。
文章前半部分教你把握开发游戏的基本逻辑(各种游戏逻辑)。
文章后半部分我会提供一个基本的2D脚色饰演的游戏框架,(开发功能取决于玩家)。
   游戏开发情况的设置

  起首我们需要一个能安装easyx.h图形界面库的C语言编译器,这里我保举vsual studio 2022
该编译器功能也是很强盛,可以兼容各种编程语言的项目开发,这里我们只利用C语言即可。

visual studio 2022 的 安装

下载链接:Visual Studio 2022 IDE - 适用于软件开发人员的编程工具

选择图中的 community 2022 社区版本(社区版免费),
然后等待安装资源包的下载。
下载好后,弹出来的窗口,点击继续→
稍稍等待一小会儿.....

从左上角可以看到(工作负荷,单个组件,语言包,安装位置)四个头目次。
起首是(工作负荷):我们只需要勾选 “利用C++的桌面开发”。

然后(单个组件):只需要查抄一下图中是否勾选了上述选项,一样平常不用更改(确定好win系统)
(语言包)默认勾选“简体中文”即可
末了(安装位置)要注意的是分成三个不同的子文件夹,你可以在同一个文件夹中新建三个子文件夹,然后将上述三个位置分别选中子文件夹即可,(如果第三个路径不可选,说明你之前下载过该编译器。)关于安装路径在哪个盘都随意。
第三个路径不可选的解决办法也很简单
第一步 :win + R 打开运行
第二步:输入 regedit 打开注册表
第三步:找到该位置

第四步:删除图中除(默认)以外的设置即可

然后点击安装,等待下载完成即可(需要一段时间,内存不小)

下载好后,运行打开,点击图中创建新项目。

选择空项目点击下一步

输入项目名称和路径

右键点击

新建项

界说名

然后就可以写代码了(你可以用helloworld试试)

如今编译器便安装好了,然后还需要安装图形界面库(很快)
easyx库的设置

下载链接:EasyX Graphics Library for C++

点击右侧红色 “下载EasyX”
下载好后,弹出窗口点击下一步。
然后会自动检测你的编译器版本,找到刚下载的Visual C++2022点击安装,
,表现安装成功就可以了,重启visual studio 2022,即可。
(最上面的EasyX文档也可以安装,里面包罗easyx图形界面库的全部函数用法)
测试easyx库的设置(将下述代码复制进去)

  1. #include<graphics.h> //需安装easyx图形库插件
  2. #include<conio.h>
  3. #include<time.h>
  4. #include<math.h>
  5. #include<sys/timeb.h>
  6. struct MyLove
  7. {
  8.     int NUMS;  //  编号
  9.     double m;
  10.     double n;
  11.     double size;
  12.     bool Is_show;
  13.     int x;
  14.     int y;
  15. };
  16. MyLove mylove[400];
  17. int CenterX = 320;
  18. int CenterY = 180;
  19. double Size = 60;
  20. void initdata();  // 初始化数据
  21. void updata();    // 更新
  22. void movedata();  // 平移
  23. void showdata();  // 显示
  24. int* GetRand(int* buf, int count, int range);  // 随机数的生成
  25. void heart(int x0, int y0, int size, COLORREF C);
  26. void HpSleep(int ms);
  27. int main()
  28. {
  29.     initgraph(640, 480);
  30.     initdata();
  31.     BeginBatchDraw();
  32.     while (true)
  33.     {
  34.         updata();
  35.         showdata();
  36.         HpSleep(30);    // 改为精确延时
  37.         FlushBatchDraw();
  38.         cleardevice();
  39.     }
  40.     EndBatchDraw();
  41.     _getch();
  42.     return 0;
  43. }
  44. void updata()
  45. {
  46.     int* buf = (int*)malloc(sizeof(int) * 20);
  47.     buf = GetRand(buf, 20, (int)(2 * Size / 0.01));
  48.     movedata();
  49.     for (int i = 0; i < 20; i++)
  50.     {
  51.         mylove[i].m = buf[i] * 0.01;
  52.         mylove[i].n = (((sin(buf[(int)i] * 0.01) * sqrt(fabs(cos(buf[(int)i] * 0.01)))) / (sin(buf[(int)i] * 0.01) + 1.4142)) - 2 * sin(buf[(int)i] * 0.01) + 2);
  53.         mylove[i].size = Size;
  54.         mylove[i].NUMS = i / 20;
  55.         mylove[i].Is_show = true;
  56.         mylove[i].x = (int)(-Size * mylove[i].n * cos(mylove[i].m) + CenterX);
  57.         mylove[i].y = (int)(-Size * mylove[i].n * sin(mylove[i].m) + CenterY - mylove[i].size);
  58.     }
  59.     for (int i = 20; i < 400; i++)
  60.     {
  61.         mylove[i].size = mylove[i].size + 1;
  62.         if (mylove[i].size > 80)
  63.         {
  64.             mylove[i].size = 80;
  65.         }
  66.         mylove[i].NUMS = i / 20;
  67.         mylove[i].x = (int)(-mylove[i].size * mylove[i].n * cos(mylove[i].m) + CenterX);
  68.         mylove[i].y = (int)(-mylove[i].size * mylove[i].n * sin(mylove[i].m) + CenterY - mylove[i].size);
  69.     }
  70. }
  71. void movedata()
  72. {
  73.     for (int i = 399; i > 19; i--)
  74.     {
  75.         mylove[i] = mylove[i - 20];
  76.     }
  77. }
  78. void showdata()
  79. {
  80.     settextcolor(RED);
  81.     wchar_t c = 0x59;    // 0x28 是电话机在 Wingdings 字体中的对应编码
  82.     for (int i = 0; i < 400; i++)
  83.     {
  84.         settextstyle(mylove[i].NUMS + 10, 0, _T("Webdings"));
  85.         setbkmode(TRANSPARENT);
  86.         outtextxy(mylove[i].x + 20, mylove[i].y + 20, c);
  87.     }
  88. }
  89. int* GetRand(int* buf, int count, int range)
  90. {
  91.     struct timeb timeSeed;
  92.     ftime(&timeSeed);
  93.     srand(timeSeed.time * 1000 + timeSeed.millitm);  // milli time
  94.     for (int i = 0; i < count; i++)
  95.     {
  96.         int randTmp = rand() % range;
  97.         for (int j = 0; j < i; j++)
  98.         {
  99.             if (buf[j] == randTmp)
  100.             {
  101.                 break;//检查重复。
  102.             }
  103.         }
  104.         buf[i] = randTmp;
  105.     }
  106.     return buf;
  107. }
  108. void initdata()
  109. {
  110.     for (int i = 0; i < 400; i++)
  111.     {
  112.         mylove[i].NUMS = 0;
  113.         mylove[i].m = 0;
  114.         mylove[i].n = 0;
  115.         mylove[i].size = 0;
  116.         mylove[i].Is_show = false;
  117.         mylove[i].x = 0;
  118.         mylove[i].y = 0;
  119.     }
  120. }
  121. // 精确延时函数(可以精确到 1ms,精度 ±1ms)
  122. // by yangw80<yw80@qq.com>, 2011-5-4
  123. void HpSleep(int ms)
  124. {
  125.     static clock_t oldclock = clock();    // 静态变量,记录上一次 tick
  126.     oldclock += ms * CLOCKS_PER_SEC / 1000;  // 更新 tick
  127.     if (clock() > oldclock)          // 如果已经超时,无需延时
  128.         oldclock = clock();
  129.     else
  130.         while (clock() < oldclock)      // 延时
  131.             Sleep(1);            // 释放 CPU 控制权,降低 CPU 占用率,精度 10~16ms
  132.     //      Sleep(0);            // 更高精度、更高 CPU 占用率,精度 1ms
  133. }
复制代码
复制好后,点击上方绿色空三角运行。(运行结果如下)

以上便完成了全部的情况设置,开启开发游戏之旅



基本游戏逻辑

起首需要包罗头文件 #include<easyx.h>来调用图形函数
想要将代码中的结果显现出来,需要一个图形化窗口,并非是黑框框。
所以,第一步初始化一个图形化窗口。
  1. initgraph(800,800);
复制代码
该函数运行后,除了命令提示符的黑窗口之外,还会产生一个新的窗口,此时窗口内是空的。
如果我们想把外部图片贴上去,需要一个容器储存外部图片
  1. IMAGE img;//声明一个可以存储外部图片的容器
复制代码
然后储存外部图片进入容器操作,&img是获取容器地址,“photo.png”是需要引入图片的路径
(路径可分为相对路径和绝对路径,我保举将图片和源程序放到同一个根目次中,既方便引用,又方便后续对于游戏的封装)
  1. loadimage(&img, "photo.png");加载图片进容器
复制代码
那储存好的图片怎样表如今屏幕上,我们需要函数将图片贴到屏幕上。
图中,x,y,前两个函数是指贴入图片的坐标(图片左上角顶点的坐标),
&img参数指贴入的图片容器,确定具体贴入哪个图片。
  1. putimage(x,y, &img);
复制代码
如今基本的图片表现便有了。
如果我们想让这个图片动起来,很好明白,我们只需要逐渐改变putimage函数的坐标参数就可以。
需要一个循环来刷新新的图像(改变坐标之后的贴图),(还需要刷新屏幕,或者利用背景覆盖法)
1,刷新屏幕:FlushBatchDraw ();(不需要参数) 清除掉上一个贴图,执行如今的贴图。
  1. FlushBatchDraw ();
复制代码
2,背景覆盖法:可以每次循环(先贴背景(覆盖掉上个位置的贴图)再贴改变坐标后的贴图)
关于图像的移动

  1. #include<stdio.h>
  2. #include<easyx.h>
  3. #include<windows.h>
  4. IMAGE back;
  5. IMAGE img;
  6. int main()
  7. {
  8. loadimg (&back,"选中背景图片的路径");
  9. loadimg (&img,"选中目标图片的路径");
  10. for(int i=1;i<=500;i++)
  11. {
  12. putimage(0,0,&back);
  13. putimage(i,i,&img);
  14. Sleep(100);
  15. }
  16. return 0;
  17. }
复制代码
其中,&back 是获取背景(IMAGE back 容器存储着与窗口大小同等的背景图片),
所以每次贴图的坐标是0,0,
&img存取的则是需要移动的目标贴图,
每次循环,会在不同坐标贴上目标图片,
由于每次循环都会贴一次背景图,所以会覆盖掉前次的目标贴图,再贴下次的目标贴图,
这样,窗口中就始终只能看到一个目标贴图,且位置在不停发生改变,产生目标图片移动的结果。
(Sleep(100)是没隔100ms也就是每0.1秒刷新一次位置,不然上述循环会在一瞬间结束,无法观察,该函数在Windows.h库内)
上述代码就会产生一个从(1,1)移动到(500,500)的图像。
自主控制及时移动

既然贴图函数的坐标参数决定了目标图像的位置,那么我们如果按下相应的按键改变坐标参数,便可实现用按键控制移动,
我们可以调用一个Windows.h函数 GetAsyncKeyState('D') ,括号内参数是被检测的按键,
如果D( 不分大小写)按键被按下,则返回非零值,否则返回零,
所以,该代码便可检测按键的及时状态,如果按下D则x++(向右移动)
  1. if(GetAsyncKeyState('D'))
  2. x++;
复制代码
所以整体移动函数模块就是(其中设置了范围,防止目标移动出边界),每次增长或减少的值不是1,而是一个预先界说好的值,可以自由控制移动速率(#define SPEED 10)
  1. void control_move()//控制人物移动
  2. {
  3.         if (GetAsyncKeyState('D') && hero.x < width)//角色右移
  4.         {
  5.                 hero.x += SPEED;
  6.         }
  7.         if (GetAsyncKeyState('A') && hero.x > 0)//角色左移
  8.         {
  9.                 hero.x -= SPEED;
  10.         }
  11.         if (GetAsyncKeyState('W') && hero.y > 0)//角色上移
  12.                 hero.y -= SPEED;
  13.         if (GetAsyncKeyState('S') && hero.y < high)//角色下移
  14.                 hero.y += SPEED;
  15. }
复制代码
然后把这个函数放入主循环内,因为游戏是同等运行的,所以全部需要改变的举动都要放到一个主循环内,由于GetAsyncKeyState是非壅闭性函数,也就是说,纵然没有按键按下,主循环依然循环着,游戏连续运行着,只是目标贴图未移动。
  1. int main()
  2. {
  3. ....省略
  4. while(1)
  5. {
  6. control_move();
  7. putimage(0,0,&back);
  8. putimage(i,i,&img);
  9. }
  10. return 0;}
复制代码
关于目标发射物(开发目标远程攻击)

  1. struct bang{
  2. int x;//坐标
  3. int y;
  4. bool live = false;//是否存活
  5. }fire;
  6. if(GetAsyncKeyState('j'))
  7. fire.live = true;
  8. if(fire.live)
  9. {
  10. fire.x+=SPEED;
  11. putimage(x,y,&img);
  12. }
复制代码
需要设定发射物的结构体,如果检测到J按键,则让发射物存活,并且自界说逻辑发射出去。
图中假设只有一个发射物,并且横向发射移动,如果需要发射多个,则只需要将结构体变量改成结构体变量数组,然后每次判定存活和移动的操作加一个外层数组遍历,同时同步所有状态。
如今基本的移动和发射逻辑都已说明

我们还需要一些辅助函数代码块,比如时间戳,每间隔多少ms运行一次函数体,且不壅闭主循环
  1. bool timer(int ms, int id)//时间戳
  2. {
  3.         static DWORD t[500];
  4.         // 将 clock() 的返回值转换为 DWORD 类型
  5.         if (static_cast<DWORD>(clock()) - t[id] > static_cast<DWORD>(ms))
  6.         {
  7.                 t[id] = static_cast<DWORD>(clock());
  8.                 return true;
  9.         }
  10.         return false;
  11. }
  12. /*时间戳*/
复制代码


   飞机大战测试

  1,头文件
  1. #include<stdio.h>
  2. #include<easyx.h>
  3. #include<conio.h>
  4. #include<time.h>
  5. #include<windows.h>
  6. #include<stdlib.h>
复制代码
2,设定图形变量存储图片
  1. IMAGE BACK_DROP;
  2. IMAGE PLANE_1;//飞机1
  3. IMAGE PLANE_2;//飞机2
  4. IMAGE DG_1;//敌机1
  5. IMAGE DG_2;//敌机2
  6. IMAGE BULLET_1;//子弹1
  7. IMAGE BULLET_2;//子弹2
复制代码
3,预界说需要利用参数值   设定 结构体(飞机和敌机)
  1. enum My {
  2.         WIDTH = 600,
  3.         HEIGHT = 864,
  4.         BULLET_NUM = 300,
  5.         SHIP_SPEED = 2,
  6.         BULLET_SPEED = 30,
  7.         ENEMY_NUM = 5,
  8.         ENEMY_SPEED = 1,
  9. };
  10. struct ZT//状态结构体
  11. {
  12.         int x;
  13.         int y;  //坐标
  14.         int hp = 100;//血量
  15.         bool live = false;//是否存活
  16.         int width;
  17.         int height;
  18. };
  19. ZT myplane;//飞机
  20. ZT BULLET[BULLET_NUM];//子弹
  21. ZT ENEMY[ENEMY_NUM];//敌机
复制代码
基本互动(如果子弹和敌机图像有交织,则判定击中,减血,血量<=0则判定死亡 )
  1. int play()
  2. {
  3.         for (int i = 0;i <= ENEMY_NUM;i++)
  4.         {
  5.                 if (!ENEMY[i].live)
  6.                 {
  7.                         continue;
  8.                 }
  9.                 for (int j = 0;j < BULLET_NUM;j++)
  10.                 {
  11.                         if (!BULLET[i].live)
  12.                         {
  13.                                 continue;
  14.                         }//检测击中
  15.                         if (BULLET[j].x > ENEMY[i].x && BULLET[j].x<ENEMY[i].x + ENEMY[i].width
  16.                                 && BULLET[j].y>ENEMY[i].y && BULLET[j].y < ENEMY[i].y + ENEMY[i].height)
  17.                         {
  18.                                 BULLET[i].live = false;
  19.                                 ENEMY[i].hp--;
  20.                         }//掉血就去死,ok?
  21.                         if (ENEMY[i].hp == 0)
  22.                         {
  23.                                 ENEMY[i].live = false;
  24.                         }
  25.                 }
  26.         }
  27.         return 0;
  28. }
复制代码
子弹和敌机的创建
  1. int PLANE_MY()//构建飞机和子弹和敌机
  2. {
  3.         //绘制飞机
  4.         putimage(myplane.x, myplane.y, &PLANE_1,NOTSRCERASE);
  5.         putimage(myplane.x, myplane.y, &PLANE_2, SRCINVERT);
  6.         //绘制子弹
  7.         for (int i = 0;i <= BULLET_NUM;i++)
  8.         {
  9.                 if (BULLET[i].live)
  10.                 {
  11.                         putimage(BULLET[i].x, BULLET[i].y, &BULLET_2, NOTSRCERASE);
  12.                         putimage(BULLET[i].x, BULLET[i].y, &BULLET_1, SRCINVERT);
  13.                 }
  14.         }//绘制敌机
  15.         for (int i = 0;i <= ENEMY_NUM;i++)
  16.         {
  17.                 if (ENEMY[i].live)
  18.                 {
  19.                         putimage(ENEMY[i].x, ENEMY[i].y, &DG_2, NOTSRCERASE);
  20.                         putimage(ENEMY[i].x, ENEMY[i].y, &DG_1, SRCINVERT);
  21.                 }
  22.         }
  23.         return 0;
  24. }
  25. int createbullet()//子弹创建
  26. {
  27.         for (int i = 0;i <= BULLET_NUM;i++)
  28.         {
  29.                 if (!BULLET[i].live)
  30.                 {
  31.                         BULLET[i].x = myplane.x + 49;
  32.                         BULLET[i].y = myplane.y;
  33.                                 BULLET[i].live = true;
  34.                                 break;
  35.                 }
  36.         }
  37.         return 0;
  38. }
复制代码
详细表明一下该部分(利用两张互补的色差图像可以实现透明贴图,后续有优化版本)
  1. putimage(BULLET[i].x, BULLET[i].y, &BULLET_2, NOTSRCERASE);
  2.                         putimage(BULLET[i].x, BULLET[i].y, &BULLET_1, SRCINVERT);
复制代码
子弹和敌机的移动,以及碰撞检测(检测可以放到里面,也可以独立出一个函数)非
  1. int bulletmove()//子弹移动
  2. {
  3.         for (int i = 0;i <= BULLET_NUM;i++)
  4.         {
  5.                 if (BULLET[i].live)
  6.                 {
  7.                         BULLET[i].y -= BULLET_SPEED;
  8.                 }
  9.                 if (BULLET[i].y < 0)
  10.                 {
  11.                         BULLET[i].live = false;
  12.                 }
  13.         }
  14.         return 0;
  15. }
  16. int createenemy()
  17. {
  18.         for (int i = 0;i <= ENEMY_NUM;i++)
  19.         {
  20.                 if (!ENEMY[i].live)
  21.                 {
  22.                         ENEMY[i].x = rand() % (WIDTH - 60);
  23.                         ENEMY[i].y = 0;
  24.                         ENEMY[i].live = true;
  25.                         break;
  26.                 }
  27.                 enemyhp(i);
  28.         }
  29.         return 0;
  30. }
  31. int enemymove()//敌机的移动
  32. {
  33.         for (int i = 0;i <= ENEMY_NUM;i++)
  34.         {
  35.                 if (ENEMY[i].live)
  36.                 {
  37.                         ENEMY[i].y += ENEMY_SPEED;
  38.                 }
  39.                 if (ENEMY[i].y > HEIGHT)
  40.                 {
  41.                         ENEMY[i].live = false;
  42.                 }
  43. }
  44.         return 0;
  45. }
  46. int penzhuang()//碰撞检测
  47. {
  48.         for (int i = 0;i <= ENEMY_NUM;i++)
  49.         {
  50.                 if (myplane.y <= ENEMY[i].y && myplane.y >= ENEMY[i].y + ENEMY[i].height
  51.                         && myplane.x >= ENEMY[i].x && myplane.x <= ENEMY[i].x + ENEMY[i].width)
  52.                 {
  53.                         myplane.live = false;
  54.                         exit(0);
  55.                 }
  56.         }
  57. }
复制代码
需要采用双缓冲画图法,可以去除游戏循环的卡顿,
  1. BeginBatchDraw();        开始批量绘图。写在循环外
  2. EndBatchDraw();        结束批量绘制,并执行未完成的绘制任务。循坏外,程序结束前
  3. FlushBatchDraw();        执行未完成的绘制任务。写在循环内,构图后,延迟前
复制代码
  

  飞机大战代码汇总

  1. #include<stdio.h>
  2. #include<easyx.h>
  3. #include<conio.h>
  4. #include<time.h>
  5. #include<windows.h>
  6. #include<stdlib.h>//牢笼IMAGE BACK_DROP;IMAGE PLANE_1;IMAGE PLANE_2;IMAGE DG_1;IMAGE DG_2;IMAGE BULLET_1;IMAGE BULLET_2;enum My {        WIDTH = 600,        HEIGHT = 864,        BULLET_NUM = 300,        SHIP_SPEED = 2,        BULLET_SPEED = 30,        ENEMY_NUM = 5,        ENEMY_SPEED = 1,};const int MAX = 10;struct ZT//状态结构体{        int x;        int y;  //坐标        int hp = 100;//血量        bool live = false;//是否存活        int width;        int height;}; ZT myplane;//飞机 ZT BULLET[BULLET_NUM];//子弹 ZT ENEMY[ENEMY_NUM];//敌机int DRAW_BACKDROP()//构造背景图{        putimage(0, 0, &BACK_DROP);        return 0;}int enemyhp(int i){        ENEMY[i].hp = 1;        ENEMY[i].width = 90;                ENEMY[i].height = 100;        return 0;}int play()
  7. {
  8.         for (int i = 0;i <= ENEMY_NUM;i++)
  9.         {
  10.                 if (!ENEMY[i].live)
  11.                 {
  12.                         continue;
  13.                 }
  14.                 for (int j = 0;j < BULLET_NUM;j++)
  15.                 {
  16.                         if (!BULLET[i].live)
  17.                         {
  18.                                 continue;
  19.                         }//检测击中
  20.                         if (BULLET[j].x > ENEMY[i].x && BULLET[j].x<ENEMY[i].x + ENEMY[i].width
  21.                                 && BULLET[j].y>ENEMY[i].y && BULLET[j].y < ENEMY[i].y + ENEMY[i].height)
  22.                         {
  23.                                 BULLET[i].live = false;
  24.                                 ENEMY[i].hp--;
  25.                         }//掉血就去死,ok?
  26.                         if (ENEMY[i].hp == 0)
  27.                         {
  28.                                 ENEMY[i].live = false;
  29.                         }
  30.                 }
  31.         }
  32.         return 0;
  33. }
  34. int PLANE_MY()//构建飞机和子弹和敌机
  35. {
  36.         //绘制飞机
  37.         putimage(myplane.x, myplane.y, &PLANE_1,NOTSRCERASE);
  38.         putimage(myplane.x, myplane.y, &PLANE_2, SRCINVERT);
  39.         //绘制子弹
  40.         for (int i = 0;i <= BULLET_NUM;i++)
  41.         {
  42.                 if (BULLET[i].live)
  43.                 {
  44.                         putimage(BULLET[i].x, BULLET[i].y, &BULLET_2, NOTSRCERASE);
  45.                         putimage(BULLET[i].x, BULLET[i].y, &BULLET_1, SRCINVERT);
  46.                 }
  47.         }//绘制敌机
  48.         for (int i = 0;i <= ENEMY_NUM;i++)
  49.         {
  50.                 if (ENEMY[i].live)
  51.                 {
  52.                         putimage(ENEMY[i].x, ENEMY[i].y, &DG_2, NOTSRCERASE);
  53.                         putimage(ENEMY[i].x, ENEMY[i].y, &DG_1, SRCINVERT);
  54.                 }
  55.         }
  56.         return 0;
  57. }
  58. int createbullet()//子弹创建
  59. {
  60.         for (int i = 0;i <= BULLET_NUM;i++)
  61.         {
  62.                 if (!BULLET[i].live)
  63.                 {
  64.                         BULLET[i].x = myplane.x + 49;
  65.                         BULLET[i].y = myplane.y;
  66.                                 BULLET[i].live = true;
  67.                                 break;
  68.                 }
  69.         }
  70.         return 0;
  71. }
  72. bool timer(int ms, int id)//制造随机性{        static DWORD t[MAX];        if (clock() - t[id] > ms)        {                t[id] = clock();                return true;        }        return false;}int bulletmove()//子弹移动
  73. {
  74.         for (int i = 0;i <= BULLET_NUM;i++)
  75.         {
  76.                 if (BULLET[i].live)
  77.                 {
  78.                         BULLET[i].y -= BULLET_SPEED;
  79.                 }
  80.                 if (BULLET[i].y < 0)
  81.                 {
  82.                         BULLET[i].live = false;
  83.                 }
  84.         }
  85.         return 0;
  86. }
  87. int createenemy()
  88. {
  89.         for (int i = 0;i <= ENEMY_NUM;i++)
  90.         {
  91.                 if (!ENEMY[i].live)
  92.                 {
  93.                         ENEMY[i].x = rand() % (WIDTH - 60);
  94.                         ENEMY[i].y = 0;
  95.                         ENEMY[i].live = true;
  96.                         break;
  97.                 }
  98.                 enemyhp(i);
  99.         }
  100.         return 0;
  101. }
  102. int enemymove()//敌机的移动
  103. {
  104.         for (int i = 0;i <= ENEMY_NUM;i++)
  105.         {
  106.                 if (ENEMY[i].live)
  107.                 {
  108.                         ENEMY[i].y += ENEMY_SPEED;
  109.                 }
  110.                 if (ENEMY[i].y > HEIGHT)
  111.                 {
  112.                         ENEMY[i].live = false;
  113.                 }
  114. }
  115.         return 0;
  116. }
  117. int penzhuang()//碰撞检测
  118. {
  119.         for (int i = 0;i <= ENEMY_NUM;i++)
  120.         {
  121.                 if (myplane.y <= ENEMY[i].y && myplane.y >= ENEMY[i].y + ENEMY[i].height
  122.                         && myplane.x >= ENEMY[i].x && myplane.x <= ENEMY[i].x + ENEMY[i].width)
  123.                 {
  124.                         myplane.live = false;
  125.                         exit(0);
  126.                 }
  127.         }
  128. }
  129. int main(){        initgraph(600, 1000);        loadimage(&BACK_DROP, "back.jpg");        loadimage(&PLANE_1,"plane1.png");        loadimage(&PLANE_2, "plane2.png");        loadimage(&DG_1, "D1.png");        loadimage(&DG_2, "D2.png");        loadimage(&BULLET_1, "zd1.png");        loadimage(&BULLET_2, "zd2.png");        myplane.x = 200;        myplane.y = 500;        myplane.live = true;        for (int i = 0;i <= BULLET_NUM;i++)        {                BULLET[i].x = 0;                BULLET[i].y = 0;                BULLET[i].live = false;                        }        while (1)        {                                if (_kbhit())//检测案件发生                {                        char c = _getch();//获取键盘信息                        switch (c)//控制移动                        {                        case 'w'://上                                if (myplane.y >= 10)                                        myplane.y -= 20;                                break;                        case 's'://下                                if (myplane.y <= 885)                                        myplane.y += 20;                                break;                        case 'a'://左                                if (myplane.x >= 20)                                        myplane.x -= 20;                                break;                        case 'd'://右                                if (myplane.x <= 465)                                        myplane.x += 20;                                break;                        case 'j':                                createbullet();                                break;                        }                }                else {                        Sleep(100);//基本刷新频率                }                                                DRAW_BACKDROP();//构建背景图                //FlushBatchDraw();                PLANE_MY();//基本原件生成                bulletmove();//子弹移动                                if (timer(500, 0))//控制敌机的出现频率                {                        createenemy();                }                if (timer(30, 2))                        {                                enemymove();                }                play();//打                penzhuang();//碰撞检测                        }//主循环        return 0;}//八个小时,老弟。
复制代码
 需要链接图片才可以运行哦,(上述说过,需要将目标图片放入指定容器)
上述可能会不太好明白,纯干货,可以参照b站课程



   原创优化游戏逻辑的2D脚色饰演游戏框架

  先展示优化的游戏函数
设定好的全局变量和常量宏
  1. #include <graphics.h>//图形算法库
  2. #include <conio.h>//控制台交流库
  3. #include<windows.h>//系统函数库
  4. #include<stdio.h>//标准输入输出库
  5. #include<time.h>//时间定义库
  6. #include<easyx.h>//图形界面库
  7. #include<math.h>//数学函数库
  8. #pragma comment( lib, "MSIMG32.LIB")//图形链接库
  9. //============================================================================预处理
  10. #define M_PI 3.1415926  //圆周率
  11. #define HERO_SPEED  1     //hero.移动速度
  12. #define HERO_JUMP_SPEED 10 //hero.跳跃帧高度
  13. #define HERO_JUMP_NUM  5   //hero.跳跃帧数
  14. #define LIGHT_SWORD_SPEED 3 //light_sword.光刃飞行速度
  15. #define DRAGON_NUM_MAX 2 //龙同时存在最大数量
  16. #define DRAGON_SPEED 2 //龙的移动速度
  17. //============================================================================常量宏
  18. int HEIGHT = 1000;//当前屏幕设备的高度(单位毫米)
  19. int WIDTH = 1700;//当前屏幕设备的宽度(单位毫米)
  20. IMAGE back;//背景
  21. IMAGE stop_imgR[13];//静止 右 待机动作
  22. IMAGE stop_imgL[13];//静止 左 待机动作
  23. IMAGE run_imgR[5];//奔跑 右 动作
  24. IMAGE run_imgL[5];//奔跑 左 动作
  25. IMAGE raise_sword;//举剑的动作
  26. IMAGE light_sword_imgR;//右光刃
  27. IMAGE light_sword_imgL;//左光刃
  28. IMAGE HP_img;//血量显示
  29. IMAGE MP_img;//蓝量显示
  30. IMAGE TX_ADD_HP[16]; //加血特效图
  31. IMAGE dragon_imgR[7]; //右 龙图片
  32. IMAGE dragon_imgL[7]; //左 龙图片
  33. IMAGE light_effect[31]; //受击光效图片
  34. int run_num = 1;//移动动作循环底码
  35. int stop_num = 1;//待机动作循环底码
  36. int TX_ADD_HP_num = 1;//特效图像循环底码
  37. int dragon_img_num = 1;//龙图运动循环底码
  38. int Affected_img_num = 1;//基础光刃受击特效图循环底码
  39. bool Previous_direction = true;//前一时刻方向判定量
  40. int dragon_rand_move_num[DRAGON_NUM_MAX + 1];//龙的随机运动底码
  41. int dragon_rand_pursuit_num[DRAGON_NUM_MAX + 1];//龙的随机追击底码
  42. //=============================================================================全局变量
复制代码
设定好的结构体
  1. struct role {
  2.         int x = 200;                        //hero.x坐标
  3.         int y = 100;                        //hero.y坐标
  4.         int blood = 100;    //hero.血量
  5.         int blue = 100;     //hero.蓝量
  6.         bool live = true;   //hero.存活
  7.         bool ground = true; //hero.触地
  8. }hero;
  9. /*人物状态结构体*/
  10. struct sword {
  11.         int x = 0;//光刃x坐标
  12.         int y = 0;//光刃y坐标
  13.         bool live = false;//光刃存活
  14.         bool direction = true;//光刃方向
  15. };
  16. /*基本远程攻击结构体*/
  17. struct sword light_sword[11];//光刃
  18. struct Special_effects {
  19.         int x = 1; //特效.x坐标
  20.         int y = 1; //特效.y坐标
  21.         bool live = false; //是否激活
  22. };
  23. /*基本特效结构体*/
  24. struct Special_effects add_blood; //加血特效
  25. struct Special_effects Affected_effect[11];//基础光刃受击效果
  26. struct move {//基本移动体坐标
  27.         int x = 800;
  28.         int y = 500;//坐标
  29.         int HP = 100;//血量
  30.         int speed_x = 10;
  31.         int speed_y = 10;//速度
  32.         bool live = false;//是否存活
  33.         bool if_move = true; //是否能移动
  34.         bool direction = true;//向左向右
  35.         bool pursuit = true;//是否追击
  36.         int die_num_zhen = 0;//死亡后的帧数
  37. };
  38. //基本敌对目标结构体
  39. struct move dragon[DRAGON_NUM_MAX + 1]; //敌龙  同时最多存在五只
  40. //==============================================================================结构体
复制代码
加载图片
  1. void load()//加载图片素材
  2. {
  3.         loadimage(&back, "back.png", 1700, 1000);//背景图的加载
  4.         loadimage(&HP_img, "HP.png", 100, 50);//血条HP图片加载
  5.         loadimage(&MP_img, "MP.png", 100, 50);//蓝条MP图片加载
  6.         //loadimage(&raise_sword, "attack.png", 400, 400);//攻击举剑动作图片加载
  7.         loadimage(&light_sword_imgR, "光刃.png", 400, 400);//右光刃攻击特效图片加载
  8.         loadimage(&light_sword_imgL, "光刃f.png", 400, 400);//左光刃攻击特效图片加载
  9.         for (int i = 1;i <= 9;i++)//01.png  02.png  03.png  04........
  10.         {
  11.                 char str[50];
  12.                 sprintf_s(str, "0%d.png", i);
  13.                 loadimage(&stop_imgR[i], str, 200, 200);//加载待机动作
  14.         }
  15.         for (int x = 10;x <= 12;x++)
  16.         {
  17.                 char str2[50];
  18.                 sprintf_s(str2, "%d.png", x);
  19.                 loadimage(&stop_imgR[x], str2, 200, 200);//加载 右 待机动作
  20.         }
  21.         for (int y = 1;y <= 4;y++)
  22.         {
  23.                 char str3[50];
  24.                 char str4[50];
  25.                 sprintf_s(str3, "run%d.png", y);
  26.                 loadimage(&run_imgR[y], str3, 180, 180);//加载 右 奔跑动作
  27.                 sprintf_s(str4, "frun%d.png", y);
  28.                 loadimage(&run_imgL[y], str4, 180, 180);//加载 左 奔跑动作
  29.         }
  30.         for (int a = 1; a <= 12; a++)
  31.         {
  32.                 char str5[50];
  33.                 sprintf_s(str5, "fs%d.png", a);
  34.                 loadimage(&stop_imgL[a], str5, 200, 200);//加载 左 待机动作
  35.         }
  36.         for (int i = 1;i <= 15;i++)//加载加血特效
  37.         {
  38.                 char str6[50];
  39.                 sprintf_s(str6, "tx%d.png", i);
  40.                 loadimage(&TX_ADD_HP[i], str6, 400, 400);
  41.         }
  42.         for (int i = 1;i <= 6;i++)//加载龙的素材图
  43.         {
  44.                 char str7[50];
  45.                 sprintf_s(str7, "dg%d.png", i);
  46.                 loadimage(&dragon_imgR[i], str7, 200, 200);
  47.                 char str8[50];
  48.                 sprintf_s(str8, "dgf%d.png", i);
  49.                 loadimage(&dragon_imgL[i], str8, 200, 200);
  50.         }
  51.         for (int i = 1;i <= 30;i++)//加载受击光效
  52.         {
  53.                 char str9[50];
  54.                 sprintf_s(str9, "gx%d.png", i);
  55.                 loadimage(&light_effect[i], str9, 200, 200);
  56.         }
  57. }
  58. //加载图片素材
复制代码
时间戳
  1. bool timer(int ms, int id)//时间戳
  2. {
  3.         static DWORD t[500];
  4.         // 将 clock() 的返回值转换为 DWORD 类型
  5.         if (static_cast<DWORD>(clock()) - t[id] > static_cast<DWORD>(ms))
  6.         {
  7.                 t[id] = static_cast<DWORD>(clock());
  8.                 return true;
  9.         }
  10.         return false;
  11. }
  12. /*时间戳*/
复制代码
获取屏幕参数(全屏的关键)
  1. /*获取当前屏幕的参数*/
  2. void transparentimage3(IMAGE* dstimg, int x, int y, IMAGE* srcimg) //png_windows透明贴图
  3. {
  4.         HDC dstDC = GetImageHDC(dstimg);
  5.         HDC srcDC = GetImageHDC(srcimg);
  6.         int w = srcimg->getwidth();
  7.         int h = srcimg->getheight();
  8.         BLENDFUNCTION bf = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
  9.         AlphaBlend(dstDC, x, y, w, h, srcDC, 0, 0, w, h, bf);
  10. }
复制代码
前面我们每个目标都要采用两张叠加的图片才能实现透明贴图,而该函数只需要利用wps工具将单个图片背景设置成win的透明背景,然后插入该函数可自动剔除掉背景
  1. void transparentimage3(IMAGE* dstimg, int x, int y, IMAGE* srcimg) //png_windows透明贴图
  2. {
  3.         HDC dstDC = GetImageHDC(dstimg);
  4.         HDC srcDC = GetImageHDC(srcimg);
  5.         int w = srcimg->getwidth();
  6.         int h = srcimg->getheight();
  7.         BLENDFUNCTION bf = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
  8.         AlphaBlend(dstDC, x, y, w, h, srcDC, 0, 0, w, h, bf);
  9. }
  10. /*windows.h 的png透明贴图工具*/
复制代码
原创函数,用于可控范围的切换图片目标,实现特定范围的人物移动行走结果,和特效

  1. void random_nums()//一帧内生成十个的随机数,前五个赋值给龙的判断移动变量,后五个给龙的追击判断变量
  2. {
  3.         int num = 10;
  4.         int used[100] = { 0 };  // 标记数组,初始化为 0
  5.         int numbers[10];
  6.         srand((unsigned int)time(NULL));  // 初始化随机数种子
  7.         for (int i = 0; i < num; i++) {
  8.                 int num;
  9.                 do {
  10.                         num = rand() % 100;  // 生成 0 到 RANGE - 1 之间的随机数
  11.                 } while (used[num]);  // 如果该数字已被使用,则重新生成
  12.                 numbers[i] = num;
  13.                 used[num] = 1;  // 标记该数字已被使用
  14.         }
  15.         // 输出生成的随机数
  16.         for (int i = 1; i <= num / 2; i++) {
  17.                 dragon_rand_move_num[i] = numbers[i];
  18.         }
  19.         for (int i = num / 2 + 1;i <= num;i++)
  20.         {
  21.                 dragon_rand_pursuit_num[i - num / 2] = numbers[i];
  22.         }
  23. }
  24. //一帧内生成特定数量的随机数
  25. int cycle_count(int min, int max, int type)//调用返回值从min~max之间的单向循环
  26. {
  27.         static int count[10];
  28.         while (count[type] < min - 1)
  29.                 count[type]++;
  30.         count[type]++;
  31.         if (count[type] > max)
  32.                 count[type] = min;
  33.         return count[type];
  34. }//不同type参数分配不同的静态变量count
  35. /*可控范围的底码循环,用于运动图片的切换*/
  36. 控制特效的单次便利图像运行,单次便利结束后,将传入的bool类型指针变为false
  37. void draw_effect_ADD_blood()
  38. {
  39.         if (add_blood.live)
  40.                 transparentimage3(NULL, hero.x - 100, hero.y - 150, &TX_ADD_HP[TX_ADD_HP_num]);
  41. }
复制代码
控制移动(通过检测前次的移动方向,可以知道某时候脚色的面朝向,从而决定贴图朝向)
  1. void control_hero()//控制人物移动
  2. {
  3.         if (GetAsyncKeyState('D') && hero.x < 1550)//角色右移
  4.         {
  5.                 hero.x += HERO_SPEED;
  6.                 Previous_direction = true;
  7.         }
  8.         if (GetAsyncKeyState('A') && hero.x > -5)//角色左移
  9.         {
  10.                 hero.x -= HERO_SPEED;
  11.                 Previous_direction = false;
  12.         }
  13.         if (GetAsyncKeyState('W') && hero.y > -5)//角色上移
  14.                 hero.y -= HERO_SPEED;
  15.         if (GetAsyncKeyState('S') && hero.y < 850)//角色下移
  16.                 hero.y += HERO_SPEED;
  17. }
  18. /*控制角色移动*/
复制代码
发射物光刃一体化程序
  1. //创造光刃
  2. void move_sword()
  3. {
  4.         for (int i = 1;i <= 10;i++)
  5.         {
  6.                 if (light_sword[i].live)
  7.                 {
  8.                         if (light_sword[i].direction)//是否朝右
  9.                                 light_sword[i].x += LIGHT_SWORD_SPEED;
  10.                         else
  11.                                 light_sword[i].x -= LIGHT_SWORD_SPEED;
  12.                 }
  13.         }
  14. }
  15. //移动光刃
  16. void draw_sword()
  17. {
  18.         for (int i = 1;i <= 10;i++)
  19.                 if (light_sword[i].live)
  20.                 {
  21.                         if (light_sword[i].direction)
  22.                                 transparentimage3(NULL, light_sword[i].x, light_sword[i].y, &light_sword_imgR);
  23.                         else
  24.                                 transparentimage3(NULL, light_sword[i].x, light_sword[i].y, &light_sword_imgL);
  25.                 }
  26. }
  27. //绘画光刃
  28. void draw_HPMP()
  29. {
  30.         transparentimage3(NULL, 10, 10, &HP_img);
  31.         transparentimage3(NULL, 10, 70, &MP_img);
  32. }
  33. //对基本光刃受击特效的绘画
  34. void Attack_detection()
  35. {
  36.         for (int i = 1;i <= 10;i++)
  37.         {
  38.                 int ctr = 1;
  39.                 for (int a = 1;a <= DRAGON_NUM_MAX;a++)
  40.                 {
  41.                         if (light_sword[i].x - dragon[a].x<200 && light_sword[i].x - dragon[a].x>-200 && light_sword[i].live)
  42.                                 if (dragon[a].live)
  43.                                         if (light_sword[i].y - dragon[a].y<0 && light_sword[i].y - dragon[a].y>-200)
  44.                                         {
  45.                                                 dragon[a].HP -= 20;
  46.                                                 Affected_effect[i].x = dragon[a].x + 50;
  47.                                                 Affected_effect[i].y = dragon[a].y + 30;
  48.                                                 Affected_effect[i].live = true;
  49.                                                 light_sword[i].live = false;
  50.                                                 ctr = 0;
  51.                                                 break;
  52.                                         }
  53.                 }
  54.                 if (ctr == 0)
  55.                         break;
  56.         }
  57. }
  58. //基本光刃命中判定以及反馈
复制代码
游戏特效
  1. //创造加血特效 (内含按键 U )
  2. int control_effect_count(int min, int max, bool* live, int type)//控制特效的单次循环运行
  3. {
  4.         static int count[10] = { min - 1 };
  5.         count[type]++;
  6.         if (count[type] >= max + 1)
  7.         {
  8.                 *live = false;
  9.                 count[type] = min - 1;
  10.                 return count[type] + 1;
  11.         }
  12.         return count[type];
  13. }
  14. //加血特效的绘画
  15. void select_dragon_speed() //根据距离分配速度
  16. {
  17.         for (int i = 1;i <= DRAGON_NUM_MAX;i++)
  18.                 if (dragon[i].pursuit && dragon[i].live)
  19.                 {//同时满足追击和移动和存活条件后,赋值追击速度
  20.                         double cx = (double)(dragon[i].x - hero.x);  //敌我x坐标差
  21.                         double cy = (double)(dragon[i].y - hero.y);  //敌我y坐标差
  22.                         double cz = sqrt(cx * cx + cy * cy);     //绝对距离
  23.                         if (cx == 0 && cy == 0)//防止敌我目标重合带来的除0bug
  24.                         {
  25.                                 cz = 1;
  26.                         }
  27.                         double cxz = cx / cz;
  28.                         double cyz = cy / cz;//移动方向参数
  29.                         dragon[i].speed_x = (int)(-DRAGON_SPEED * cxz);
  30.                         dragon[i].speed_y = (int)(-DRAGON_SPEED * cyz);//分配速度
  31.                 }
  32. }
复制代码
用算法赋予目标自动寻敌并且追击的结果
  1. //根据敌我位移分配速度和状态
  2. void dragon_move()
  3. {
  4.         for (int i = 1;i <= DRAGON_NUM_MAX;i++)
  5.         {
  6.                 if (dragon[i].live && dragon[i].pursuit)
  7.                 {//基本移动
  8.                         dragon[i].x += dragon[i].speed_x;
  9.                         dragon[i].y += dragon[i].speed_y;
  10.                 }
  11.                 if (dragon[i].speed_x > 0)
  12.                         dragon[i].direction = false;
  13.                 else
  14.                         dragon[i].direction = true;
  15.         }
  16. }
复制代码
敌对目标的创建
  1. void dragon_move()
  2. {
  3.         for (int i = 1;i <= DRAGON_NUM_MAX;i++)
  4.         {
  5.                 if (dragon[i].live && dragon[i].pursuit)
  6.                 {//基本移动
  7.                         dragon[i].x += dragon[i].speed_x;
  8.                         dragon[i].y += dragon[i].speed_y;
  9.                 }
  10.                 if (dragon[i].speed_x > 0)
  11.                         dragon[i].direction = false;
  12.                 else
  13.                         dragon[i].direction = true;
  14.         }
  15. }
  16. //龙的移动
  17. void draw_dragon()
  18. {
  19.         for (int i = 1;i <= DRAGON_NUM_MAX;i++)
  20.                 if (dragon[i].live)
  21.                 {
  22.                         if (dragon[i].direction)
  23.                                 transparentimage3(NULL, dragon[i].x, dragon[i].y, &dragon_imgR[dragon_img_num]);
  24.                         else
  25.                                 transparentimage3(NULL, dragon[i].x, dragon[i].y, &dragon_imgL[dragon_img_num]);
  26.                 }
  27. }
  28. //龙的绘画
  29. void Stop_the_Dragon_Crossing_Realm()//阻止龙的越界
  30. {
  31.         for (int i = 1;i <= DRAGON_NUM_MAX;i++)
  32.         {
  33.                 if (dragon[i].x <= 20)// 注意30-20要 > speed_x,防止瞬间越界
  34.                 {
  35.                         dragon[i].x = 30;
  36.                         dragon[i].speed_x = -dragon[i].speed_x;
  37.                 }
  38.                 if (dragon[i].x >= 1680)// 注意980-970要 > speed_x,防止瞬间越界
  39.                 {
  40.                         dragon[i].x = 1670;
  41.                         dragon[i].speed_x = -dragon[i].speed_x;
  42.                 }
  43.                 if (dragon[i].y <= 20)// 注意30-20要 > speed_y,防止瞬间越界
  44.                 {
  45.                         dragon[i].y = 30;
  46.                         dragon[i].speed_y = -dragon[i].speed_y;
  47.                 }
  48.                 if (dragon[i].y >= 980)// 注意1680-1670要 > speed_y,防止瞬间越界
  49.                 {
  50.                         dragon[i].y = 970;
  51.                         dragon[i].speed_y = -dragon[i].speed_y;
  52.                 }
  53.         }
  54. }
  55. //阻止龙越界
  56. void creat_dragon()
  57. {
  58.         for (int i = 1;i <= DRAGON_NUM_MAX;i++)
  59.         {
  60.                 if (dragon[i].HP <= 0 && dragon[i].live)
  61.                 {
  62.                         dragon[i].die_num_zhen = 0;
  63.                         dragon[i].live = false;
  64.                         //dragon[i].deathTime = clock(); // 更新死亡时间
  65.                 }
  66.                 if (!dragon[i].live)
  67.                 {
  68.                         if (dragon[i].die_num_zhen <= 4)//4*0.5=2s
  69.                                 continue;
  70.                         //if (clock() - dragon[i].deathTime < 2000) continue; // 5 秒内不重新生成
  71.                         dragon[i].x = 800;
  72.                         dragon[i].y = 500;
  73.                         dragon[i].live = true;
  74.                         dragon[i].HP = 100; // 重新生成时恢复血量
  75.                         break;
  76.                 }
  77.         }
  78. }
  79. //创造龙,附带空地才创造
  80. void dragon_x_dragon()//两条龙之间保持距离,避免重叠
  81. {
  82.         for (int i = 1;i <= DRAGON_NUM_MAX;i++)
  83.         {
  84.                 for (int a = 1;a <= i;a++)
  85.                 {
  86.                         if (dragon[i].x - dragon[a].x <= 200 && dragon[i].x - dragon[a].x > 0)
  87.                         {//  dragon[i]在左  <- -> dragon[i+1]在右
  88.                                 if (dragon[a].speed_x > 0)
  89.                                         dragon[a].speed_x = 0;//如果左边的在右移则水平停止
  90.                                 if (dragon[i].speed_x < 0)
  91.                                         dragon[i].speed_x = 0;
  92.                         }
  93.                         if (dragon[a].x - dragon[i].x <= 200 && dragon[a].x - dragon[i].x > 0)
  94.                         {//   dragon[i+1]在左 <- ->  dragon[i]在右
  95.                                 if (dragon[i].speed_x > 0)
  96.                                         dragon[i].speed_x = 0;
  97.                                 if (dragon[a].speed_x < 0)
  98.                                         dragon[a].speed_x = 0;
  99.                         }
  100.                 }
  101.         }
  102. }
  103. //两条龙之间保持距离,避免重叠,该函数需要放到获取所有速度之后
  104. void draw_light_effect()
  105. {
  106.         for (int i = 1;i <= 10;i++)
  107.                 if (Affected_effect[i].live)
  108.                         transparentimage3(NULL, Affected_effect[i].x, Affected_effect[i].y, &light_effect[Affected_img_num]);
  109. }
复制代码
组合的mian函数主运行块
  1. int main()
  2. {
  3.         Get_Height_And_Width(&HEIGHT, &WIDTH);//获取屏幕参数,构建全屏窗口
  4.         initgraph(WIDTH, HEIGHT);//初始化图形界面窗口
  5.         load();//加载图片
  6.         putback();//张贴背景
  7.         BeginBatchDraw();//开启双缓冲绘图
  8.         srand(time(0));//设定随机种子
  9.         while (true)
  10.         {
  11.                 putback();//背景绘画
  12.                 control_hero();//控制角色移动   (控制按键:W,A,S,D )
  13.                 Select_texture();//控制选择人物状态并绘图出人物
  14.                 timer_thing();//需要时间延迟的事件集合(内含控制按键J)
  15.                 select_dragon_speed();//赋予龙追击的能力
  16.                 Attack_detection();//受击检测
  17.                 dragon_x_dragon();//防止龙的重叠
  18.                 Stop_the_Dragon_Crossing_Realm();
  19.                 //绘画
  20.                 {
  21.                         draw_sword();//光刃的绘画
  22.                         draw_HPMP();//状态条的绘画
  23.                         draw_effect_ADD_blood();//加血特效的绘画
  24.                         draw_dragon();//绘画龙
  25.                         draw_light_effect();
  26.                 }
  27.                 //移动
  28.                 {
  29.                         move_sword();//光刃的移动
  30.                 }
  31.                 {
  32.                         creat_add_HP();//创造加血特效 (内含按键 U )
  33.                 }
  34.                 beyond_sword_boundary();//超出边界的光刃判断消失
  35.                 FlushBatchDraw();//刷新缓冲绘图
  36.                 //cleardevice();
  37.         }
  38.         EndBatchDraw();//结束缓冲绘图
  39.         exit(0);//退出程序
  40.         return 0;
  41. }
复制代码
  该游戏总代码

  1. #include <graphics.h>//图形算法库
  2. #include <conio.h>//控制台交流库
  3. #include<windows.h>//系统函数库
  4. #include<stdio.h>//标准输入输出库
  5. #include<time.h>//时间定义库
  6. #include<easyx.h>//图形界面库
  7. #include<math.h>//数学函数库
  8. #pragma comment( lib, "MSIMG32.LIB")//图形链接库
  9. //============================================================================预处理
  10. #define M_PI 3.1415926  //圆周率
  11. #define HERO_SPEED  1     //hero.移动速度
  12. #define HERO_JUMP_SPEED 10 //hero.跳跃帧高度
  13. #define HERO_JUMP_NUM  5   //hero.跳跃帧数
  14. #define LIGHT_SWORD_SPEED 3 //light_sword.光刃飞行速度
  15. #define DRAGON_NUM_MAX 2 //龙同时存在最大数量
  16. #define DRAGON_SPEED 2 //龙的移动速度
  17. //============================================================================常量宏
  18. int HEIGHT = 1000;//当前屏幕设备的高度(单位毫米)
  19. int WIDTH = 1700;//当前屏幕设备的宽度(单位毫米)
  20. IMAGE back;//背景
  21. IMAGE stop_imgR[13];//静止 右 待机动作
  22. IMAGE stop_imgL[13];//静止 左 待机动作
  23. IMAGE run_imgR[5];//奔跑 右 动作
  24. IMAGE run_imgL[5];//奔跑 左 动作
  25. IMAGE raise_sword;//举剑的动作
  26. IMAGE light_sword_imgR;//右光刃
  27. IMAGE light_sword_imgL;//左光刃
  28. IMAGE HP_img;//血量显示
  29. IMAGE MP_img;//蓝量显示
  30. IMAGE TX_ADD_HP[16]; //加血特效图
  31. IMAGE dragon_imgR[7]; //右 龙图片
  32. IMAGE dragon_imgL[7]; //左 龙图片
  33. IMAGE light_effect[31]; //受击光效图片
  34. int run_num = 1;//移动动作循环底码
  35. int stop_num = 1;//待机动作循环底码
  36. int TX_ADD_HP_num = 1;//特效图像循环底码
  37. int dragon_img_num = 1;//龙图运动循环底码
  38. int Affected_img_num = 1;//基础光刃受击特效图循环底码
  39. bool Previous_direction = true;//前一时刻方向判定量
  40. int dragon_rand_move_num[DRAGON_NUM_MAX + 1];//龙的随机运动底码
  41. int dragon_rand_pursuit_num[DRAGON_NUM_MAX + 1];//龙的随机追击底码
  42. //=============================================================================全局变量struct role {
  43.         int x = 200;                        //hero.x坐标
  44.         int y = 100;                        //hero.y坐标
  45.         int blood = 100;    //hero.血量
  46.         int blue = 100;     //hero.蓝量
  47.         bool live = true;   //hero.存活
  48.         bool ground = true; //hero.触地
  49. }hero;
  50. /*人物状态结构体*/
  51. struct sword {
  52.         int x = 0;//光刃x坐标
  53.         int y = 0;//光刃y坐标
  54.         bool live = false;//光刃存活
  55.         bool direction = true;//光刃方向
  56. };
  57. /*基本远程攻击结构体*/
  58. struct sword light_sword[11];//光刃
  59. struct Special_effects {
  60.         int x = 1; //特效.x坐标
  61.         int y = 1; //特效.y坐标
  62.         bool live = false; //是否激活
  63. };
  64. /*基本特效结构体*/
  65. struct Special_effects add_blood; //加血特效
  66. struct Special_effects Affected_effect[11];//基础光刃受击效果
  67. struct move {//基本移动体坐标
  68.         int x = 800;
  69.         int y = 500;//坐标
  70.         int HP = 100;//血量
  71.         int speed_x = 10;
  72.         int speed_y = 10;//速度
  73.         bool live = false;//是否存活
  74.         bool if_move = true; //是否能移动
  75.         bool direction = true;//向左向右
  76.         bool pursuit = true;//是否追击
  77.         int die_num_zhen = 0;//死亡后的帧数
  78. };
  79. //基本敌对目标结构体
  80. struct move dragon[DRAGON_NUM_MAX + 1]; //敌龙  同时最多存在五只
  81. //==============================================================================结构体
  82. void load()//加载图片素材
  83. {
  84.         loadimage(&back, "back.png", 1700, 1000);//背景图的加载
  85.         loadimage(&HP_img, "HP.png", 100, 50);//血条HP图片加载
  86.         loadimage(&MP_img, "MP.png", 100, 50);//蓝条MP图片加载
  87.         //loadimage(&raise_sword, "attack.png", 400, 400);//攻击举剑动作图片加载
  88.         loadimage(&light_sword_imgR, "光刃.png", 400, 400);//右光刃攻击特效图片加载
  89.         loadimage(&light_sword_imgL, "光刃f.png", 400, 400);//左光刃攻击特效图片加载
  90.         for (int i = 1;i <= 9;i++)//01.png  02.png  03.png  04........
  91.         {
  92.                 char str[50];
  93.                 sprintf_s(str, "0%d.png", i);
  94.                 loadimage(&stop_imgR[i], str, 200, 200);//加载待机动作
  95.         }
  96.         for (int x = 10;x <= 12;x++)
  97.         {
  98.                 char str2[50];
  99.                 sprintf_s(str2, "%d.png", x);
  100.                 loadimage(&stop_imgR[x], str2, 200, 200);//加载 右 待机动作
  101.         }
  102.         for (int y = 1;y <= 4;y++)
  103.         {
  104.                 char str3[50];
  105.                 char str4[50];
  106.                 sprintf_s(str3, "run%d.png", y);
  107.                 loadimage(&run_imgR[y], str3, 180, 180);//加载 右 奔跑动作
  108.                 sprintf_s(str4, "frun%d.png", y);
  109.                 loadimage(&run_imgL[y], str4, 180, 180);//加载 左 奔跑动作
  110.         }
  111.         for (int a = 1; a <= 12; a++)
  112.         {
  113.                 char str5[50];
  114.                 sprintf_s(str5, "fs%d.png", a);
  115.                 loadimage(&stop_imgL[a], str5, 200, 200);//加载 左 待机动作
  116.         }
  117.         for (int i = 1;i <= 15;i++)//加载加血特效
  118.         {
  119.                 char str6[50];
  120.                 sprintf_s(str6, "tx%d.png", i);
  121.                 loadimage(&TX_ADD_HP[i], str6, 400, 400);
  122.         }
  123.         for (int i = 1;i <= 6;i++)//加载龙的素材图
  124.         {
  125.                 char str7[50];
  126.                 sprintf_s(str7, "dg%d.png", i);
  127.                 loadimage(&dragon_imgR[i], str7, 200, 200);
  128.                 char str8[50];
  129.                 sprintf_s(str8, "dgf%d.png", i);
  130.                 loadimage(&dragon_imgL[i], str8, 200, 200);
  131.         }
  132.         for (int i = 1;i <= 30;i++)//加载受击光效
  133.         {
  134.                 char str9[50];
  135.                 sprintf_s(str9, "gx%d.png", i);
  136.                 loadimage(&light_effect[i], str9, 200, 200);
  137.         }
  138. }
  139. //加载图片素材
  140. bool timer(int ms, int id)//时间戳
  141. {
  142.         static DWORD t[500];
  143.         // 将 clock() 的返回值转换为 DWORD 类型
  144.         if (static_cast<DWORD>(clock()) - t[id] > static_cast<DWORD>(ms))
  145.         {
  146.                 t[id] = static_cast<DWORD>(clock());
  147.                 return true;
  148.         }
  149.         return false;
  150. }
  151. /*时间戳*/
  152. void Get_Height_And_Width(int* H, int* W)//获取当前屏幕的参数{        int screenWidth = *W = GetSystemMetrics(SM_CXSCREEN);        int screenHeight = *H = GetSystemMetrics(SM_CYSCREEN);}/*获取当前屏幕的参数*/
  153. void transparentimage3(IMAGE* dstimg, int x, int y, IMAGE* srcimg) //png_windows透明贴图
  154. {
  155.         HDC dstDC = GetImageHDC(dstimg);
  156.         HDC srcDC = GetImageHDC(srcimg);
  157.         int w = srcimg->getwidth();
  158.         int h = srcimg->getheight();
  159.         BLENDFUNCTION bf = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
  160.         AlphaBlend(dstDC, x, y, w, h, srcDC, 0, 0, w, h, bf);
  161. }
  162. /*windows.h 的png透明贴图工具*/void random_nums()//一帧内生成十个的随机数,前五个赋值给龙的判定移动变量,后五个给龙的追击判定变量{        int num = 10;        int used[100] = { 0 };  // 标记数组,初始化为 0        int numbers[10];        srand((unsigned int)time(NULL));  // 初始化随机数种子        for (int i = 0; i < num; i++) {                int num;                do {                        num = rand() % 100;  // 生成 0 到 RANGE - 1 之间的随机数                } while (used[num]);  // 如果该数字已被利用,则重新生成                numbers[i] = num;                used[num] = 1;  // 标记该数字已被利用        }        // 输出生成的随机数        for (int i = 1; i <= num / 2; i++) {                dragon_rand_move_num[i] = numbers[i];        }        for (int i = num / 2 + 1;i <= num;i++)        {                dragon_rand_pursuit_num[i - num / 2] = numbers[i];        }}//一帧内生成特定数目的随机数int cycle_count(int min, int max, int type)//调用返回值从min~max之间的单向循环{        static int count[10];        while (count[type] < min - 1)                count[type]++;        count[type]++;        if (count[type] > max)                count[type] = min;        return count[type];}//不同type参数分配不同的静态变量count/*可控范围的底码循环,用于运动图片的切换*/void control_hero()//控制人物移动
  163. {
  164.         if (GetAsyncKeyState('D') && hero.x < 1550)//角色右移
  165.         {
  166.                 hero.x += HERO_SPEED;
  167.                 Previous_direction = true;
  168.         }
  169.         if (GetAsyncKeyState('A') && hero.x > -5)//角色左移
  170.         {
  171.                 hero.x -= HERO_SPEED;
  172.                 Previous_direction = false;
  173.         }
  174.         if (GetAsyncKeyState('W') && hero.y > -5)//角色上移
  175.                 hero.y -= HERO_SPEED;
  176.         if (GetAsyncKeyState('S') && hero.y < 850)//角色下移
  177.                 hero.y += HERO_SPEED;
  178. }
  179. /*控制角色移动*/
  180. void creat_sword(){        if (GetAsyncKeyState('J'))        {                for (int i = 1;i <= 10;i++)                {                        if (!light_sword[i].live)                        {                                light_sword[i].live = true;                                light_sword[i].x = hero.x - 100;//光刃继续人物前坐标释放                                light_sword[i].y = hero.y - 100;                                if (Previous_direction)//是否朝右                                        light_sword[i].direction = true;                                else                                        light_sword[i].direction = false;                                break;                        }                }        }}//创造光刃void move_sword(){        for (int i = 1;i <= 10;i++)        {                if (light_sword[i].live)                {                        if (light_sword[i].direction)//是否朝右                                light_sword[i].x += LIGHT_SWORD_SPEED;                        else                                light_sword[i].x -= LIGHT_SWORD_SPEED;                }        }}//移动光刃void draw_sword(){        for (int i = 1;i <= 10;i++)                if (light_sword[i].live)                {                        if (light_sword[i].direction)                                transparentimage3(NULL, light_sword[i].x, light_sword[i].y, &light_sword_imgR);                        else                                transparentimage3(NULL, light_sword[i].x, light_sword[i].y, &light_sword_imgL);                }}//绘画光刃void draw_HPMP(){        transparentimage3(NULL, 10, 10, &HP_img);        transparentimage3(NULL, 10, 70, &MP_img);}//状态栏的构建void Select_texture()//选择使命状态并且画图{        if (GetAsyncKeyState('D'))//是否按下D        {                transparentimage3(NULL, hero.x, hero.y, &run_imgR[run_num]);        }        else {//没有按下D                if (GetAsyncKeyState('A'))//是否按下A                {                        transparentimage3(NULL, hero.x, hero.y, &run_imgL[run_num]);                }                else {//没有按下A                        if (GetAsyncKeyState('W') || GetAsyncKeyState('S'))                        {//是否按下W或S                                if (Previous_direction)//是否右朝向                                        transparentimage3(NULL, hero.x, hero.y, &run_imgR[run_num]);//右朝向上下移动                                else//左朝向                                        transparentimage3(NULL, hero.x, hero.y, &run_imgL[run_num]);//左朝向上下移动                        }                        else {//待机动作                                if (Previous_direction)//是否右朝向                                        transparentimage3(NULL, hero.x, hero.y, &stop_imgR[stop_num]);//待机右朝向                                else//左朝向                                        transparentimage3(NULL, hero.x, hero.y, &stop_imgL[stop_num]);//待机左朝向                        }                }        }}//人物动作状态的选择判定画图void putback(){        putimage(0, 0, &back);}//背景图的绘画void beyond_sword_boundary(){        for (int i = 1;i <= 10;i++)                if (light_sword[i].x<0 || light_sword[i].x>WIDTH)                        light_sword[i].live = false;}//超出边界的光刃判定消失void creat_add_HP()//创造加血特效 (内含按键 U ){//触发条件,查验按键“U" 并且 特效不存活 并且 特效已完成        if (GetAsyncKeyState('U') && !add_blood.live)                add_blood.live = true;}//创造加血特效 (内含按键 U )int control_effect_count(int min, int max, bool* live, int type)//控制特效的单次循环运行{        static int count[10] = { min - 1 };        count[type]++;        if (count[type] >= max + 1)        {                *live = false;                count[type] = min - 1;                return count[type] + 1;        }        return count[type];}控制特效的单次便利图像运行,单次便利结束后,将传入的bool类型指针变为falsevoid draw_effect_ADD_blood(){        if (add_blood.live)                transparentimage3(NULL, hero.x - 100, hero.y - 150, &TX_ADD_HP[TX_ADD_HP_num]);}//加血特效的绘画void select_dragon_speed() //根据距离分配速率{        for (int i = 1;i <= DRAGON_NUM_MAX;i++)                if (dragon[i].pursuit && dragon[i].live)                {//同时满意追击和移动和存活条件后,赋值追击速率                        double cx = (double)(dragon[i].x - hero.x);  //敌我x坐标差                        double cy = (double)(dragon[i].y - hero.y);  //敌我y坐标差                        double cz = sqrt(cx * cx + cy * cy);     //绝对距离                        if (cx == 0 && cy == 0)//防止敌我目标重合带来的除0bug                        {                                cz = 1;                        }                        double cxz = cx / cz;                        double cyz = cy / cz;//移动方向参数                        dragon[i].speed_x = (int)(-DRAGON_SPEED * cxz);                        dragon[i].speed_y = (int)(-DRAGON_SPEED * cyz);//分配速率                }}//根据敌我位移分配速度和状态
  181. void dragon_move()
  182. {
  183.         for (int i = 1;i <= DRAGON_NUM_MAX;i++)
  184.         {
  185.                 if (dragon[i].live && dragon[i].pursuit)
  186.                 {//基本移动
  187.                         dragon[i].x += dragon[i].speed_x;
  188.                         dragon[i].y += dragon[i].speed_y;
  189.                 }
  190.                 if (dragon[i].speed_x > 0)
  191.                         dragon[i].direction = false;
  192.                 else
  193.                         dragon[i].direction = true;
  194.         }
  195. }
  196. //龙的移动void draw_dragon(){        for (int i = 1;i <= DRAGON_NUM_MAX;i++)                if (dragon[i].live)                {                        if (dragon[i].direction)                                transparentimage3(NULL, dragon[i].x, dragon[i].y, &dragon_imgR[dragon_img_num]);                        else                                transparentimage3(NULL, dragon[i].x, dragon[i].y, &dragon_imgL[dragon_img_num]);                }}//龙的绘画void Stop_the_Dragon_Crossing_Realm()//克制龙的越界{        for (int i = 1;i <= DRAGON_NUM_MAX;i++)        {                if (dragon[i].x <= 20)// 注意30-20要 > speed_x,防止瞬间越界                {                        dragon[i].x = 30;                        dragon[i].speed_x = -dragon[i].speed_x;                }                if (dragon[i].x >= 1680)// 注意980-970要 > speed_x,防止瞬间越界                {                        dragon[i].x = 1670;                        dragon[i].speed_x = -dragon[i].speed_x;                }                if (dragon[i].y <= 20)// 注意30-20要 > speed_y,防止瞬间越界                {                        dragon[i].y = 30;                        dragon[i].speed_y = -dragon[i].speed_y;                }                if (dragon[i].y >= 980)// 注意1680-1670要 > speed_y,防止瞬间越界                {                        dragon[i].y = 970;                        dragon[i].speed_y = -dragon[i].speed_y;                }        }}//克制龙越界void creat_dragon(){        for (int i = 1;i <= DRAGON_NUM_MAX;i++)        {                if (dragon[i].HP <= 0 && dragon[i].live)                {                        dragon[i].die_num_zhen = 0;                        dragon[i].live = false;                        //dragon[i].deathTime = clock(); // 更新死亡时间                }                if (!dragon[i].live)                {                        if (dragon[i].die_num_zhen <= 4)//4*0.5=2s                                continue;                        //if (clock() - dragon[i].deathTime < 2000) continue; // 5 秒内不重新生成                        dragon[i].x = 800;                        dragon[i].y = 500;                        dragon[i].live = true;                        dragon[i].HP = 100; // 重新生成时恢复血量                        break;                }        }}//创造龙,附带空地才创造void dragon_x_dragon()//两条龙之间保持距离,克制重叠{        for (int i = 1;i <= DRAGON_NUM_MAX;i++)        {                for (int a = 1;a <= i;a++)                {                        if (dragon[i].x - dragon[a].x <= 200 && dragon[i].x - dragon[a].x > 0)                        {//  dragon[i]在左  <- -> dragon[i+1]在右                                 if (dragon[a].speed_x > 0)                                        dragon[a].speed_x = 0;//如果左边的在右移则水平克制                                if (dragon[i].speed_x < 0)                                        dragon[i].speed_x = 0;                        }                        if (dragon[a].x - dragon[i].x <= 200 && dragon[a].x - dragon[i].x > 0)                        {//   dragon[i+1]在左 <- ->  dragon[i]在右                                if (dragon[i].speed_x > 0)                                        dragon[i].speed_x = 0;                                if (dragon[a].speed_x < 0)                                        dragon[a].speed_x = 0;                        }                }        }}//两条龙之间保持距离,克制重叠,该函数需要放到获取所有速率之后void draw_light_effect(){        for (int i = 1;i <= 10;i++)                if (Affected_effect[i].live)                        transparentimage3(NULL, Affected_effect[i].x, Affected_effect[i].y, &light_effect[Affected_img_num]);}//对基本光刃受击特效的绘画void Attack_detection(){        for (int i = 1;i <= 10;i++)        {                int ctr = 1;                for (int a = 1;a <= DRAGON_NUM_MAX;a++)                {                        if (light_sword[i].x - dragon[a].x<200 && light_sword[i].x - dragon[a].x>-200 && light_sword[i].live)                                if (dragon[a].live)                                        if (light_sword[i].y - dragon[a].y<0 && light_sword[i].y - dragon[a].y>-200)                                        {                                                dragon[a].HP -= 20;                                                Affected_effect[i].x = dragon[a].x + 50;                                                Affected_effect[i].y = dragon[a].y + 30;                                                Affected_effect[i].live = true;                                                light_sword[i].live = false;                                                ctr = 0;                                                break;                                        }                }                if (ctr == 0)                        break;        }}//基本光刃掷中判定以及反馈//=========================================================================功能函数的构建void timer_thing()//需要时间延迟的事件集合{        if (timer(100, 1))        {//脚色待机动作速率                stop_num = cycle_count(1, 12, 1);        }        if (timer(60, 2))        {//脚色奔驰动作速率                run_num = cycle_count(1, 4, 2);        }        if (timer(50, 3))  //防止一瞬间释放过多的光刃        {                creat_sword();//控制光刃释放(控制按键:J )        }        if (timer(50, 4) && add_blood.live)//控制加血特效图片运行的延迟        {                TX_ADD_HP_num = control_effect_count(1, 15, &add_blood.live, 1);        }        if (timer(100, 5)) //控制龙的动作图片        {                dragon_img_num = cycle_count(1, 6, 3);        }        if (timer(2000, 7))        {                creat_dragon();//创造龙        }        if (timer(10, 8))        {                dragon_move();//龙的移动        }        if (timer(10, 9))        {//基础光刃攻击受击特效速率控制                for (int i = 1;i <= 10;i++)                        Affected_img_num = control_effect_count(1, 30, &Affected_effect[i].live, 2);        }        if (timer(500, 10))        {                for (int i = 1;i <= DRAGON_NUM_MAX;i++)                {                        if (!dragon[i].live)                                dragon[i].die_num_zhen++;                }        }}//需要时间延迟的事件集合,内含J按键int main()
  197. {
  198.         Get_Height_And_Width(&HEIGHT, &WIDTH);//获取屏幕参数,构建全屏窗口
  199.         initgraph(WIDTH, HEIGHT);//初始化图形界面窗口
  200.         load();//加载图片
  201.         putback();//张贴背景
  202.         BeginBatchDraw();//开启双缓冲绘图
  203.         srand(time(0));//设定随机种子
  204.         while (true)
  205.         {
  206.                 putback();//背景绘画
  207.                 control_hero();//控制角色移动   (控制按键:W,A,S,D )
  208.                 Select_texture();//控制选择人物状态并绘图出人物
  209.                 timer_thing();//需要时间延迟的事件集合(内含控制按键J)
  210.                 select_dragon_speed();//赋予龙追击的能力
  211.                 Attack_detection();//受击检测
  212.                 dragon_x_dragon();//防止龙的重叠
  213.                 Stop_the_Dragon_Crossing_Realm();
  214.                 //绘画
  215.                 {
  216.                         draw_sword();//光刃的绘画
  217.                         draw_HPMP();//状态条的绘画
  218.                         draw_effect_ADD_blood();//加血特效的绘画
  219.                         draw_dragon();//绘画龙
  220.                         draw_light_effect();
  221.                 }
  222.                 //移动
  223.                 {
  224.                         move_sword();//光刃的移动
  225.                 }
  226.                 {
  227.                         creat_add_HP();//创造加血特效 (内含按键 U )
  228.                 }
  229.                 beyond_sword_boundary();//超出边界的光刃判断消失
  230.                 FlushBatchDraw();//刷新缓冲绘图
  231.                 //cleardevice();
  232.         }
  233.         EndBatchDraw();//结束缓冲绘图
  234.         exit(0);//退出程序
  235.         return 0;
  236. }
复制代码
  游戏结果

  


 







   该游戏资源

   游戏已经被我封装好,分享到了网盘上,感情兴趣的可以实验一下。
通过网盘分享的文件:封装游戏测试.zip链接:
https://pan.baidu.com/s/1indM1boxj6QvrpsaIH_85Q?pwd=LONG
提取码: LONG

提取后利用方法:

利用文件资源管理器打开,点击Debug

点击该运行文件,

 点击全部解压缩


同样再找到该运行文件并运行

一步步操作


上述您选择安装的指定位置(一样平常息争压后的文件一个位置)
就会出现一个软件,点击运行,就可以玩了
(注意:同时打开的有一个黑框框,最小化即可,不要关掉,他会获取用户的按键操作)
(W A S D 移动 U 特效 J 攻击)(只是一个基础2D游戏框架,未添加太多功能,感兴趣的小伙伴可以按照喜好实验添加)

   本文结束....感谢观看。

  


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

用户国营

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表