我正在使用Bully的街机制作ConSumo游戏。基本上,有一个敌人摔跤手成一直线,如果相撞就会反弹玩家。当与敌方摔跤手相撞时,我似乎无法弄清楚弹跳玩家的角度。
我尝试使用(player.centerY-敌人.centerY)/(player.centerX-player.centerY)的反正切计算碰撞角度,然后增加180度以反映该角度。
double angle = Math.atan(((player.getCenterY() - enemies[i].getCenterY())/ (player.getCenterX() - enemies[i].getCenterX())));
angle = Math.toDegrees(angle);
angle += 180;
angle = Math.toRadians(angle);
player.addX(Math.cos(Angle) * strength);
plyaer.addY(-(Math.sin(angle) * strength));
我试图让玩家以相同的角度弹回(我知道这不是理想的结果,但是我至少想先抓住它,如果您可以提出更好的方法,我将不胜感激),但它仅在碰撞的一侧或两侧起作用,而另一侧似乎将玩家拉过敌人,而不是将其弹跳回来。
答案 0 :(得分:0)
也许您可以尝试考虑脉冲守恒和能量守恒的物理方法。
基本上,质量为mp
的玩家的速度为[vp; 0]
,质量为me
的敌人的速度为[ve; 0]
。因此,没有y组件,因为它们仅水平移动。现在,在发生冲突时t = t_col
,假设玩家的质心具有坐标[xp, yp]
,而敌人的质心具有坐标[xe, ye]
(您可以随时对其进行调整以确保存在如果需要,可以通过使y坐标相差更大来实现更大的弹跳效果)。
动量守恒告诉我们,碰撞后立即将两个物体的速度分别称为[Vp, Wp]
和[Ve, We]
[Vp; Wp] = [vp; 0] + (1/mp)*[I1; I2];
[Ve; We] = [ve; 0] - (1/me)*[I1; I2];
其中,通常假定冲击垂直于物体表面,可以将向量[I1; I2]
与连接两个中心的向量[xp - xe; yp - ye]
对齐。将该信息与能量守恒相结合,可以计算出所述向量的大小并找到
k = (mp*me/(mp+me)) * (vp - ve)*(xp - xe) / ((xp - xe)^2 + (yp - ye)^2);
I1 = k*(xp - xe);
I2 = k*(yp - ye);
所以基本上,在发生碰撞时,您可以输入以下信息:
[xp; yp], [vp; 0]
[xe; ye], [ve; 0]
mp
的质量和敌人me
的质量然后计算
k = (mp*me/(mp+me)) * (vp - ve)*(xp - xe) / ((xp - xe)^2 + (yp - ye)^2);
I1 = k*(xp - xe);
I2 = k*(yp - ye);
Vp = vp + (1/mp)*I1;
Wp = (1/mp)*abs(I2);
Ve = ve - (1/me)*I1;
We = (1/me)*abs(I2);
观察到我使用了abs(I2)
,它是I2
的绝对值。这是因为对于两个对象之一,碰撞后速度的y分量将为正(因此没有差异),而对于另一个对象将为负。对于负数,我们还可以添加一个事实,即物体在碰撞后可能会立即从地面反弹(因此先与物体碰撞然后与地面碰撞)。因此,我们使用反射定律,有点像镜子反射光的方式。
碰撞后,在时间t = t_col
,两个玩家的抛物线轨迹(在他们重新着陆之前)将是
xp(t) = xp + Vp * (t - t_col);
yp(t) = yp + Wp * (t - t_col) - (g/2) * (t - t_col)^2;
xe(t) = xe + Ve * (t - t_col);
ye(t) = ye + We * (t - t_col) - (g/2) * (t - t_col)^2;
如果需要角度:
cos(angle_p) = Vp / (Vp^2 + Wp^2);
sin(angle_p) = Wp / (Vp^2 + Wp^2);
cos(angle_e) = Ve / (Ve^2 + We^2);
sin(angle_e) = We / (Ve^2 + We^2);
其中angle_p
是玩家的角度,angle_e
是敌人的角度。