我最近在Monogame开始了一个3D第一人称射击游戏,我在相机控制方面遇到了一些问题,我无法弄清楚当我按住左边时我如何让相机慢慢打开它的X轴/右箭头键。
此时,我的代码如下:
Matrix view = Matrix.CreateLookAt(new Vector3(60, 20, 10), new Vector3(0, 0, 0), Vector3.UnitZ);
Matrix projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45), 800f / 600f, 0.1f, 100f);
然后在更新部分我有这个:
if (kb.IsKeyDown(Keys.Left))
{
view = Matrix.CreateLookAt(new Vector3(60, 20, 10), new Vector3(-2, -2, -2), Vector3.UnitZ);
}
问题是,此代码只是将相机移动到侧面然后停止。我不确定如何继续移动直到我放开钥匙?
我的整个代码将显示在下面,因为我忘了一些东西(地板顶点当前不起作用,与船相关的名称是由于我在教程中工作):
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace Game1
{
/// <summary>
/// This is the main type for your game.
/// </summary>
public class Game1 : Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Model model;
Vector3 ship1Location = new Vector3(40, 0, 0);
Vector3 ship2Location = new Vector3(20, 0, 0);
Matrix view = Matrix.CreateLookAt(new Vector3(60, 20, 10), new Vector3(0, 0, 0), Vector3.UnitZ);
Matrix projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45), 800f / 600f, 0.1f, 100f);
VertexPositionTexture[] floorVerts;
BasicEffect effect;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
floorVerts = new VertexPositionTexture[6];
floorVerts[0].Position = new Vector3(-20, -20, 0);
floorVerts[1].Position = new Vector3(-20, 20, 0);
floorVerts[2].Position = new Vector3(20, -20, 0);
floorVerts[3].Position = floorVerts[1].Position;
floorVerts[4].Position = new Vector3(20, 20, 0);
floorVerts[5].Position = floorVerts[2].Position;
effect = new BasicEffect(graphics.GraphicsDevice);
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
model = Content.Load<Model>("health2");
}
protected override void UnloadContent()
{
}
protected override void Update(GameTime gameTime)
{
// Allows the game to exit
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
Matrix ship1WorldMatrix = Matrix.CreateTranslation(ship1Location);
Matrix ship2WorldMatrix = Matrix.CreateTranslation(ship2Location);
if (IsCollision(model, ship1WorldMatrix, model, ship2WorldMatrix))
{
ship1Location = new Vector3(0, -20, 0);
}
KeyboardState kb = Keyboard.GetState();
if (kb.IsKeyDown(Keys.A))
{
ship1Location += new Vector3(-0.1f, 0, 0);
}
if (kb.IsKeyDown(Keys.Left))
{
view = Matrix.CreateLookAt(new Vector3(60, 20, 10), new Vector3(-2, -2, -2), Vector3.UnitZ);
}
ship2Location += new Vector3(0, 0, 0);
base.Update(gameTime);
}
private bool IsCollision(Model model1, Matrix world1, Model model2, Matrix world2)
{
for (int meshIndex1 = 0; meshIndex1 < model1.Meshes.Count; meshIndex1++)
{
BoundingSphere sphere1 = model1.Meshes[meshIndex1].BoundingSphere;
sphere1 = sphere1.Transform(world1);
for (int meshIndex2 = 0; meshIndex2 < model2.Meshes.Count; meshIndex2++)
{
BoundingSphere sphere2 = model2.Meshes[meshIndex2].BoundingSphere;
sphere2 = sphere2.Transform(world2);
if (sphere1.Intersects(sphere2))
return true;
}
}
return false;
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
DrawGround();
Matrix ship1WorldMatrix = Matrix.CreateTranslation(ship1Location);
Matrix ship2WorldMatrix = Matrix.CreateTranslation(ship2Location);
DrawModel(model, ship1WorldMatrix, view, projection);
DrawModel(model, ship2WorldMatrix, view, projection);
base.Draw(gameTime);
}
void DrawGround()
{
// The assignment of effect.View and effect.Projection
// are nearly identical to the code in the Model drawing code.
float aspectRatio =
graphics.PreferredBackBufferWidth / (float)graphics.PreferredBackBufferHeight;
float fieldOfView = Microsoft.Xna.Framework.MathHelper.PiOver4;
float nearClipPlane = 1;
float farClipPlane = 200;
effect.Projection = Matrix.CreatePerspectiveFieldOfView(
fieldOfView, aspectRatio, nearClipPlane, farClipPlane);
foreach (var pass in effect.CurrentTechnique.Passes)
{
pass.Apply();
graphics.GraphicsDevice.DrawUserPrimitives(
// We’ll be rendering two trinalges
PrimitiveType.TriangleList,
// The array of verts that we want to render
floorVerts,
// The offset, which is 0 since we want to start
// at the beginning of the floorVerts array
0,
// The number of triangles to draw
2);
}
}
private void DrawModel(Model model, Matrix world, Matrix view, Matrix projection)
{
foreach (ModelMesh mesh in model.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.AmbientLightColor = new Vector3(2f, 0, 0);
effect.World = world;
effect.View = view;
effect.Projection = projection;
}
mesh.Draw();
}
}
}
}
答案 0 :(得分:1)
由于相机的位置和它所看到的点是创建视图矩阵的必要参数,因此您可以简单地围绕camLookAt
旋转(思考轨道)LookAt camPosition
,如下所示:
//declare class scope variables
Vector3 camPosition = new Vector3(60, 20, 10);//your starting camera position
Vector3 camLookAt = Vector3.Zero;//your starting camera focus point (look at)
Vector2 camUp = Vector3.Up;
float camYawRate = 0.004f;//set to taste
//in the Update method
float elapsed = gameTime.ElapsedGameTime.TotalSeconds;
//later in the method...
if (kb.IsKeyDown(Keys.Left))
{
camLookAt = Vector3.Transform(camLookAt - camPosition,Matrix.CreateRotationY(-camYawRate * elapsedTime)) + camPosition;);//remove the - sign from camYawRate to rotate to the right (or vice versa)
view = Matrix.CreateLookAt(camPosition, camLookAt, camUp);
}
就是这样,试一试。添加另一个类似的块以向右旋转。