function distance(x1, y1, x2, y2) {
var x = x1 - x2;
var y = y1 - y2;
return(Math.sqrt((x*x) + (y*y)))
};
function collisionCirc(circ1, circ2) {
var d = distance(circ1.x, circ1.y, circ2.x, circ2.y);
var r = circ1.radius + circ2.radius;
return(r > d);
};
function collisionCircPoint(circ1, circ2) {
var cx = ((circ1.x * circ2.radius) + (circ2.x * circ1.radius)) / (circ1.radius + circ2.radius);
var cy = ((circ1.y * circ2.radius) + (circ2.y * circ1.radius)) / (circ1.radius + circ2.radius);
var p = [cx, cy];
return p;
};
function angleDegrees(x1, y1, x2, y2) {
return (Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI) + 180;
};
function updateCollisions() {
var a;
var p;
Player.hitArea = new PIXI.Circle(Player.sprite.x, Player.sprite.y, 20);
MapObjects.chest.hitArea = new PIXI.Circle(MapObjects.chest.x, MapObjects.chest.y, 20);
if (collisionCirc(Player.hitArea, MapObjects.chest.hitArea)) {
a = angleDegrees(Player.sprite.x, Player.sprite.y, MapObjects.chest.x, MapObjects.chest.y);
p = collisionCircPoint(Player.hitArea, MapObjects.chest.hitArea);
Player.sprite.x = p[0];
Player.sprite.y = p[1];
};
};
我在地图上有2个精灵,每个都有一个圆圈hitArea定义。我试图做一个平稳的圆形碰撞,玩家无法通过。我想我可以将Player.sprite的坐标设置为碰撞点,但它只是将它转换为MapObjects.chest的坐标,即使碰撞点是正确的并且距离MapObject.chest的中心20像素。我做错了什么或创建碰撞需要什么更多信息,就像我可以围绕圆形对象圈出的JavaScript物理库一样?
答案 0 :(得分:1)
碰撞点位于玩家和障碍物之间。如果您将玩家移向碰撞点,您实际上是将玩家移近。例如,如果玩家与障碍物之间恰好有40像素(r1 + r2),则碰撞点位于它们之间,距离障碍物仅20 px!
如果你有多个物体,那么在发生碰撞时正确对象是很困难的。如果附近只有一个障碍物,您可以直接将玩家移离障碍物。但是,通过这种方式,玩家可能最终会陷入另一个障碍。
另一个解决方案是回到起点并尝试较小的动作,直到没有碰撞。这样你最终会做对,但这也可能很慢。
数学上正确的解决方案是计算碰撞发生前要移动的最大距离。这是通过求解以下向量方程来完成的:
# p = player position before moving
# o = obstacle position
# u = player direction (unit vector)
# d = distance to move
distance(o, p + d * u) = o.radius + p.radius
这个数学,你可以自己解决,也可以使用像Wolfram Alpha这样的工具。
求解此等式将为您提供零,一或两个可能的距离值。您可以忽略的负值,因为它们意味着玩家已经超越了障碍。如果你只获得一个值,则意味着玩家只会刷过障碍物,你也可以解除障碍物。两个值意味着碰撞发生在这些距离之间;较小的值是碰撞开始的地方,较大的值是玩家已经穿过障碍物的地方。此外,如果一个值是正值而另一个值是负值,则意味着玩家已经在障碍物内,这应该永远不会发生。
如果玩家不能快速移动,你应该对附近的所有障碍物进行此检查,然后根据最小的非阴性结果(即零或正)或更少来移动玩家。 / p>
最后,围绕一个圆形物体,你可以在碰撞后沿垂直方向(左或右,取决于玩家将经过的障碍物的哪一侧)移动玩家一点点,如果这不是& #39;引起任何新的碰撞。
还有许多其他可能的实现。
答案 1 :(得分:0)
Player.hitArea = new PIXI.Circle(Player.sprite.x, Player.sprite.y, 20);
MapObjects.chest.hitArea = new PIXI.Circle(MapObjects.chest.x, MapObjects.chest.y, 20);
if (collisionCirc(Player.hitArea, MapObjects.chest.hitArea)) {
p = collisionCircPoint(Player.hitArea, MapObjects.chest.hitArea);
a = angleDegrees(Player.sprite.x, Player.sprite.y, MapObjects.chest.x, MapObjects.chest.y);
if (Player.sprite.x - MapObjects.chest.x > 0) {
Player.sprite.x += 1;
} else if (Player.sprite.x + MapObjects.chest.x > 0) {
Player.sprite.x -= 1;
};
if (Player.sprite.y - MapObjects.chest.y > 0) {
Player.sprite.y += 1;
} else if (Player.sprite.y + MapObjects.chest.y > 0) {
Player.sprite.y -= 1;
};
};
};
我添加了它并且它实际上运行得很好,当在特定角度运行到MapObjects.chest的hitArea时,减去玩家速度稍微太快。稍后再努力。