作者yoll522 (522)
看板GameDesign
标题[请益] 整个游戏设计结构
时间Wed Dec 26 12:18:33 2012
各位高手好,最近我设计的游戏已经完成一小部分了
其中包含角色移动、攻击、跳跃等基本功能,
敌人也可以移动、攻击被打到也会扣血
可是我设计的结构可能太差了,因为如果怪物一次出现10只
我游戏就会开始顿顿的,我本来以为这很正常,因为数量太多
不过我想想不对,我之前玩过别人设计的直向飞行游戏,
敌人加上自身的子弹近百颗,那些子弹每次都要计算
『下一步要移动到哪里、有没有撞到东西、是否超出游戏视窗外』
可是她的游戏却不会LAG,所以一定是我的设计结构有问题
想请教一下我设计的方式有没有问题
我游戏的主回圈大概如下
while(quit!=ture){
if( SDL_PollEvent( &event ) ) //判断使用者是否有操作键盘
role.handle_input(); //去判断使用者有没有按到移动、攻击、防御、跳
//的按键
role.move(); //计算角色移动的距离,如果上面的if不成立等於不会移动
//也会判断主角是否有踩空地板导致开始下降
role.show(); //将角色相应的图片贴上,移动贴移动,攻击贴攻击
bat.action(); //敌人的移动、攻击、是否被打、贴图全部都在这函式一次完成
SDL_Flip( screen ) //更新视窗
}
其实这样还好,但如果敌人有10只,那bat.action()会修改成如下
for(int i=0 ; i<have_enemy_count ; ++i )
bat[i].action();
主要就是改成这样之後当敌人数量一多,就开始顿顿的了
因为这回圈跑的时间有稍微延迟到,造成画面更新的速度下降
我游戏现在完全没有使用任何多执行绪,
我本来想说敌人的部份改成让执行绪去跑,可是这样有一个大问题
我画面更新时有时候敌人的图片还没贴上就更新画面了,
有时候一只怪物反而会贴两次才更新画面
是否有办法说执行绪完成怪物的判断且贴一次图之後,先暂停
等到画面更新了才继续跑一次判断?
当然主程式的画面更新也要先等所有的怪物都贴好图了才更新画面,
如果还没贴好图就暂停等怪物贴好
想请教一下我整个游戏架构该怎麽设计才会更好?
谢谢
我本来想说要贴上move()、show()、action()等函式的内容
可是实在是太多太杂了@@
当然也有可能是我那些函式的内容设计的不够好才会造成延迟 @@
不好意思麻烦各位高手给点意见,谢谢
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 220.134.49.54
※ 编辑: yoll522 来自: 220.134.49.54 (12/26 12:22)
1F:推 LaPass:语言? 12/26 12:28
2F:→ yoll522:不好意思忘记说了,我是用sdl写的 12/26 12:35
3F:→ bleed1979:关於碰撞是怎麽刻的呢? 12/26 12:39
我碰撞是用矩阵的方式,主角有一个隐藏的矩阵会跟着主角移动
怪物也有怪物的矩阵,当主角攻击时会出现攻击的矩阵
如果怪物的矩阵碰到了攻击的矩阵那就算攻击到了
4F:推 BSpowerx:一般问题应该比较容易出在碰撞判断上、场景太大之类的 12/26 12:40
对吼@@ 我想到我的游戏视窗是1024*768,我现在有弄一个测试的背景是3000*900
我就直接把这3000*900整张贴上去,
然後再用一个摄影机的变数去判断角色应该要在3000*900这张背景上的哪个位置出现
有可能是因为这张图太大张的关系吗? 请问图片的大小张在贴的时候会影响效能吗?
5F:推 LaPass:如果是碰撞问题的话..... 可以切场景来判断说 12/26 12:41
6F:→ LaPass:先把物件分区,分区完後再计算碰撞 12/26 12:41
请问什麽是物件分区?
7F:推 LayerZ:"所有的子弹都要判断有没有撞到东西"? 12/26 12:50
8F:→ LayerZ:除了主角还会撞到什麽东西吗,只要计算主角那区附近的子弹 12/26 12:51
9F:→ LayerZ:就好了吧,如果有特殊的再一个一个加进去,然後两个物件在 12/26 12:52
10F:→ LayerZ:一个区域也只需计算一次 12/26 12:52
因为我看有些游戏敌方的某些子弹再跟玩家的子弹相撞後会消失,
所以我以为敌方的每颗子弹随时都在判断有没有撞到任何东西@@
11F:推 kuso0516:你在游戏中有设定延迟吗? 12/26 12:56
12F:→ kuso0516:应该说你怎麽控制游戏的FPS? 12/26 12:57
其实我现在没有设置FPS,因为我当初在学LAZY FOO到16课时
网址:
http://ppt.cc/tKgh
里面有提到用FPS的方式去移动那个圆点
可是当我学到第32课的时候:
http://ppt.cc/DJzD
里面用的却不是用FPS去控制,而是用delta timer去判断
而且这种移动方法让画面更顺,所以我就把cap the frame rate的方法全部删掉了
13F:→ azureblaze:10只就lag感觉是绘图方面的问题 12/26 13:29
14F:→ azureblaze:参考看看 i3+内显 8000子弹@60FPS 12/26 13:31
请问这是PTT的文章吗? 我刚刚GOOGLE了一下查不到关键字@@
15F:→ azureblaze:线性移动+对一个角色做圆形碰撞判定 12/26 13:31
请问意思是用圆形的矩阵来做判断吗?
可是我是用rect来做长方形的矩阵,这些会有影响到吗?
16F:→ azureblaze:建议你做做看profiling 12/26 13:32
17F:→ azureblaze:VerySleepy或是CodeAnalyst都是免费的 12/26 13:34
18F:→ azureblaze:他可以帮你看每个function花了多少时间 12/26 13:34
好的谢谢你,我会去查看看我哪个函式跑太久了
19F:推 cowbaying:我觉得问题出在bat.action() 12/26 16:06
20F:→ cowbaying:你把move show action都做个计时器看看跑一次需时多少 12/26 16:07
21F:→ cowbaying:这样比较清楚 12/26 16:07
22F:推 cowbaying:你画面更新率若是60 那麽全部的计算需要在16毫秒内完成 12/26 16:08
了解,我晚点来查查看是什麽函式卡太久,可是我游戏并没有设定画面更新率
原因跟我上面提到的一样,会不会是我对这部分的观念出错了@@
23F:推 cjcat2266:Google broadphase 12/26 16:47
谢谢你,我等等来看一下查到的资料
※ 编辑: yoll522 来自: 220.134.49.54 (12/26 17:22)
24F:→ azureblaze:10只broadphase应该没什麽帮助就是了 12/26 16:57
※ 编辑: yoll522 来自: 220.134.49.54 (12/26 17:24)
※ 编辑: yoll522 来自: 220.134.49.54 (12/26 17:25)
25F:推 azureblaze:我说的参考看看是我以前游戏的效能 12/26 18:01
26F:→ azureblaze:圆形碰撞判定是直接判断两者之间的距离 12/26 18:02
27F:→ azureblaze:方形判定没有写错理论上会快一点 12/26 18:02
28F:→ azureblaze:可是碰撞判定就算一个像素一个像素检查 12/26 18:03
29F:→ azureblaze:应该也不会到10只就不行 12/26 18:03
30F:→ azureblaze:所以你目前应该先做profile 12/26 18:04
我刚刚用内建的方法测试了一次,我的方法如下
Timer test;
test.start(); //里面会取得目前时间的变数startTicks = SDL_GetTicks();
role.show();
test.get_ticks();//这里会取得扣掉时间後的费时 SDL_GetTicks()-startTicks;
可是测出来的结果有点出乎我意料,
当只有一只怪物的时候的执行时间:
http://ppt.cc/WsRY
当有10只怪物的时候:
http://ppt.cc/L6Il
bat_action();执行出来居然只有5毫秒@@
可是不知道为什麽我人物在移动的时候就真的会有点卡卡的
没有像一只怪物的时候那麽顺
好奇怪@@
※ 编辑: yoll522 来自: 220.134.49.54 (12/26 18:30)
32F:→ kuso0516:另外你的delta time是怎麽设定的? 12/26 19:05
不好意思我网址没复制好,我已经修正了
delta time其实也没有设定什麽,
int xVel=400;
Timer delta;
delta.start()
while(1){
....
....
role.move(delta.get_ticks());
delta.start();
....
....
}
move(Uint32 deltaTicks){
x += xVel * ( deltaTicks / 1000.f );
}
这种公式可以让角色每次移动的距离都跟上一次移动的时间差而改变
可能这一次是 x += 400 * ( 50 / 1000.f );
然後下一次突然系统很顿,所以造成游戏也LAG了一下
因此变成x += 400 * ( 300 / 1000.f );
我全部就只有玩家、敌人的移动会用到这公式,其他都没有再用了@@
我原本也以为要用double-buffer,可是SDL的画面更新好像比较不一样
再贴图上去的时候画面并不会显示,她好像会先贴到某张看不到的画布
接着我用SDL_Flip( screen )更新视窗时才会一次更新画面
所以我再猜SDL应该不会用到double-buffer
※ 编辑: yoll522 来自: 220.134.49.54 (12/26 20:46)
※ 编辑: yoll522 来自: 220.134.49.54 (12/26 20:46)
34F:→ kuso0516:有试过纪录整个回圈跑一次的时间吗 还有吨的感觉 12/26 21:05
35F:→ kuso0516:是FPS太低的那种顿 还是输入会延迟的吨? 12/26 21:05
吨的感觉是像fps太低的那种,就是画面感觉会小小的跳一格跳一格的显示
然後我刚刚测试了整个回圈跑完的时间,却奇怪的数字满大的
而且我发现更奇怪的是当我站在怪物的右边数字会在2x,而这时候才会开始吨
当我再怪物的左边数字会是18左右,这时候就不会吨
站在怪物左边:
http://ppt.cc/FOJC
站在怪物右边:
http://ppt.cc/aY61
哇哩勒这是什麽奇怪的现象@@
※ 编辑: yoll522 来自: 220.134.49.54 (12/26 21:56)
36F:→ kuso0516:时间检查多一点 看看是哪边的问题 另外就算平均为25ms 12/26 23:16
37F:→ kuso0516:那你每秒也还有40FPS 应该不至於太顿才对 12/26 23:16
38F:→ kuso0516:但每秒LOOP只跑40次 反而你的输入可能会稍微有点延迟感? 12/26 23:17
的确是不会太顿,只是前面顺顺的,中间却突然顿顿的感觉有点奇怪
然後我输入延迟是没什麽感觉@@
我刚刚照你说的到处检查,结果出来了,超无言的
原来我写的函式几乎都不会吨,
真的就是我背景那张delay到了,我背景3000*900
大概就是因为一次贴太大张了才造成这种问题
难怪我之前看一本书,在教写类似枫之谷的游戏,在贴地图的时候
他游戏视窗假设800*600,地图假设8000*600这麽长
他却把它截图拆成(800*600)*10张,我还想说他干嘛没是要拆成这麽多张
直接一张贴上去不就好了@@
大概就是因为太大张的图会造成lag吧
学到了一课@@ 真的很谢谢各位的帮忙
感恩
不过我就算把地图改成跟视窗同样大小的1024*768
贴背景还是花了13、14左右
再一次感谢各位
※ 编辑: yoll522 来自: 220.134.49.54 (12/27 00:29)
39F:→ yoll522:可是还有一个无解的就是不晓得为什麽我站在怪物右边会 12/27 00:40
40F:→ yoll522:比左边顿,我可能还得查查 12/27 00:40
我查到原因了,不是什麽左边右边的关系,而是敌方角色图片的问题
我怪物的图档原本就是面向右边的,然後我利用程式翻转
这样我就有了向左、右边的图,
可是当我贴原本的向右的图案时会delay大概5、6左右
我贴用程式翻转的向左的图案反而不会delay到@@
我一开始读档的时候就没有释放过,所以应该不会是因为重复读图档的关系
请问有人知道为什麽吗?谢谢
※ 编辑: yoll522 来自: 220.134.49.54 (12/27 00:53)
41F:推 LPH66:你的向左向右的图片是否属於显示用的? 12/27 01:09
42F:→ LPH66:不属於显示用的图片在贴图时由於要多一次转换所以会变慢 12/27 01:09
感谢你,我刚刚测试了一下,我发现是因为去背的关系@@
SDL_SetColorKey( Image, SDL_SRCCOLORKEY,
SDL_MapRGB(Image->format, 0, 255, 0 ) );
我如果用了去背的功能,每次贴图的时後都会LAG
可是如果把去背拿掉,那贴图的时候非常顺畅@@
连背景图也是很顺
不过我角色不管怎样都要去背才行
可是请问为什麽去背在每次贴图的时候都会造成LAG?
谢谢你们
※ 编辑: yoll522 来自: 220.134.49.54 (12/27 07:35)
43F:→ yoll522:不然我就是在复制一次图片吧,把原本右边的图去背後 12/27 07:38
44F:→ yoll522:再复制到另外一个变数,然後把原本去背的给释放 12/27 07:39
我找到了一个函式,关键就是
SDL_SetColorKey( optimizedImage,SDL_SRCCOLORKEY|SDL_RLEACCEL,
SDL_MapRGB( optimizedImage->format, 0, 255, 0x00 ) );
在第二个引数多加一个SDL_RLEACCEL就可以告之SDL我要重复使用
这样就没问题了~
※ 编辑: yoll522 来自: 220.134.49.54 (12/27 09:39)