我一直在研究一种太空飞船游戏,你可以在这种游戏中使用着陆器并从地面起飞,然后尽可能高地飞起来直到你崩溃。我遇到的问题是我试图实现的相机没有将着陆器保持在中心,着陆器最终比相机更快,然后离开屏幕。我不明白为什么,我已经尝试了一切让它发挥作用。我创建了一个测试用例,其中我在一个简单的程序中使用了相机,其中精灵在四个方向上移动。那个工作正常,但是当我在主游戏上实现相机时,它无法正常工作。任何帮助将不胜感激。
这是相机类:
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 :(得分:0)
为什么需要使用2D相机的翻译?对于可以做得更简单的事情来说,这是一种非常复杂的方式。在我看来,2D相机应该只是一个对应于相机视口左上角的矢量。然后从任何精灵位置中减去相机矢量,它将与相机一起移动。
因此,在您的情况下,只需将相机矢量设置为中心点减去屏幕宽度和高度的一半:
Camera = SpriteCenter - new Vector2(GraphicsDevice.Viewport.Width / 2, GraphicsDevice.Viewport.Height / 2);
对于每个绘图调用,从精灵的实际位置中减去Camera矢量。 你去了,你的精灵将永远居中。
如果你正在做一些不能让它发挥作用的特殊事物,那么我无法理解你的实际问题。我希望这会有所帮助。
答案 1 :(得分: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);
如果看起来有点偏离,您可能需要将着陆器位置的一半添加回原点或位置。