2013-03-12 29 views
0

我一直在研究一種太空飛船遊戲,在這種遊戲中,你需要一架着陸器並從地面起飛,然後儘可能高地飛起來,直到你崩潰。我遇到的問題是,我試圖實現的攝像頭不能將着陸器保持在中心位置,着陸器最終會變得比相機更快,然後熄滅屏幕。我不明白爲什麼,我已經嘗試了一切,使其工作。我創建了一個測試用例,我在一個簡單的程序中使用相機,其中一個精靈在四個方向上移動。這一個工作正常,但是當我在我的主遊戲上實現相機時,它無法正常工作。任何幫助,將不勝感激。XNA二維相機不會保持精靈居中

這是相機類:

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); 

如果你們需要更多的代碼,我可以上傳任何東西你們需要

回答

0

爲什麼你需要使用2D相機的翻譯?對於可以做得更簡單的事情來說,這是一種非常複雜的方式。在我看來,2D相機應該只是一個與相機視口左上角對應的矢量。然後,從任何精靈位置減去相機矢量,它將與相機一起移動。

所以你的情況,只需將相機設置矢量是在中心點減去一半的屏幕寬度和高度的:

Camera = SpriteCenter - new Vector2(GraphicsDevice.Viewport.Width/2, GraphicsDevice.Viewport.Height/2); 

對於每個繪圖調用,從實際位置減去攝像機矢量一個精靈。 在那裏,你的精靈將永遠處於中心位置。

如果您正在做一些不允許此功能的特殊功能,那麼我無法理解您的實際問題。我希望這有幫助。

0

我不同意@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); 

你可能會不得不增加一半如果看起來有點偏離,你的着陸器位置返回原點或位置。