所以,我正在重新发明轮子(并学到了很多),尝试制作一个简单的物理引擎用于我的游戏引擎。我一直在搜索互联网,尝试修复目前的问题(但不成功)。有很多相关资源可供使用,但是我找到的所有内容似乎都不能适用于我的情况。
简而言之,当两个矩形相撞时,碰撞解决方法在某些角落处无法正常运作。失败的方式根据矩形的尺寸而异。我正在寻找一种“最短重叠”类型的碰撞解决方案或另一种相当简单的解决方案(欢迎提出建议!)。下面会有更好的解释和插图。
首先,这是我的物理循环。它仅循环所有游戏实体并检查它们是否与任何其他游戏实体碰撞。虽然效率不高(n^2之类的),但现在可以使用。
这里是问题开始出现的地方。我希望实体能够被简单地“推”出目标实体,并将速度设为0。只要实体和目标都是完美的正方形,这样做就没问题。但如果实体(gif中的玩家角色)是一个矩形,那么在与目标(正方形)碰撞时,碰撞将会在最长的边(X轴)上“滑动”。如果我交换玩家的尺寸,使其变得短而宽,则同样的问题会出现在Y轴上。
简而言之,当两个矩形相撞时,碰撞解决方法在某些角落处无法正常运作。失败的方式根据矩形的尺寸而异。我正在寻找一种“最短重叠”类型的碰撞解决方案或另一种相当简单的解决方案(欢迎提出建议!)。下面会有更好的解释和插图。
首先,这是我的物理循环。它仅循环所有游戏实体并检查它们是否与任何其他游戏实体碰撞。虽然效率不高(n^2之类的),但现在可以使用。
updatePhysics: function(step) {
// Loop through entities and update positions based on velocities
for (var entityID in Vroom.entityList) {
var entity = Vroom.entityList[entityID];
if (entity.physicsEnabled) {
switch (entity.entityType) {
case VroomEntity.KINEMATIC:
entity.pos.x += entity.vel.x * step;
entity.pos.y += entity.vel.y * step;
break;
case VroomEntity.DYNAMIC:
// Dynamic stuff
break;
}
}
}
// Loop through entities and detect collisions. Resolve collisions as they are detected.
for (var entityID in Vroom.entityList) {
var entity = Vroom.entityList[entityID];
if (entity.physicsEnabled && entity.entityType !== VroomEntity.STATIC) {
for (var targetID in Vroom.entityList) {
if (targetID !== entityID) {
var target = Vroom.entityList[targetID];
if (target.physicsEnabled) {
// Check if current entity and target is colliding
if (Vroom.collideEntity(entity, target)) {
switch (entity.collisionType) {
case VroomEntity.DISPLACE:
Vroom.resolveTestTest(entity, target);
break;
}
}
}
}
}
}
}
},
这是实际碰撞检测的代码。这个代码似乎也可以正常工作。
collideEntity: function(entity, target) {
if (entity.getBottom() < target.getTop() || entity.getTop() > target.getBottom() || entity.getRight() < target.getLeft() || entity.getLeft() > target.getRight()) {
return false;
}
return true;
},
这里是问题开始出现的地方。我希望实体能够被简单地“推”出目标实体,并将速度设为0。只要实体和目标都是完美的正方形,这样做就没问题。但如果实体(gif中的玩家角色)是一个矩形,那么在与目标(正方形)碰撞时,碰撞将会在最长的边(X轴)上“滑动”。如果我交换玩家的尺寸,使其变得短而宽,则同样的问题会出现在Y轴上。
resolveTestTest: function(entity, target) {
var normalizedX = (target.getMidX() - entity.getMidX());
var normalizedY = (target.getMidY() - entity.getMidY());
var absoluteNormalizedX = Math.abs(normalizedX);
var absoluteNormalizedY = Math.abs(normalizedY);
console.log(absoluteNormalizedX, absoluteNormalizedY);
// The collision is comming from the left or right
if (absoluteNormalizedX > absoluteNormalizedY) {
if (normalizedX < 0) {
entity.pos.x = target.getRight();
} else {
entity.pos.x = target.getLeft() - entity.dim.width;
}
// Set velocity to 0
entity.vel.x = 0;
// The collision is comming from the top or bottom
} else {
if (normalizedY < 0) {
entity.pos.y = target.getBottom();
} else {
entity.pos.y = target.getTop() - entity.dim.height;
}
// Set velocity to 0
entity.vel.y = 0;
}
},
我应该如何解决这个滑动问题?我已经为此头痛了5天,如果有人能帮我指点迷津,我将不胜感激!
谢谢 :)
-- 编辑:--
如果只沿左侧或右侧移动,也会发生滑动。
-- 编辑2 工作代码:-- 请参见我的答案,其中包括一个工作示例!