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);
如果着陆器的位置看起来有点偏离原点或位置,您可能需要将一半的着陆器位置添加回原点或位置