似乎无法获得平滑的 3D 碰撞 XNA
Can't seem to get smooth 3D collision XNA
我正在制作 3D 游戏。玩家是"camera"。我希望它不要穿过已实现的墙壁。但现在我希望它能够像在任何其他 fps 中一样沿墙 "glide"。这是代码:提前致谢:
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
float dt = (float)gameTime.ElapsedGameTime.TotalSeconds;
keyState = Keyboard.GetState();
camera.Update(gameTime);
if (keyState.IsKeyDown(Keys.W)) camera.moveVector.Z = 1;
if (keyState.IsKeyDown(Keys.S)) camera.moveVector.Z = -1;
if (keyState.IsKeyDown(Keys.A)) camera.moveVector.X = 1;
if (keyState.IsKeyDown(Keys.D)) camera.moveVector.X = -1;
if (keyState.IsKeyDown(Keys.Space)&&camera.Position.Y>=0.5f) camera.moveVector.Y = 0.5f;
if (camera.moveVector != Vector3.Zero)
{
//We don't want to make the player move faster when it is going diagonally.
camera.moveVector.Normalize();
//Now we add the smoothing factor and speed factor
camera.moveVector *= (dt * camera.cameraSpeed);
Vector3 newPosition = camera.PreviewMove(camera.moveVector);
bool moveTrue = true;
if (newPosition.X < 0 || newPosition.X > Map.mazeWidth) moveTrue = false;
if (newPosition.Z < 0 || newPosition.Z > Map.mazeHeight) moveTrue = false;
foreach (BoundingBox boxes in map.GetBoundsForCell((int)newPosition.X, (int)newPosition.Z))
{
if (boxes.Contains(newPosition) == ContainmentType.Contains)
{
moveTrue = false;
}
}
if (moveTrue) camera.Move(camera.moveVector);
base.Update(gameTime);
下面是执行移动的代码:
//Updating the look at vector
public void UpdateLookAt()
{
//Built a rotation matrix to rotate the direction we are looking
Matrix rotationMatrix = Matrix.CreateRotationX(cameraRotation.X) * Matrix.CreateRotationY(cameraRotation.Y);
// Build a look at offset vector
Vector3 lookAtOffset = Vector3.Transform(Vector3.UnitZ, rotationMatrix);
//Update our camera's look at the vector
cameraLookAt = (cameraPosition + lookAtOffset);
}
//Method to create movement and to check if it can move:)
public Vector3 PreviewMove(Vector3 amount)
{
//Create a rotation matrix to move the camera
Matrix rotate = Matrix.CreateRotationY(cameraRotation.Y);
//Create the vector for movement
Vector3 movement = new Vector3(amount.X, amount.Y, amount.Z);
movement = Vector3.Transform(movement, rotate);
// Give the value of the camera position +ze movement
return (cameraPosition+movement);
}
//Method that moves the camera when it hasnt'collided with anything
public void Move(Vector3 scale)
{
//Moveto the location
MoveTo(PreviewMove(scale), Rotation);
}
已经想到用xna给的invert方法了。但我似乎找不到正常的。而且我试图将相机平行于墙壁移动。但我无法做到这一点。欢迎任何帮助。
如果你发现一个点与边界框相交,你必须检查入口点位于六个面中的哪一个。这可以按如下方式完成:在旧相机位置和新相机位置之间构造一条线段新的:
p = (1 - t) * oldPos + t * newPos
,其中您仅使用 oldPos
和 newPos
的维度,这对于面部来说很有趣(例如,对于 left/right 面部,采用 x 坐标)。 p
是人脸的对应坐标。为每个面计算 t
并找到 t
最大的面,忽略点已经位于其后的面(即面法线和从面到点的方向的点积是消极的)。这将是您的切入点所在的面孔。然后你需要做的就是调整相关坐标(同样是 left/right 脸等的 x 坐标),使其不在范围内(例如,为右脸设置 newPos.x = boundingBox.MaxX
) .这等于点在边界框表面上的投影,相当于在发生交叉时仅使用平行于框的移动矢量分量。
顺便说一句,上面公式的解是:
t = (p - oldPos) / (newPos - oldPos)
我正在制作 3D 游戏。玩家是"camera"。我希望它不要穿过已实现的墙壁。但现在我希望它能够像在任何其他 fps 中一样沿墙 "glide"。这是代码:提前致谢:
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
float dt = (float)gameTime.ElapsedGameTime.TotalSeconds;
keyState = Keyboard.GetState();
camera.Update(gameTime);
if (keyState.IsKeyDown(Keys.W)) camera.moveVector.Z = 1;
if (keyState.IsKeyDown(Keys.S)) camera.moveVector.Z = -1;
if (keyState.IsKeyDown(Keys.A)) camera.moveVector.X = 1;
if (keyState.IsKeyDown(Keys.D)) camera.moveVector.X = -1;
if (keyState.IsKeyDown(Keys.Space)&&camera.Position.Y>=0.5f) camera.moveVector.Y = 0.5f;
if (camera.moveVector != Vector3.Zero)
{
//We don't want to make the player move faster when it is going diagonally.
camera.moveVector.Normalize();
//Now we add the smoothing factor and speed factor
camera.moveVector *= (dt * camera.cameraSpeed);
Vector3 newPosition = camera.PreviewMove(camera.moveVector);
bool moveTrue = true;
if (newPosition.X < 0 || newPosition.X > Map.mazeWidth) moveTrue = false;
if (newPosition.Z < 0 || newPosition.Z > Map.mazeHeight) moveTrue = false;
foreach (BoundingBox boxes in map.GetBoundsForCell((int)newPosition.X, (int)newPosition.Z))
{
if (boxes.Contains(newPosition) == ContainmentType.Contains)
{
moveTrue = false;
}
}
if (moveTrue) camera.Move(camera.moveVector);
base.Update(gameTime);
下面是执行移动的代码:
//Updating the look at vector
public void UpdateLookAt()
{
//Built a rotation matrix to rotate the direction we are looking
Matrix rotationMatrix = Matrix.CreateRotationX(cameraRotation.X) * Matrix.CreateRotationY(cameraRotation.Y);
// Build a look at offset vector
Vector3 lookAtOffset = Vector3.Transform(Vector3.UnitZ, rotationMatrix);
//Update our camera's look at the vector
cameraLookAt = (cameraPosition + lookAtOffset);
}
//Method to create movement and to check if it can move:)
public Vector3 PreviewMove(Vector3 amount)
{
//Create a rotation matrix to move the camera
Matrix rotate = Matrix.CreateRotationY(cameraRotation.Y);
//Create the vector for movement
Vector3 movement = new Vector3(amount.X, amount.Y, amount.Z);
movement = Vector3.Transform(movement, rotate);
// Give the value of the camera position +ze movement
return (cameraPosition+movement);
}
//Method that moves the camera when it hasnt'collided with anything
public void Move(Vector3 scale)
{
//Moveto the location
MoveTo(PreviewMove(scale), Rotation);
}
已经想到用xna给的invert方法了。但我似乎找不到正常的。而且我试图将相机平行于墙壁移动。但我无法做到这一点。欢迎任何帮助。
如果你发现一个点与边界框相交,你必须检查入口点位于六个面中的哪一个。这可以按如下方式完成:在旧相机位置和新相机位置之间构造一条线段新的:
p = (1 - t) * oldPos + t * newPos
,其中您仅使用 oldPos
和 newPos
的维度,这对于面部来说很有趣(例如,对于 left/right 面部,采用 x 坐标)。 p
是人脸的对应坐标。为每个面计算 t
并找到 t
最大的面,忽略点已经位于其后的面(即面法线和从面到点的方向的点积是消极的)。这将是您的切入点所在的面孔。然后你需要做的就是调整相关坐标(同样是 left/right 脸等的 x 坐标),使其不在范围内(例如,为右脸设置 newPos.x = boundingBox.MaxX
) .这等于点在边界框表面上的投影,相当于在发生交叉时仅使用平行于框的移动矢量分量。
顺便说一句,上面公式的解是:
t = (p - oldPos) / (newPos - oldPos)