鱼C论坛

 找回密码
 立即注册
查看: 1839|回复: 2

[技术交流] 扫盲贴 大家都来0门槛设计出自己的游戏.

[复制链接]
发表于 2022-10-8 18:23:38 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

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

x
/*

新框架设计逻辑一览:

一 球,拍,统一称为"道具",各道具使用各自的数组一一对应.

二 main之前:
1,声明(宏定义方式)图形窗口宽度和高度 gw gh
2,声明字符数组,用于存放png文件路径的文字变量: char name
3,声明消息的变量:msg
4,声明存msg中的值的变量:mousex mousey mouselb mouserb
5,声明道具数组:ball paddle
6,声明道具的控制变量数组:ballx bally ballstatu paddlex paddley paddlestatu
7,声明并定义道具数组的初始化函数: initball(); intipaddle();
8,声明并定义消息取值函数:getmsg();
9,声明并定义透明绘图函数: putPNG(int,int,IMAGE,IMAGE,int);

1,声明初始化函数:init()
2,声明并定义init();并在其中使用上述声明,完成贴图载入和相应的变量数组初始化
3,声明并定义update();每次循环中使用putPNG更新画面贴图位置
4,声明用户输入input();

main之前的声明和变量的2点动态原理:
  1) 消息取值函数getmsg() 依赖全局(全局高于main函数体)来接受msg
     其中使用了"无阻塞取得消息函数": peekmessage()
     peekmessage的参数只有1个,且按引用入参: &msg
     并赋值给4个变量:mousex mousey mouselb mouserb
     分别是:分别存放鼠标x轴,y轴,左键按下,右键按下的值
  2) input(),其中将使用4个变量: mousex mousey mouselb mouserb
     取得的4个鼠标的值来操作paddle的位置,进而影响ball的位置
     每次循环只响应1次鼠标的取值以保持输入一致进而在input()中
     实现的所有"动作函数"都能有一个"统一的数值基准点"
     动作函数可以自由定义如下:
     a.全屏色差判断,使用getpexle(x,y)来实现是否碰到
     b.局部点重全判断,使用 右边:x+getwidth >= 右边:x 来检测是否碰到等
     c.按实际事物来编写碰撞,碰撞检测是程序的核心

三 main之中:
1,init()初始化绘图窗,初始化一切道具
2,while( getmsg() )消息变量赋值,同时返回0可让while退出
3,input()用来执行上行getmsg()中检索到的4项鼠标值
4,使用绘图缓冲区: BigenBatchDraw() 写入图形但并不贴图到屏幕
5,update中使用 putPNG 来绘图放置到绘冲区间,实现每次循环绘制1张全新的图片
  update中的道具位置,依赖于input()中获得的4项变量的变化,而发生变化
6,可以增加变量在绘图区间设置if分支,实现分支设计,重新开始,过关等:
7,完成用户输入后,更新(缓冲区的)贴图,直到执行EndBatchDraw(),把缓冲写到画面
  下面是while中的顺序:

  //获得消息,可退出(暂停并调用菜单再询问是否退出)且得到鼠标的4个值
  while( getmsg() )

  //先按init()中的排列,更新一次,若无输入,保持init()的画面不动
  if( 有生命 )
  BigenBatchDraw();
  update();   //更新一次,依靠鼠标的4个值,直接和间接操作(影响)道具
  EndBatchDraw();
  sleep(10);  //休眠10毫秒让windows处理其它的事

  //使用鼠标的4个值,input()中应当包括所有的动作函数如:按左键跳起等等
  input();


  //动作函数中,还应当包括: 检查生命值和关卡是否通关
  if 挂了
  生命--
  重新开始    //restart();分两种:一是重新画,一是记录残局画出来
  else
  结束        //无命可用,通关(失败画面) lost();

  if 过关
  关卡++
  重新开始   //restart();按关卡值设定不同画面或显示要素
  else
  结束       //无关可过,通关(成功画面) success();

//以上,个人觉得,只要会打出hello world的坛友且能来鱼C里,就能看懂吧?
//应当看得懂吧?若开始看不懂,可以按下面的做,跑起来后,断点之,再看即可.
//实在不行,就发贴吧.应当是其它懂的坛友,一句话就能解决的事.
//业务简介完毕
//-------------------------------------------------------------
//
送给所有和自己一样的初学者

写在前面的话:

    基于编程学习的枯燥,除基础知识外,需要人为地设置"乐趣",来实现人的
自激行为,可以促使在实现的过程中,不得不去查资料,从而提升对编程的认识
深度,这个过程既能减少学习的难度,又能增加学习的兴趣,套用一位老朋友的
话说:无论学多学少,只要兴趣还在,就好.

    原本,这是一个没有做完的系列教程,叫: "从中场入门C++"还未来得及从
"轻重缓急"上整理,也有可能会对初学朋友造成"揠苗助长"的副作用,但我觉想,
既然能来到鱼C,就一定是很有编程爱好的朋友,至少和自己一样吧,所以还是有
信心把原本简单的道理,也通过此篇实例,讲的简单化,大众化,容易接受化.

    原本想把此做成系列教程发到CSDN的,后来发现CSDN越来越不用心做事,
越来越"广告化",所以,我想,即使发到CSDN上,所产生的社会效果也不会很大,因
为本人就是一个不愿意为了下载某个要用的东西而去不择手段的"充值再充值"大
搞拿来主义.有用的东西固然有价值,但作为初学者,我想,还是应该更多地去追求
所以然,至少要知道个大概,至少这个方向不会是错误的.

    看到了鱼C大佬点赞了,受到感动是其一,其二是前几次的版主的回复,也让我
感到的论坛的活力,所以就把这些不是技术的技术送绘坛里吧.也算是自己没有充
鱼币买会员,作为为论坛尽一点绵力,尽一点人事.

    为方便大家的讨论,现将自己理解的一些编程技术,借着这个"新框架""放上来,
有更多的坛友能加入到"对像化"的认识中来,从而讯速提高自己对C++的认识,还能
保持学习的兴趣就是本人的初衷.

本程序的使用前提有四条: (不改,只能如标题写字,测试一下看能不能跑起来的-_-:))
一:
安装包:
code block 17.12_with_MinGW_gcc4.9.2(tdm-1)
(官网下载历史版本即可,若下不到,可发贴索要,我再发网盘)

二:
头文件和库文件:
easyx.h
graphics.h (随easyx.h同时发布的版本才行)
libeasyx.a

3个文件很小,安装好code block后:

2个头文件easyx.h和graphics.h放到这里:
C:\Program Files\CodeBlocks\MinGW\include

1个库文件libeasyx.a放到这里:
C:\Program Files\CodeBlocks\MinGW\lib

三:
素材:
1个球(本体白色),1个遮罩球,两者构成透明绘图的效果,需要先放置遮罩到内存,再放
置本体图形,2者必须同像素大小即可实现完美显示.

1个球拍(本体灰+红),1个球拍遮罩,同上

四:
创建好控制台hell world惯例程序后,执行一次,输出hello world到dos窗口.
然后,找到自己的"工程目录",拿自己的控制台工程目录所示:
F:\e0
是我的"工程目录"路径.
里面会有2个目录:bin obj此暂不用管它,还有4个文件: xxx是你自己的命名:
xxx.project file
xxx.depend
xxx.layout
main.cpp  (若不改,默认的话就是这个文件名)
此时,应代表hello world执行成功一次了.

然后,为了能正常使用拷入到include和lib中的easyX头和库,要设置如下:
找到以下标签:
Project -> Project options -> Linker settings点开
看向左边的Debug和Release,先点开Debug,再看向右边的"Other linker options"
空框,里面写入-leasyx后,点击OK,此时已设置好easyX在Debug运行中的链接器.
再重复一次上面的动作,设置Release,OK即可.

    本着简洁好懂和抛砖引玉的想法,避免在开头就折腾不清设置,折腾不清画面等
问题,特别地讲一下上述素材,4张素材一并和头,库文件上传到附件,见目录res中的
4个图片.搞清楚了本例后,相信大家就有能力开发更新的框架和绘出更犀利的原创素
材,来把自己的游戏做到尽善尽美了.到时候别忘了来坛里交流一下,共同提高.

    现在把res目录复制到 F:\e0中即可复制以下的代码,跑起来.
若还有什么意外的情况,请跟贴留言,我尽量解答

2022.10.7 howzyao

*/


