Javascript 碰撞检测&x27;不要让物体传送起来
已解决,有关最终算法,请参见文章底部 背景:我正在使用JS和HTML画布元素开发2D平台。关卡地图是基于平铺的,但玩家不会被夹在平铺上。我正在使用中概述的碰撞检测算法。除了一个边缘情况(或“壁架”情况)外,它基本上可以工作 问题: 球员摔倒了,也向右移动,撞到了墙上。当它落下时,它会传送到壁架的高度。相反,玩家应该在不进行远程传送的情况下正常下落 有没有办法改变算法来防止这种行为?如果不是,你能建议一种替代的碰撞检测算法吗?理想情况下,任何修正都不会假设玩家总是摔倒,因为在游戏中,玩家的摔倒方向在上/下/左/右之间切换 算法:Javascript 碰撞检测&x27;不要让物体传送起来,javascript,algorithm,2d,collision-detection,game-physics,Javascript,Algorithm,2d,Collision Detection,Game Physics,已解决,有关最终算法,请参见文章底部 背景:我正在使用JS和HTML画布元素开发2D平台。关卡地图是基于平铺的,但玩家不会被夹在平铺上。我正在使用中概述的碰撞检测算法。除了一个边缘情况(或“壁架”情况)外,它基本上可以工作 问题: 球员摔倒了,也向右移动,撞到了墙上。当它落下时,它会传送到壁架的高度。相反,玩家应该在不进行远程传送的情况下正常下落 有没有办法改变算法来防止这种行为?如果不是,你能建议一种替代的碰撞检测算法吗?理想情况下,任何修正都不会假设玩家总是摔倒,因为在游戏中,玩家的摔倒方
getBorderTiles
的函数获取一个对象(玩家)并返回与玩家的4个角中的每一个相接触的tiles。由于玩家的大小不超过一块瓷砖,因此这些边界瓷砖必然是玩家触摸的唯一瓷砖。请注意,其中一些瓷砖可能是相同的。例如,如果玩家仅占用一列,左上/右上分幅将与左下/右下分幅相同。如果发生这种情况,getBorderTiles
仍然返回所有四个tile,但其中一些将是相同的var borderTiles=getBorderTiles(object),//如果一个tile不在该级别内,则返回0(一个falsy值)
tileTL=borderTiles.topLeft,
tileTR=borderTiles.topRight,
tileBL=borderTiles.bottomLeft,
tileBR=borderTiles.bottomRight,
coordsBR=getTopleftxyCoordinationFTile(tileBR),//(x,y)坐标指的是tile的左上角
xRight=coordsBR.x,//x的右分幅(用于调整对象的位置,因为它落在4个分幅的中间)
yBottom=coordsBR.y,//y底部瓷砖(用于调整对象的位置,因为它落在4块瓷砖的中间)
typeTL=tileTL?level.map[tileTL.row][tileTL.col]:-1,//如果tileTL在该级别中,则获取其类型,否则为-1
typeTR=tileTR?level.map[tileTR.row][tileTR.col]:-1,
typeBL=tileBL?level.map[tileBL.row][tileBL.col]:-1,
typeBR=tileBR?level.map[tileBR.row][tileBR.col]:-1,
CollizeSTL=typeTL==TILETYPE.SOLID,//如果平铺为实心,则为true
collidesTR=typeTR==TILETYPE.SOLID,
collidesBL=typeBL==TILETYPE.SOLID,
collizesbr=typeBR==TILETYPE.SOLID,
collide sup=false,
CollipsDown=false,
collipsleft=false,
碰撞右=假;
//上下
如果(object.vy<0&((collidesTL&&!collidesBL)| |(collidesTR&&!collidesBR))){
collide sup=true;
/*对象被推出底行,因此底行现在是顶行。更改碰撞__
变量,因为这会影响碰撞测试,但无需更改平铺变量*/
collidesTL=collidesBL;
collizestr=collizesbr;
}如果(object.vy>0&((collidesBL&&!collidesTL)| |(collidesBR&&!collidesTR)),则为else{
CollipsDown=真;
/*对象被推出底行,因此底行现在是顶行。更改碰撞__
变量,因为这会影响碰撞测试,但无需更改平铺变量*/
collidesBL=collidesTL;
collizesbr=collizestr;
}
//左右
如果(object.vx<0&((collidesTL&&!collidesTR)| |(collidesBL&&!collidesBR))){
collizesleft=true;
}否则如果(obj
sizes: sTile = 50, sPlayer = 20
old position (fine, top-left corner): oX = 27, oY = 35
speeds: vX = 7, vY = 10
new position: x = oX + vX = 34, y = oY + vY = 45 => (34, 45)
solid: tile at (50, 50)
1.1. Checking x-direction, relevant points for positive vX are the ones to the right:
(54, 45) and (54, 65). The latter gives a conflict and we need to correct the
position to p1 = (30, 45) and speed v1 = (0, 10).
2.1. Checking y-direction based on previous position, relevant points: (30, 65) and
(50, 65). There is no conflict, p1 and v1 remain unchanged.
3.1. There was a conflict in step 1.1. so we cannot return the current result
immediately and have to calculate the distance d1 = 4 + 0 = 4.
1.2. Checking y-direction first this time, relevant points: (34, 65) and (54, 65).
Because the latter gives a conflict we calculate p2 = (34, 30) and v2 = (7, 0).
2.2. Checking x-direction based on step 1.2., relevant points: (54, 30) and (54, 50).
There is no conflict, p2 and v2 remain unchanged.
3.2. Because there was a conflict in step 1.2. we calculate the distance d2 = 15.
5. Change position and speed to p1 and v1 because d1 is smaller than d2.