论给物理物体加入寻路操作
gamemaker吧
全部回复
仅看楼主
level 13
众所周知GMS里面新增物理模块,但是很多同学发现,一个物体一旦启用了物理计算之后,原来的非物理方面的属性变量(例如speed等)就都不能正常工作。 GMS给我们的这种物理功能能够很好的计算一些东西(例如惯性、把人撞开啊等等),而且是支持矢量的碰撞笼罩(Fixture)。但是GMS中的mp寻路或者其他的寻路方式是基于direction和speed来执行的,而物理物体Obviously不能执行。那么怎么办呢?? 以下方法是喵君的方法(掌声起): ~~~~~~~~~~~~~~~~~请到水面下400米~~~~~~~~~~~~~~~~~~~~~
实际上物理方面和非物理方面并非没有交叉点,因为至少来讲物理的计算也要靠坐标(想到了什么??) 点,坐标点是非物理和物理的交界,那么既然如此,我们就需要用点来计算他的运动轨迹哈(你又想到了什么??)【喂喂喂,那边那个把鞋头子……喂喂,怎么还飞上来了??】,用点来控制移动的轨迹咱肯定优先想到的是路径(Path)。那么我们奏来捶上一个path。 ai_path=path_add(); 然后光有path没有point也不行的哈【那同学,把漫画交出来,讲到这么重点的位置居然看漫画,明天找家长!】。然后……我想想哈,啊对了,记不记得mp类函数有一个:
mp_potential_path_object(path,xg,yg,stepsize,factor,object)
先说一下参数哈,path就是你的路径的id,我们这里选用的是品种优良的ai_path,xg、yg构成目标点的坐标位置(注意最好用目标的phy_position_x或y来表示,即物理坐标),stepsize就是速度【某个勤奋好学的学生:老师,不是说速度这个东西不能在物理模式下用么?】,这个同学的提问非常好,那么我们一会再来解答这个问题,这里就先不要管了,填上一个大一点的数(5就ok)。然后这个factor字面上将就是因素,这个填4就好了【同学们:“为啥啊?”】,是酱紫,factor就是你这个寻路体每次寻路产生多少种路径,太小了太大了都很膈应,太小了,一旦找不到路此函数就会不断的计算下去,而太大了,有可能这个寻路体会绕远而显得太弱智。object是你要躲避的物体的index或者id。 那么一切就绪,我们假想一个目标叫做target,那么就这么写:
mp_potential_path_object(ai_path,target.x,target.y,5,4,o_block); Absolutely,路径有了,我们就来找路径中的点:
在这里会用到一个for循环结构。
var i,points,tar_x,tar_y; //临时采用记步变量i和点数变量
pointspoints=path_het_number(ai_path); //获取路径点数量
for(i=0,i<points-1,i+=1)
{
tar_x=path_get_point_x(ai_path,i);tar_y=path_get_point_y(ai_path,i);//获取路径点坐标}physics_apply_force(x,y,lengthdir_x(50,point_direction(x,y,target.tar_x,target.tar_y)),lengthdir_y(50,point_direction(x,y,target.tar_x,target.tar_y)));//力驱动物体移动
这就是寻路的流程,然后你带到房间里看看,里面放好o_block和target……
是不是都发现一个严重的问题就是寻路体一撞墙就会死机崩掉哈,那么如果有这个情况的话恭喜你同学们,你被我骗拉……【喂喂喂现在可崇尚节俭,再撇洋柿子可就是浪费!!】
为啥会出现这熊色样呢??其实我也不太清楚【喂喂……声音消失在西红柿的海洋中】。我初步猜测是因为mp寻路的object碰撞和物体的物理碰撞会发生冲突(mp的碰撞是逐像素判断,而物理的fixture则是矢量性判断),而且,因为mp_..._object函数的关系两者是避免碰撞的(就是干撞撞不上的),但是根据物理来讲,除非这两者是碰撞组,否则是不可能的。那么既然如此,我们就不要把这个寻路交给寻路者管理了。可是,不交给寻路体的话怎么能让他寻路呢??
一个物体没有寻路的目标就无异于是一个瞎子【To be polite,叫盲人】,盲人也会动,但是他们的移动是漫无目的的【没别的意思,只是一个不太恰当却又很贴切的比喻】,于是乎,导盲犬应运而生。既然给他双眼睛就行动不便的话,那么我们就可以把寻路的工作交给一个“导盲犬”来执行。所以我们就可以创建这么一个“导盲犬”——o_handle(名字自己爱咋起咋起,自己知道就行)。 有了这个o_handle,妈妈再也不用担心我撞墙会撞死,o_handle要保证无精灵、不开物理,然后把寻路代码移到o_handle的步事件里面,把优良的ai_path也移到o_handle的创建事件中。(注意:力学驱动的代码要保留在寻路体中,一来我是让这个寻路体去跟着导盲犬,二来你把这段代码放到一个没有执行物理操作的o_handle中是要报错的。)
这就涉及到某好学的学生问的问题,为什么要这个stepsize(实际是步进长度,mp函数是步进寻路),这里就体现出来了,因为o_handle没有物理,所以路径里面的速度、方向是可以驱动非物理的o_handle移动的,而且,这个速度要相对大一些,防止因为他的速度太慢而拖慢寻路体的移动。 好了这就是物理基本寻路的主要内容,刚才开会过程中同学们试的听说有穿墙而过的,这个弱智给我死出来!!你他喵的又忘了填碰撞事件了。代码完整如下:(o_tar是寻路的最终目标,而target是寻路体跟随的引导目标)<寻路体>
//创建事件中
var target;target=instance_create(x,y,o_handle);
//步事件中
physics_apply_force(x,y,lengthdir_x(50,point_direction(x,y,target.tar_x,target.tar_y)),0);
physics_apply_force(x,y,0,lengthdir_y(50,point_direction(x,y,target.tar_x,target.tar_y)))//两个

到一起也行;
<o_handle>
mp_potential_settings(30,10,3,false)
//创建事件中
ai_path=path_add();tar_x=0;tar_y=0;
//步事件中
mp_potential_path_object(ai_path,o_tar.phy_position_x,o_tar.phy_position_y,5,4,o_block);var points,i;points=path_get_number(ai_path)for(i=0;i<points-1;i+=1){tar_x=path_get_point_x(ai_path,i)tar_y=path_get_point_y(ai_path,i)};
2014年06月21日 06点06分 1
level 13
最近呢发现了这个卡死的原因,是因为当物理撞到障碍之后呢,会在瞬间同时产生两个方向的路径,这样,就没办法确定按那条线走,导致施加力发生了矛盾,因此崩掉
2014年06月21日 06点06分 2
level 13
之前这个方式呢,还是有很多缺陷。所以呢大家最好先不要着急拿走。挂出来的目的呢是为了和大家讨论
2014年06月21日 06点06分 3
level 13
根据最新的发现,我们正在去掉导盲犬,但是仍然不可避免的有路径冲突,看看大家有木有什么好的办法
2014年06月21日 06点06分 4
level 11
(⊙o⊙)哇涨姿势了!
2014年06月21日 07点06分 5
level 11
(⊙o⊙)哇涨姿势了!
2014年06月21日 07点06分 6
拖了两个
2014年06月21日 07点06分
回复 智_囊_小_太 :抽了-
2014年06月21日 08点06分
level 4
没接触过GMS物理引擎
能不能试试每步 while+条件 控制一下
以前GM既定路径与临时的改变(比如被击飞被挡路)我是用while+条件控制的
2014年06月23日 02点06分 7
有点没太懂,但是在物理范畴来讲呢,发生了碰撞对路径的改变就是相当频繁的,这样导致了卡滞
2014年06月23日 12点06分
意思就是如果既定路径是条上下的直线,然后 while 左边有人推我 x+=1 可以吧while写到step最后,这样先执行完每步的物理计算然后再调整位置,直到外部影响结束,然后进行下个step 因为所有改变是在每步发生,所以看上去应该是一个路径与碰撞综合运作的结果
2014年06月23日 14点06分
吧务
level 12
一直没研究物理引擎,这个要顶
2014年06月23日 03点06分 8
level 5
表述有点化简为繁的感觉[汗]
2016年12月23日 02点12分 9
level 6
然而看不懂[滑稽]
2017年01月20日 09点01分 10
level 6
神奇的最短路各种SPFA,Dijkstra等等[滑稽]
2017年02月11日 12点02分 11
1