Monogame - 当我的玩家发生碰撞时,让摄像机停止
本文关键字:摄像机 碰撞 我的 玩家 Monogame | 更新日期: 2023-09-27 18:31:39
我已经在我的3D游戏中达到了一个位置,我现在正在尝试完善相机。我最终想要的是一个工作的第一人称摄像机,当它与墙壁相撞时会停止。我假设您通过让相机与模型一起移动并让模型碰撞以停止相机来做到这一点,我只是在了解如何做到这一点时遇到问题。
我让模型工作所以它停止了,我只需要锁定相机不移动。到目前为止,这是我拥有的代码,使模型停止使用 collison:
if (player_health != 0)
{
if (kb.IsKeyDown(Keys.Left))
{
player_x = player_x + 0.05f;
world_player = Matrix.CreateTranslation(new Vector3(player_x, player_y, player_z));
if (IsCollision(ball, world_player, ball, world_spike))
{
player_x = player_x - 0.05f;
world_player = Matrix.CreateTranslation(new Vector3(player_x, player_y, player_z));
player_health = 0;
}
if (IsCollision(ball, world_player, ball, world_bullet[0]))
{
player_health = 0;
}
// use this code for any standard collision
if ((IsCollision(ball, world_player, ball, world_cannon)) || (IsCollision(ball, world_player, ball, walls[0])) || (IsCollision(ball, world_player, ball, walls[1])))
{
player_x = player_x - 0.05f;
world_player = Matrix.CreateTranslation(new Vector3(player_x, player_y, player_z));
}
}
我的相机已添加到 game1 类中:
camera = new Camera(this, new Vector3(10f, 3f, 5f), Vector3.Zero, 5f);
Components.Add(camera);
还有相机类本身(我被告知这太复杂了?对于相机类来说,但更简单的不起作用):
namespace Game7
{
class Camera : GameComponent
{
private Vector3 cameraPosition;
private Vector3 cameraRotation;
private float cameraSpeed;
private Vector3 cameraLookAt;
private Vector3 mouseRotationBuffer;
private MouseState currentMouseState;
private MouseState previousMouseState;
// Properties
public Vector3 Position
{
get { return cameraPosition; }
set
{
cameraPosition = value;
UpdateLookAt();
}
}
public Vector3 Rotation
{
get { return cameraRotation; }
set
{
cameraRotation = value;
UpdateLookAt();
}
}
public Matrix Projection
{
get;
protected set;
}
public Matrix View
{
get
{
return Matrix.CreateLookAt(cameraPosition, cameraLookAt, Vector3.Up);
}
}
//Constructor
public Camera(Game game, Vector3 position, Vector3 rotation, float speed)
: base(game)
{
cameraSpeed = speed;
// projection matrix
Projection = Matrix.CreatePerspectiveFieldOfView(
MathHelper.PiOver4,
Game.GraphicsDevice.Viewport.AspectRatio,
0.05f,
1000.0f);
// set camera positiona nd rotation
MoveTo(position, rotation);
previousMouseState = Mouse.GetState();
}
// set Camera's position and rotation
private void MoveTo(Vector3 pos, Vector3 rot)
{
Position = pos;
Rotation = rot;
}
//update the look at vector
private void UpdateLookAt()
{
// build rotation matrix
Matrix rotationMatrix = Matrix.CreateRotationX(cameraRotation.X) * Matrix.CreateRotationY(cameraRotation.Y);
// Look at ofset, change of look at
Vector3 lookAtOffset = Vector3.Transform(Vector3.UnitZ, rotationMatrix);
// update our cameras look at vector
cameraLookAt = cameraPosition + lookAtOffset;
}
// Simulated movement
private Vector3 PreviewMove(Vector3 amount)
{
// Create rotate matrix
Matrix rotate = Matrix.CreateRotationY(cameraRotation.Y);
// Create a movement vector
Vector3 movement = new Vector3(amount.X, amount.Y, amount.Z);
movement = Vector3.Transform(movement, rotate);
return cameraPosition + movement;
}
// Actually move the camera
private void Move(Vector3 scale)
{
MoveTo(PreviewMove(scale), Rotation);
}
// updat method
public override void Update(GameTime gameTime)
{
// smooth mouse?
float dt = (float)gameTime.ElapsedGameTime.TotalSeconds;
currentMouseState = Mouse.GetState();
KeyboardState ks = Keyboard.GetState();
// input
Vector3 moveVector = Vector3.Zero;
if (ks.IsKeyDown(Keys.W))
moveVector.Z = 1;
if (ks.IsKeyDown(Keys.S))
moveVector.Z = -1;
if (ks.IsKeyDown(Keys.A))
moveVector.X = 1;
if (ks.IsKeyDown(Keys.D))
moveVector.X = -1;
if (moveVector != Vector3.Zero)
{
//normalize it
//so that we dont move faster diagonally
moveVector.Normalize();
// now smooth and speed
moveVector *= dt * cameraSpeed;
// move camera
Move(moveVector);
}
// Handle mouse input
float deltaX;
float deltaY;
if(currentMouseState != previousMouseState)
{
//Cache mouse location
deltaX = currentMouseState.X - (Game.GraphicsDevice.Viewport.Width / 2);
deltaY = currentMouseState.Y - (Game.GraphicsDevice.Viewport.Height / 2);
// smooth mouse ? rotation
mouseRotationBuffer.X -= 0.01f * deltaX * dt;
mouseRotationBuffer.Y -= 0.01f * deltaY * dt;
if (mouseRotationBuffer.Y < MathHelper.ToRadians(-75.0f))
mouseRotationBuffer.Y = mouseRotationBuffer.Y - (mouseRotationBuffer.Y - MathHelper.ToRadians(-75.0f));
if (mouseRotationBuffer.Y > MathHelper.ToRadians(75.0f))
mouseRotationBuffer.Y = mouseRotationBuffer.Y - (mouseRotationBuffer.Y - MathHelper.ToRadians(75.0f));
Rotation = new Vector3(-MathHelper.Clamp(mouseRotationBuffer.Y, MathHelper.ToRadians(-75.0f), MathHelper.ToRadians(75.0f)), MathHelper.WrapAngle(mouseRotationBuffer.X), 0);
deltaX = 0;
deltaY = 0;
}
// Alt + F4 to close now.
// Makes sure the mouse doesn't wander across the screen (might be a little buggy by showing the mouse)
Mouse.SetPosition(Game.GraphicsDevice.Viewport.Width / 2, Game.GraphicsDevice.Viewport.Height / 2);
previousMouseState = currentMouseState;
base.Update(gameTime);
}
}
}
相机类的预览移动部分旨在检测碰撞的地方,至少我遵循的指南是这样说的,我只是不知道如何集成它。感谢您的任何帮助或输入,即使它只是指向其他指南或资源的链接,也将不胜感激!
如果您的英雄模型(玩家)已经具有移动功能和碰撞功能,并且您希望摄像机跟随模型,那么您可以极大地简化摄像机更新。
假设在移动播放器后,播放器的新位置和/或方向以player_world
表示,只需借用存储在player_world
矩阵中的位置和方向信息即可构建每帧的视图矩阵。
//after moving player and setting its matrix accordingly:
view = Matrix.Invert(player_world);
这就是您完整的相机类更新。这将创建一个视图矩阵,该矩阵与玩家处于同一位置,面向玩家所在的相同方向。如果玩家模型因为撞墙而停止,则摄像机(视图矩阵)也会停止,因为它是从玩家的"停止"矩阵构建的。当移动和旋转与玩家相同时,无需创建用于移动和旋转摄像机的整个类。
有时,本地玩家模型原点位于玩家的脚或腹部,您希望相机位于眼睛所在的头部。如果是这样,只需应用如下内容:
//after moving player and setting its matrix accordingly:
Matrix camera_world = player_world;
camera_world *= Matrix.CreateTranslation(Vector3.Up * ??f);// set ??f to the height difference between feet and head
view = Matrix.Invert(camera_world);