我正在创造一个Monogame第一人称射击游戏,至少学会这样做,我遇到了一个我似乎无法弄清楚的问题。我有一个带鼠标+键盘输入的第一人称相机,以及一个可以四处移动的地板,所以基本上是一个基本的“三维世界”。
现在我想在0,10,0(或任何地方)的位置绘制一个球的3D模型,但是当我在我的相机周围移动时,球保持在原位,我的相机的中心和我一起移动。
有谁知道这些问题?我有一个相机类,并试图在游戏类中绘制我的模型。我认为这与我使用多个矩阵有关吗?
相机类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
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.
Mouse.SetPosition(Game.GraphicsDevice.Viewport.Width / 2, Game.GraphicsDevice.Viewport.Height / 2);
previousMouseState = currentMouseState;
base.Update(gameTime);
}
}
}
游戏类:
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace Game7
{
/// <summary>
/// This is the main type for your game.
/// </summary>
public class Game1 : Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Camera camera;
Floor floor;
BasicEffect effect;
Model ball;
private Matrix world = Matrix.CreateTranslation(new Vector3(0, 10, 0));
private Matrix view = Matrix.CreateLookAt(new Vector3(0, 0, 10), new Vector3(0, 0, 0), Vector3.UnitY);
private Matrix projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45), 800f / 480f, 0.1f, 100f);
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
/// <summary>
/// Allows the game to perform any initialization it needs to before starting to run.
/// This is where it can query for any required services and load any non-graphic
/// related content. Calling base.Initialize will enumerate through any components
/// and initialize them as well.
/// </summary>
protected override void Initialize()
{
// TODO: Add your initialization logic here
camera = new Camera(this, new Vector3(10f, 1f, 5f), Vector3.Zero, 5f);
Components.Add(camera);
floor = new Floor(GraphicsDevice, 40, 40);
effect = new BasicEffect(GraphicsDevice);
base.Initialize();
}
/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
ball = Content.Load<Model>("Ball DAE");
// TODO: use this.Content to load your game content here
}
/// <summary>
/// UnloadContent will be called once per game and is the place to unload
/// game-specific content.
/// </summary>
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
// TODO: Add your update logic here
base.Update(gameTime);
}
/// <summary>
/// This is called when the game should draw itself.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
// TODO: Add your drawing code here
floor.Draw(camera, effect);
DrawModel(ball, world, view, projection);
base.Draw(gameTime);
}
private void DrawModel(Model model, Matrix world, Matrix view, Matrix projection)
{
foreach (ModelMesh mesh in model.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
//effect.World = world;
effect.View = view;
effect.Projection = projection;
}
mesh.Draw();
}
}
}
}
感谢您的帮助。
哦,如果我取消注释effect.world = world,那么球根本就不会画画。
答案 0 :(得分:0)
要绘制模型,效果需要世界,视图和投影矩阵。您的代码表明您没有清楚地了解到底发生了什么。
世界是一个表示模型旋转和旋转的矩阵。相对于世界的位置。当矩阵移动或旋转时,此矩阵会发生变化。
视图是一个矩阵,表示相机相对于世界的旋转和位置(更准确地说,是世界相对于相机的位置/旋转)。该矩阵通常由相机类拥有,并且相同的视图矩阵用于绘制所有对象。
投影矩阵表示世界的出现方式。有点像相机上的镜头。该矩阵通常也由相机类拥有,并且相同的投影矩阵用于绘制所有对象。
您的游戏类具有用于绘制模型的私有世界,视图和投影矩阵。您还可以在相机类中创建一个用于绘制地板的视图和投影矩阵。你必须使用相同的视图和投射地板和球。所以你应该使用相机的视图&amp;像你在地板上一样投射球。
effect.View = camera.View;
effect.Projection = camera.Projection;