XNA 4.0 3D Collision
Я пытался поработать над трехмерной игрой форвардера (например, Temple Run) в XNA 4.0.
Я бью немного о кирпичную стену, поэтому любая помощь будет высоко ценится!
В настоящее время я использую свой собственный метод обнаружения столкновений, который требует, чтобы размеры для каждой модели были жестко запрограммированы в методе столкновений. Я попытался использовать код от Microsoft, прямо ниже, но он всегда возвращает false:
static bool CheckForCollisions(Entity c1, Entity c2)
{
for (int i = 0; i < c1.body.Meshes.Count; i++)
{
// Check whether the bounding boxes of the two cubes intersect.
BoundingSphere c1BoundingSphere = c1.body.Meshes[i].BoundingSphere;
c1BoundingSphere.Center += c1.position;
for (int j = 0; j < c2.body.Meshes.Count; j++)
{
BoundingSphere c2BoundingSphere = c2.body.Meshes[j].BoundingSphere;
c2BoundingSphere.Center += c2.position;
if (c1BoundingSphere.Intersects(c2BoundingSphere))
{
return true;
}
}
}
return false;
}
Это было взято и изменено очень немного из класса Here My Entity следующим образом.
Мой код, который я считаю уместным, будет:
public class Entity
{
public int rowID;
public Model body;
public Vector3 position;
public float rotation = 0f;
public float rotatePerFrame = 0f;
protected internal float toRight = 0;
protected internal float toLeft = 0;
protected internal float forward = 0;
protected internal float back = 0;
protected internal float bottom = 0;
protected internal float top = 0;
public void setDimensions(float right, float left, float front, float back, float top, float bottom)
{
this.toRight = right;
this.toLeft = left;
this.forward = front;
this.back = back;
this.top = top;
this.bottom = bottom;
}
public Entity RotateEnt(Entity e,float degrees)//Psuedo-only accurate to 90 degrees.
{
float actual = MathHelper.ToDegrees(degrees);
switch ((int)actual)
{
case 0:
break;
case 90:
// float temp = e.forward;
// e.forward = e.toLeft;
// e.toLeft =e.back ;
// e.back = e.toRight;
// e.toRight = temp;
float temp = e.forward;
e.forward = e.toRight;
e.toRight = e.back;
e.back = e.toLeft;
e.toLeft = temp;
break;
case 180:
e.forward = e.back;
e.back = e.forward;
e.toRight = e.toLeft;
e.toLeft = e.toRight;
break;
default: //case: 270
e.toRight = e.forward;
e.back = e.toRight;
e.toLeft = e.back;
e.forward = e.toLeft;
break;
}
return e;
}
public bool Collides(Entity e)
{
Entity c1 = RotateEnt(this, this.rotation);
Entity c2 = RotateEnt(e, e.rotation);
float myRightest = c1.position.X + c1.toRight;
float myLeftest = c1.position.X - c1.toLeft;
float hisRightest = c2.position.X + c2.toRight;
float hisLeftest = c2.position.X - c2.toLeft;
if(Collides1D(myLeftest, myRightest, hisLeftest, hisRightest))
{
float myTop = c1.position.Y + c1.top;
float myBottom = c1.position.Y - c1.bottom;
float hisTop = c2.position.Y + c2.top;
float hisBottom = c2.position.Y - c2.bottom;
if (Collides1D(myBottom, myTop, hisBottom, hisTop))
{
float myBack = c1.position.Z - c1.forward;
float myForward = c1.position.Z + c1.back;
float hisBack = c2.position.Z - c2.forward;
float hisForward = c2.position.Z + c2.back;
if (Collides1D(myBack, myForward, hisBack, hisForward))
{
return true;
}
}
}
return false;
}
}
static bool Collides1D(float left1, float right1, float left2, float right2)
{
if (left1 >= left2 && left1 <= right2)
return true;
if (right1 >= left2 && right1 <= right2)
return true;
if (left2 >= left1 && left2 <= right1)
return true;
if (right2 >= left1 && right2 <= right1)
return true;
return false;
}
Мой собственный метод также облажался, когда я пытался вращать модели.
В идеале было бы хорошо узнать, что не так с кодом от Microsoft, чтобы я мог использовать его где угодно, не беспокоясь о жестком кодировании в измерениях объектов.
Если бы кто-нибудь мог увидеть быстрое исправление моего собственного базового метода обнаружения столкновений, это тоже было бы здорово.
Я посмотрел учебники Reimers, но я не получаю их сейчас, может быть, я слишком долго смотрел на свой собственный код...
Любую другую информацию, которую вы хотите, я могу попробовать и предоставить. Я также могу загрузить модели, если в этом проблема. Я использую модели от Maya, экспортированные как FBX. Я использую MSVS 2010. Большое спасибо!
Джек
1 ответ
Я думаю, что проблема, возможно, не в коде коллизии, а в том, как вы обновляете позицию своих сущностей. Я не вижу код обновления или MoveForward() и т. Д., Тип кода. Однако, во-первых, я думаю, вам будет гораздо проще использовать матрицу вместо набора значений с плавающей точкой для вращения. Например, вы могли бы иметь:
public class Entity
{
...
public Matrix RotationMatrix = Matrix.Identity;
public Vector3 position;
Public Entity(Vector3 FaceDirection, Vector3 UpDirection, Vector3 Position)
{
...
position = Position
RotationMatrix = Matrix.CreateWorld(Position, FaceDirection, UpDirection)
}
}
Тогда, если вы хотите повернуть, все, что вам нужно сделать, это:
public Void RotateEnt(float Degrees)
{
RotationMatrix *= Matrix.CreateFromAxisAngle(RotationMatrix.Up, MathHelper.ToRadians(Degrees));
}
И если вы сделаете все это, то вы легко сможете обновить позицию вашей организации, что, я думаю, является проблемой
public Void Update(GameTime gametime)
{
position += RotationMatrix.Forward * gametime.ElapsedRealTime.TotalMilliseconds * x; //x = some number to scale up or down velocity.
}
Если вы сделаете это, я думаю, что позиция вашей сущности будет обновлена, что должно исправить вашу проблему столкновения. Но, не зная, как вы обновляете положение своих сущностей, я просто размышляю. НТН