GameMaker Studio 2

创建于:2017-04-19

创建人: dougen

190 信息 1080 成员
游戏开发工具 GameMaker Studio 2 的讨论小组

GMS:理解碰撞基础 P1

highway★ 2018-03-08

作者:Zack bell

翻译:highway★

有问题联系我 -> zbell91@comcast.net 

或者公开提问 -> http://ask.fm/ZackBellGames

碰撞基础我几乎每天都会被问到这个问题,所以我觉得应该多花点时间聊聊它。我如何实现不同角度的斜坡和更高级的碰撞特征。说实话,我认为这是很简单的碰撞检测。但是,我明白这对很多人来说并不是很直观。好在,你一旦明白是怎么回事了,那就不会再有困惑。碰撞涉及到的概念可以很容易的扩展到可跳穿的平台、移动地形等等。

1 - 首先检测坚固平坦的块状对象。基本上,玩家应该在与地面、天花板和墙壁时停下。

Image title

vx和vy变量是player的水平和垂直速度

// 垂直碰撞

repeat(abs(vy))

{

if (!place_meeting(x, y + sign(vy), oParSolid))

y += sign(vy);

else

{

vy = 0; break;

}

}

// 水平碰撞

repeat(abs(vx))

{

if (!place_meeting(x + sign(vx), y, oParSolid))

x += sign(vx);

else

{

vx = 0;

break;

}

}

上面的代码解释一下,我们就是在循环中问下面这些问题:

  • 1   - 在我移动的方向(上/下)上是否有1个像素的碰撞?
  • 2a - 如果没有,继续向原方向移动1个像素。
  • 2b - 如果有,那重置速度(上/下),退出循环。
  • 3   - 重复1。

重复这个循环,直到一个碰撞导致你跳出循环,或者你已经在循环中迭代了"vy"次。水平移动缓和跟这个一样。


2 - 接下来我们让player上下斜坡。更具体的说,斜坡就是每个step增加player的y坐标1个像素。

Image title

粗体是我们增加的代码

// 垂直碰撞

repeat(abs(vy))

{

if (!place_meeting(x, y + sign(vy), oParSolid))

y += sign(vy);

else

{

vy = 0;break;

}

}



// 水平碰撞

repeat(abs(vx)) 

{

// 上坡

if (place_meeting(x + sign(vx), y, oParSolid) && !place_meeting(x + sign(vx), y - 1, oParSolid))

    --y;

// 下坡 

if (!place_meeting(x + sign(vx), y, oParSolid) && !place_meeting(x + sign(vx), y + 1,     oParSolid) && place_meeting(x + sign(vx), y + 2, oParSolid))

++y;

if (!place_meeting(x + sign(vx), y, oParSolid))

x += sign(vx);

else

{

vx = 0;break;

}

}

你会注意到,在垂直碰撞上没有任何变化。我写的初始循环会让player不会掉穿平台。但是,我对水平碰撞循环进行了两处修改,这些是为了实现上下斜坡。

// 上坡

1 - 你正在移动的方向上(左/右)是否存在碰撞 &&  如果player向上移动1个像素且在该方向没有碰撞 ?

2 - 如果有碰撞,靠近斜坡并将player向上推1个像素。循环的剩余部分将搞定将player在水平方向上向斜坡移动。

// 下坡

1 - 你正在移动的方向上(左/右)是否存在碰撞 && 如果player向下移动1个像素且在该方向没有碰撞 && 如果player向下移动2个像素的话在该方向产生碰撞 ?

2 - 如果满足上面的所有条件,你就可以下坡了。

第三次检测(下移)是检测你是不是站在边缘/悬崖上。如果不是,那所有的角落都会被当作是斜坡。3 -  最后,你可能想要处理更陡的斜坡。我会展示一个斜坡示例,每个step调整player的y左边2个像素。

Image title

跟之前一样,粗体是我们增加的代码

// 垂直碰撞

repeat(abs(vy))

{

if (!place_meeting(x, y + sign(vy), oParSolid))

y += sign(vy)

;else

{

vy = 0;break;

}

}


// 水平碰撞

repeat(abs(vx))

{

//上坡

if (place_meeting(x + sign(vx), y, oParSolid) && place_meeting(x + sign(vx), y - 1, oParSolid) && !place_meeting(x + sign(vx), y - 2, oParSolid))

y -= 2;

else if (place_meeting(x + sign(vx), y, oParSolid) && !place_meeting(x + sign(vx), y - 1, oParSolid))

--y;

//下坡        

if (!place_meeting(x + sign(vx), y, oParSolid) && !place_meeting(x + sign(vx), y + 1, oParSolid) && !place_meeting(x + sign(vx), y + 2, oParSolid) && place_meeting(x + sign(vx), y + 3, oParSolid))

y += 2;

else if (!place_meeting(x + sign(vx), y, oParSolid) && !place_meeting(x + sign(vx), y + 1, oParSolid) && place_meeting(x + sign(vx), y + 2, oParSolid))

++y;


if (!place_meeting(x + sign(vx), y, oParSolid))

x += sign(vx);

else

{

vx = 0;

break;

}

}

并没那么复杂,对吧~简单碰撞的关键是迭代对象的移动路径。前方是否有碰撞?如果没有,那么移动。否则,停止。


你可以试试更复杂的~ 你可能注意到了我检测2像素和1像素斜坡的方式。 你可以在内部循环中设置一个变量(比如slopeMax),并在任意陡度的斜坡上进行迭代。此外,当你上很陡的斜坡时,你可以调整player的移动速度。



thx


译注:不知道indienova这活见鬼又反人类的文字编辑工具什么时候能升级一下……代码的格式我没改,全部贴边儿,nova的编辑太麻烦了,见谅)




(转发自:原日志地址

近期喜欢的会员

 
shinobu 2020-08-22

感谢分享,正好在寻找上下坡的方案

 

加入 indienova

  • 建立个人/工作室档案
  • 建立开发中的游戏档案
  • 关注个人/工作室动态
  • 寻找合作伙伴共同开发
  • 寻求线上发行
  • 更多服务……
登录/注册