C# XNA 2D相机不能使精灵居中
我一直在做一种太空船游戏,在游戏中你带着着陆器从地面起飞,飞到你能飞到的最高点,直到你坠落。我遇到的问题是,我尝试实现的摄像头无法将着陆器保持在中心位置,着陆器最终会比摄像头更快,并离开屏幕。我不明白为什么,我已经尽了一切努力使它起作用。我创建了一个测试用例,在这个测试用例中,我在一个简单的程序中使用了摄像头,其中一个精灵向四个方向移动。这一个工作得很好,但当我在我的主游戏上安装摄像头时,它不能正常工作。任何帮助都将不胜感激 这是相机类:C# XNA 2D相机不能使精灵居中,c#,xna,2d,xna-4.0,C#,Xna,2d,Xna 4.0,我一直在做一种太空船游戏,在游戏中你带着着陆器从地面起飞,飞到你能飞到的最高点,直到你坠落。我遇到的问题是,我尝试实现的摄像头无法将着陆器保持在中心位置,着陆器最终会比摄像头更快,并离开屏幕。我不明白为什么,我已经尽了一切努力使它起作用。我创建了一个测试用例,在这个测试用例中,我在一个简单的程序中使用了摄像头,其中一个精灵向四个方向移动。这一个工作得很好,但当我在我的主游戏上安装摄像头时,它不能正常工作。任何帮助都将不胜感激 这是相机类: using System; using System.C
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
namespace WindowsGame4.Main
{
class Camera
{
public Matrix transform;
Viewport view;
Vector2 centre;
public Camera(Viewport newView)
{
view = newView;
}
public void Update(GameTime gameTime, Game1 lander, Lander _lander)
{
centre = new Vector2(_lander.Position.X + (lander.lander.Width / 2) - 455, _lander.Position.Y + (lander.lander.Height/2)-910);
transform = Matrix.CreateTranslation(new Vector3(-centre.X - _lander.Velocity.X, -centre.Y - _lander.Velocity.Y, 0));
}
}
}
这是Game1中的主要更新方法:
// Creates the handler to allow the use of the keyboard inputs
KeyboardState keyboard = Keyboard.GetState();
// Sets up the launch position to allow for scoring and height determining
startPos = 700f;
// Mainly for debug, allows for leaving the game whenever desired
if (keyboard.IsKeyDown(Keys.Escape))
{
Exit();
}
// The logic for the thruster, checks for if the space key is down and if
// the lander has any fuel remaining. If there is no fuel the thrusters
// will not work.
if (keyboard.IsKeyDown(Keys.Space) && !empty)
{
_lander.Accelerate(_thruster.GetAcceleration(), gameTime.ElapsedGameTime);
// Turns on the thruster
_thruster.Active = true;
// Tells the program that the lander has taken off, allowing the gravity to kick in
landed = false;
// Keeps track of the amount of fuel you have
if (_lander.Fuel > 0)
{
// Subtracts 1 from the fuel for every second that the 'SPACE' key is down
_lander.Fuel--;
}
else if (_lander.Fuel <= 0)
{
empty = true;
endPos = _lander.Position.Y;
}
}
if (keyboard.IsKeyUp(Keys.Space) || empty)
{
// Turns off the thruster as long as the player is not pressing 'SPACE'
_thruster.Active = false;
}
// This is the logic structure for the landing portion of the game, it sets up a
// level area in which the player can land on, which in turn then checks the Position.X value
// to see how many points to give based on their close proximity to the landing site.
// ** Could possibly add depth or different levels based on location, like landing on a mountain
// ** Or landing in the bottom of a crater
if (_lander.Position.Y >= 800)
{
landed = true;
// If you have died or Failed a mission 3 times then the game is over
if (_lander.Lives == 1)
{
currentGameState = GameState.GameOver;
}
// As long as you have a life left the game will continue
// This logic also is only applied if the player has landed on the ground
// ** Add a rotational fixer as to make the lander stand straight up as opposed to the way its oriented
// ** Upon landing
else if (_lander.Lives > 0)
{
// Sets the landers position to the current position that its landed at, thus stopping the gravity
// Resets the velocity, thus making sure it doesnt continue to fall
_lander.Position = new Vector2(_lander.Position.X, _lander.Position.Y);
_lander.Velocity = new Vector2();
// Sets up the first landing site, this particular one is the highset value landing site is almost right
// On top of the flag that is placed to indicate where to land.
// *** Will Not Use In Final Version, Will Substitue With Logic For Height And Cash Gained ***
if ((_lander.Position.X >= 600 && _lander.Position.X <= 650) || (_lander.Position.X <= 600 && _lander.Position.X >= 550))
{
// *** Will be implemented to display a "YOU HAVE FAILED THE MISSION" screen. ***
failure = false;
// This is for debugging purposes only, will change to be automatic once all functions are complete
if (keyboard.IsKeyDown(Keys.Enter))
{
// (1) -- Resets the position of the lander back to its original position and Velocity
// (2) -- Add 150 points to the score based on the location that the lander set down at
// (3) -- Continues on to the next level
_lander.Position = new Vector2(graphics.PreferredBackBufferWidth / 2, 100); // (1)
_lander.Velocity = new Vector2(); // (1)
_lander.Score += 150; // (2)
currentGameState = GameState.Level2; // (3)
}
}
// Sets up the second landing site, this particular one is the second highest value landing site that is
// A large circle surrounding the landing site above
else if ((_lander.Position.X >= 651 && _lander.Position.X <= 750 ) || (_lander.Position.X <= 549 && _lander.Position.X >= 450))
{
// *** Will be implemented to display a "YOU HAVE FAILED THE MISSION" screen. ***
failure = false;
// This is for debugging purposes only, will change to be automatic once all functions are complete
if (keyboard.IsKeyDown(Keys.Enter))
{
// (1) -- Resets the position of the lander back to its original position and Velocity
// (2) -- Add 50 points to the score based on the location that the lander set down at
// (3) -- Continues on to the next level
_lander.Position = new Vector2(graphics.PreferredBackBufferWidth / 2, 100); // (1)
_lander.Velocity = new Vector2(); // (1)
_lander.Score += 50; // (2)
currentGameState = GameState.Level2; // (3)
}
}
// Sets up the final landing site, this particular one is the failing portion of the map that is
// A large area that encompasses the rest of the map.
else if ((_lander.Position.X >= 751 && _lander.Position.X <= 850) || (_lander.Position.X <= 449 && _lander.Position.X >= 0))
{
// You get no points so it does not only need to done once, it can be done as many times as needed
// And it will not change the data
_lander.Score = 0;
// *** Will be implemented to display a "YOU HAVE FAILED THE MISSION" screen. ***
failure = true;
// This is for debugging purposes only, will change to be automatic once all functions are complete
if (keyboard.IsKeyDown(Keys.Enter))
{
// (1) -- Resets the position of the lander back to its original position and Velocity
// (2) -- Takes away one of your lives as a result of the players failure to land correctly
_lander.Position = new Vector2(graphics.PreferredBackBufferWidth / 2, 100); // (1)
_lander.Velocity = new Vector2(); // (1)
_lander.Lives--; // (2)
}
}
// This is just a loop that gives a visual representation of refueling before the next level begins.
for (double i = _lander.Fuel; i < 500; i++)
{
_lander.Fuel += .05;
}
}
}
// A very simple call to the Gravity and Lander classes that simulates gravity as long as the
// lander has not landed
else if (!landed)
{
_lander.Accelerate(_gravity.GetAcceleration(), gameTime.ElapsedGameTime);
}
// Moves the lander according to gravity calculated by the lander class
_lander.DoMovement(gameTime.ElapsedGameTime);
// Calculates the height achieved based off of starting height and ending height
height = startPos - endPos;
// This will rotate the lander when the keys are pressed down
// They will also check to make sure if it is landed or not
// If it's landed then it will not allow the lander to rotate.
if (keyboard.IsKeyDown(Keys.Left) && landed == false)
{
// (1) -- This will also change the angle of rotation for the thruster as to all for movement in
// That specific direction.
// Example: if you rotate to the left and turn on the thrusters you will starting moving
// to the left
rotation -= 0.1f;
_lander.Rotation = rotation;
_thruster.Rotation = rotation; // (1)
}
if (keyboard.IsKeyDown(Keys.Right) && landed == false)
{
// (1) -- This will also change the angle of rotation for the thruster as to all for movement in that specific direction.
// (2) -- This will also change the angle of rotation for the lander as to all for movement in that specific direction.
// Example: if you rotate to the right and turn on the thrusters you will starting moving
// to the right
rotation += 0.1f;
_lander.Rotation = rotation; // (2)
_thruster.Rotation = rotation; // (1)
}
// Calls the camera class to allow the screen to move with the player
camera.Update(gameTime, this, _lander);
//创建允许使用键盘输入的处理程序
KeyboardState键盘=keyboard.GetState();
//设置发射位置以允许计分和高度确定
startPos=700f;
//主要用于调试,允许随时离开游戏
如果(键盘.IsKeyDown(键.Escape))
{
退出();
}
//推进器的逻辑检查空格键是否按下,以及
//着陆器还有剩余的燃料。如果没有燃料,推力器将停止工作
//这是行不通的。
if(keyboard.IsKeyDown(Keys.Space)和&!empty)
{
_着陆器加速(_-pulster.GetAcceleration(),gameTime.ElapsedGameTime);
//打开推进器
_推进器。激活=真;
//告诉程序着陆器已经起飞,允许重力进入
登陆=假;
//跟踪您的燃油量
如果(_lander.Fuel>0)
{
//按下“空格”键后,每秒钟从燃油中减去1
_着陆器燃料;
}
否则,如果(_lander.Fuel=800)
{
着陆=真;
//如果你三次死亡或失败,游戏就结束了
如果(_lander.lifes==1)
{
currentGameState=GameState.GameOver;
}
//只要你还有生命,游戏就会继续
//此逻辑也仅适用于球员落地的情况
//**添加一个旋转固定器,使着陆器直立,而不是其定向方式
//**着陆时
如果(_lander.lifes>0),则为else
{
//将着陆器位置设置为其着陆的当前位置,从而停止重力
//重置速度,从而确保速度不会继续下降
_着陆器位置=新矢量2(_着陆器位置.X,_着陆器位置.Y);
_着陆器速度=新矢量2();
//设置第一个着陆点,这一个是高值着陆点,几乎正确
//在旗帜的顶部,用来指示着陆地点。
//***将不会在最终版本中使用,将用高度和获得的现金的逻辑替换***
如果(("lander.Position.X>=600&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&。然后从任何精灵位置减去相机矢量,它将随相机移动
因此,在您的情况下,只需将摄影机向量设置为中心点减去屏幕宽度和高度的一半:
Camera = SpriteCenter - new Vector2(GraphicsDevice.Viewport.Width / 2, GraphicsDevice.Viewport.Height / 2);
对于每个图形调用,从精灵的实际位置减去摄影机向量。
这样,你的精灵将永远居中
如果您正在做一些特殊的事情,但不允许此功能正常运行,那么我无法理解您的实际问题。我希望这会有所帮助。我不同意@Sarkilas,我认为使用转换将简化您的代码,而无需每次指定相机
您可以使用此代码作为位置、原点、缩放和旋转的基础
return Matrix.CreateTranslation(new Vector3(-Position, 0.0f)) *
Matrix.CreateTranslation(new Vector3(-Origin, 0.0f)) *
Matrix.CreateRotationZ(Rotation) *
Matrix.CreateScale(Zoom, Zoom, 1) *
Matrix.CreateTranslation(new Vector3(Origin, 0.0f));
问题是着陆器不是您的原点,它应该是您的位置,而原点应该是视口大小的一半,就像这样
Position = lander.Position;
Origin = new Vector2(view.Width / 2, view.Height / 2);
如果着陆器的位置看起来有点偏离原点或位置,您可能需要将一半的着陆器位置添加回原点或位置