再上源码:

  1. #include <graphics.h> //easyX版graphics.h (使用了mfc)
  2. #include <conio.h>   //使用kbhit
  3. #include <stdio.h>  //使用sprintf

  4. //图形窗口宽度和高度
  5. #define gw 640
  6. #define gh 480

  7. //加载png文件路径的文字变量
  8. #define namen 64
  9. char name[namen];

  10. //消息取值,以便一次循环下来,使用统一的值(直接使用消息太快,会导至道具失控)
  11. ExMessage msg;
  12. int mousex;
  13. int mousey;
  14. int mouselb;
  15. int mouserb;

  16. //球个数,球,球遮罩(为实现边界透明),坐标,状态,初始化
  17. //能出现在图形窗中可控地显示的最大球数 balln个
  18. //为了兼容putPNG,只好设为数组,当前仅普通球,fireball绘图中...
  19. #define balln 16
  20. IMAGE ball[1];
  21. IMAGE ballmask[1];
  22. int   ballx[balln];
  23. int   bally[balln];
  24. int   ballstatu[balln];
  25. void initball()
  26. {
  27.     sprintf(name,"F:/e0/res/ball000.png");
  28.     loadimage(&ball[0],name);
  29.     sprintf(name,"F:/e0/res/ball001.png");
  30.     loadimage(&ballmask[0],name);

  31.     for(int i=0;i<balln;i++)
  32.     {
  33.         ballx[i]=0;
  34.         bally[i]=0;
  35.         ballstatu[i]=0;
  36.     }
  37. }

  38. //拍个数,拍,拍遮罩(为实现边界透明),坐标,状态,初始化
  39. #define paddlen 1
  40. IMAGE paddle[paddlen];
  41. IMAGE paddlemask[paddlen];
  42. int   paddlex[paddlen];
  43. int   paddley[paddlen];
  44. int   paddlestatu[paddlen]; //若有几个拍时,只能其中一个为1,其它为0
  45. void initpaddle()
  46. {
  47.     for(int i=0;i<paddlen;i++)
  48.     {
  49.         sprintf(name,"F:/e0/res/paddle00%d.png",i);
  50.         loadimage(&paddle[i],name);
  51.         sprintf(name,"F:/e0/res/paddle00%d.png",i);
  52.         loadimage(&paddlemask[i],name);
  53.         paddlex[i]=0;
  54.         paddley[i]=0;
  55.         paddlestatu[i]=0;
  56.     }
  57. }

  58. //道具摆放函数,实现透明无边界:先放道具遮罩,再放道具实体
  59. void putPNG(int x,int y,IMAGE *mask,IMAGE *actor,int I)
  60. {
  61.     putimage(x,y,&mask[I],SRCAND);
  62.     putimage(x,y,&actor[I],SRCPAINT);
  63. }

  64. //消息赋值和退出 (无论用户有没有输入,msg都有消息 getch退出用途除外)
  65. int getmsg()
  66. {
  67.     peekmessage(&msg);
  68.     mousex = msg.x;
  69.     mousey = msg.y;
  70.     mouselb = msg.lbutton;
  71.     mouserb = msg.rbutton;
  72.     flushmessage();
  73.     FlushMouseMsgBuffer();

  74.     if(kbhit())
  75.     {
  76.         switch (getch())
  77.         {
  78.         case 27:
  79.             return 0;
  80.         }
  81.     }
  82.     return 1;
  83. }

  84. //初始化图形窗口 所有道具初始化函数放这里集中管理
  85. void init()
  86. {
  87.     initgraph(gw,gh);

  88.     HWND hwnd;
  89.     hwnd = GetHWnd();
  90.     SetWindowText(hwnd,"e0  新版架构(慢移鼠标左键按下可写字)    esc退出");

  91.     //初始化球
  92.     initball();

  93.     putPNG(100,100,ballmask,ball,0); //一个球出现在画面

  94.     ballstatu[0]=1; //状态==1

  95.     //初始化拍
  96.     initpaddle();

  97.     putPNG(getmaxx()/2 - paddle[0].getwidth()/2, //一个拍出现在画面
  98.            getmaxy() - paddle[0].getheight()-5,
  99.            paddlemask,paddle,0);

  100.     paddlestatu[0]=1; //状态==1

  101.     //初始其它道具
  102.     //...
  103. }

  104. //集中管理道具,因为每次绘图,需要最低时间复杂度,采用单次遍历
  105. void update()
  106. {
  107.     //测试: 更新球xy座标 测试,仅能写字,写字是动作,应当放入input()中
  108.     for(int i=0;i<balln;i++)
  109.     {
  110.         if(ballstatu[i]==1 && mouselb)
  111.         {
  112.             putPNG(mousex-ball[i].getwidth()/2,
  113.                    mousey-ball[i].getheight()/2,ballmask,ball,i);
  114.         }
  115.     }

  116.     //更新拍x座标
  117.     //...

  118.     //更新其它道具x,y坐标
  119.     //...
  120. }

  121. //用户输入需要根据消息变量实现,不能失控
  122. void input()
  123. {
  124.     //mousex;mousey,mouselb,mouserb; 4项值的利用
  125. }

  126. //结束画面,并关闭init中的图形窗口,以免退出后,内仍被存占用
  127. void ended()
  128. {
  129.     cleardevice();
  130.     sprintf(name,"已退出 按任意键关闭窗口");
  131.     outtextxy(getmaxx()/2 - textwidth(name)/2,
  132.               getmaxy()/2 - textheight(name)/2,
  133.               name);
  134.     getch();
  135.     closegraph();
  136.     delete name;
  137. }

  138. int main()
  139. {
  140.     init();

  141.     while( getmsg() )
  142.     {
  143.         input();

  144.         BeginBatchDraw();

  145.         update();

  146.         EndBatchDraw();

  147.         Sleep(5);
  148.     }

  149.     ended();

  150.     return 0;
  151. }
复制代码


再上必要的附件:

必要的附件.zip (46.13 KB, 下载次数: 1)


最后,希望贴子不要沉,大家都来0门槛设计出自己的游戏.
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2022-10-8 18:24:33 | 显示全部楼层
索性补上设置图示:

sshot1.png


sshot2.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-10-8 21:56:45 | 显示全部楼层
本帖最后由 howzyao 于 2022-10-8 21:58 编辑

刚测试win8.1 x64下的运行,需要让windows自动释放而不能使用closegraph()
否则报错.
64位下,使用最新版code block时,去这里下载附件,附件内有使用说明.
https://fishc.com.cn/thread-218941-1-1.html
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-5-4 02:38

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表