Answers:
我想到两个选择:
您肯定应该实现某种表面类型。想一想,如果不知道角色是撞墙还是撞梯,如何才能爬上梯子呢?您可以简单地使用OOP来使用继承来管理类型层次结构,但是我建议您使用通过枚举类型实现的“类别”:
这是一个想法:“冲突”枚举为每个类别都有一个标志。例如:
namespace Collisions
{
enum Type
{
None = 0,
Floor = 1 << 0,
Ladder = 1 << 1,
Enemy = 1 << 2,
... // And whatever else you need.
// Then, you can construct named groups of flags.
Player = Floor | Ladder | Enemy
};
}
使用此方法,您将能够测试玩家是否碰撞了您应管理的任何事物,因此您的引擎可以调用实体的“ Collided”方法:
void Player::Collided( Collisions::Type group )
{
if ( group & Collisions::Ladder )
{
// Manage Ladder Collision
}
if ( group & Collisions::Floor )
{
// Manage Floor Collision
}
if ( group & Collisions::Enemy )
{
// Manage Enemy Collision
}
}
该方法基于类别的二进制值,使用按位标志和按位“或”运算符来确保每个组具有不同的值。此方法工作良好且易于扩展,因此您可以创建海关冲突组。游戏中的每个实体(玩家,敌人等)都有一些称为“过滤器”的位,用于确定它可以与之碰撞的地方。您的冲突代码应该检查一下位是否匹配并做出相应的反应,其中一些代码可能类似于:
void PhysicEngine::OnCollision(...)
{
mPhysics.AddContact( body1, body1.GetFilter(), body2, body2.GetFilter() );
}
如果您认为角色的脚始终在角色下方一定距离,并且您没有离开表面,那么角色就在地面上。
在粗略的伪代码中:
bool isOnGround(Character& chr) { // down vector is opposite from your characters current up vector. // if you want to support wall jumps, animate the vecToFoot as appropriate. vec vecToFoot = -chr.up * chr.footDistanceFromCentre;
// if feet are moving away from any surface, can't be on the ground if (dot(chr.velocity, down) < 0.0f) return false;
// generate line from character centre to the foot position vec linePos0 = chr.position; vec linePos1 = chr.position + vecToFoot;
// test line against world. If it returns a hit surface, we're on the ground if (testLineAgainstWorld(line0, line1, &surface) return true;
return false; }
char
,甚至不要使用伪代码。