我的问题是,我有一个物体,我想朝着它面向的方向前进,现在我能够旋转它,但无法让它向前移动。谁能告诉我如何解决这个问题?一些代码(评论是瑞典语,但应该可以理解函数的作用)
游戏代码:
namespace MultiPlayerTanks
{
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Tank Player1, Player2; //skapa två spelare/tanks
GameObj Bana; //Skapa ett GameObj som ska användas som bana
SpriteFont font; //Spritefont för utskrift
Meter PowerMeter,PowerMeter2, Player1LifeMeter, Player2LifeMeter; //Mätare för liv och kraft
List<Shot> allShots = new List<Shot>();
List<Shot> allShots2 = new List<Shot>();//Ny lista för alla skott(-objekt)
Texture2D shot1Gfx; //Grafik till skotten
List<Explosion> allExplosions = new List<Explosion>();
List<Explosion> allExplosions2 = new List<Explosion>();//Ny lista för alla explosioner
Texture2D explosionGfx; //Grafik till explosionen
string displayMessage = ""; //Text som skalman skrivas ut
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
// Change of resolution.
this.graphics.PreferredBackBufferWidth = 800;
this.graphics.PreferredBackBufferHeight = 600;
//this.graphics.IsFullScreen = true;
}
protected override void Initialize()
{
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
//Ladar in grafiken
Texture2D greenTankGfx = Content.Load<Texture2D>("green_tank");
Texture2D redTankGfx = Content.Load<Texture2D>("red_tank");
Texture2D level1Gfx = Content.Load<Texture2D>("level");
Texture2D redMeterGfx = Content.Load<Texture2D>("meter");
Texture2D lifeMeterGfx = Content.Load<Texture2D>("life_meter");
shot1Gfx = Content.Load<Texture2D>("shot");
explosionGfx = Content.Load<Texture2D>("explosion");
//Load basic texture to make it recognizable :)
//Skapa Objekt
//Tilldelning av properties direkt.. slipper skriva konstruktorer
Player1 = new Tank()
{
Gfx = greenTankGfx,
Position = new Vector2(400, 300),
Speed = 0,
Direction = new Vector2(0, -1),
Enemy = false
};
Player2 = new Tank()
{
Gfx = redTankGfx,
Position = new Vector2(400, 300),
Speed = 0,
Direction = new Vector2(0, -1),
Enemy = true
};
Bana = new GameObj() { Gfx = level1Gfx, Position = new Vector2(0, 0), Angle = 0 };
PowerMeter = new Meter() { Gfx = redMeterGfx, Position = new Vector2 (Player1.Position.X,Player1.Position.Y) };
PowerMeter2 = new Meter() { Gfx = redMeterGfx, Position = new Vector2(Player2.Position.X,Player2.Position.Y) };
Player1LifeMeter = new Meter() { Gfx = lifeMeterGfx, Position = new Vector2(50, 50) };
Player2LifeMeter = new Meter() { Gfx = lifeMeterGfx, Position = new Vector2(250, 50) };
font = Content.Load<SpriteFont>("SpriteFont1");
}
protected override void UnloadContent()
{
}
protected override void Update(GameTime gameTime)
{
Player1.Update(gameTime); //Uppdatera spelare1
Player2.Update(gameTime);
//Sätter Kraftmätarens värde till vår spelares "skottkraft"
PowerMeter2.Value = Player2.ShotPower;
PowerMeter.Value = Player1.ShotPower;
//Sätter Livmätarnas värde till resp. spelares liv-värde
Player1LifeMeter.Value = Player1.Life;
Player2LifeMeter.Value = Player2.Life;
#region player 2 shotfired
if (Player2.ShotFired) //Ifall ett skott avfyrats
{
//Lägger till ett nytt skott i listan
allShots2.Add(new Shot()
{
Gfx = shot1Gfx,
Position = Player2.Position + (Player2.Direction * (Player2.Gfx.Height) / 2) +
(Player2.Direction * shot1Gfx.Height / 2),
Angle = Player2.Angle,
Speed = 5.0F + Player2.Speed,
Power = Player2.ShotPower,
Direction = Player2.Direction
});
Player2.ShotPower = 0;
Player2.ShotFired = false;
}
for (int i = 0; i < allShots2.Count; i++) //Loopar igenom alla skott
{
allShots2[i].Update(gameTime); //uppdaterar skott
if (allShots2[i].Power < 0) //Är skottets "kraft" slut?
{
//Lägg till en ny Explosion
allExplosions2.Add(new Explosion() { Gfx = explosionGfx, Position = allShots2[i].Position });
allShots2.RemoveAt(i); //Tar bort skottet
}
}
for (int i = 0; i < allExplosions2.Count; i++) //Loopa igenom alla explosioner
{
allExplosions2[i].Update(gameTime); //Uppdatera explosion
//Ta bort "färdiga" explosioner
if (allExplosions2[i].Active == false) allExplosions2.RemoveAt(i);
}
#endregion
if (Player1.ShotFired) //Ifall ett skott avfyrats
{
//Lägger till ett nytt skott i listan
allShots.Add(new Shot()
{
Gfx = shot1Gfx,
Position = Player1.Position + (Player1.Direction * (Player1.Gfx.Height) / 2) +
(Player1.Direction * shot1Gfx.Height / 2),
Angle = Player1.Angle,
Speed = 5.0F + Player1.Speed,
Power = Player1.ShotPower,
Direction = Player1.Direction
});
Player1.ShotPower = 0;
Player1.ShotFired = false;
}
for (int i = 0; i < allShots.Count; i++) //Loopar igenom alla skott
{
allShots[i].Update(gameTime); //uppdaterar skott
if (allShots[i].Power < 0) //Är skottets "kraft" slut?
{
//Lägg till en ny Explosion
allExplosions.Add(new Explosion() { Gfx = explosionGfx, Position = allShots[i].Position });
allShots.RemoveAt(i); //Tar bort skottet
}
}
for (int i = 0; i < allExplosions.Count; i++) //Loopa igenom alla explosioner
{
allExplosions[i].Update(gameTime); //Uppdatera explosion
//Ta bort "färdiga" explosioner
if (allExplosions[i].Active == false) allExplosions.RemoveAt(i);
}
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Black);
spriteBatch.Begin();
//Ritar ut bana, spelare och mätare
Bana.Draw(spriteBatch, new Vector2(0,0));
PowerMeter.Draw(spriteBatch, Player1.Position);
PowerMeter2.Draw(spriteBatch, Player2.Position);
Player1.Draw(spriteBatch, Player1.Position);
Player2.Draw(spriteBatch, Player2.Position);
Player1LifeMeter.Draw(spriteBatch, new Vector2(0, 0));
Player2LifeMeter.Draw(spriteBatch, new Vector2(0, 0));
//Loopar igenom alla skott och ritar ut dem
for (int i = 0; i < allShots.Count; i++)
{
allShots[i].Draw(spriteBatch, Player1.Position);
}
//Loopar igenom alla explosioner och ritar ut dem
for (int i = 0; i < allExplosions.Count; i++)
{
allExplosions[i].Draw(spriteBatch, Player1.Position);
}
///////////////////////////////////////////////////
for (int i = 0; i < allShots2.Count; i++)
{
allShots2[i].Draw(spriteBatch, Player2.Position);
}
//Loopar igenom alla explosioner och ritar ut dem
for (int i = 0; i < allExplosions2.Count; i++)
{
allExplosions2[i].Draw(spriteBatch, Player2.Position);
}
//Skriver ut spelarnas namn och liv mm..
string nameFormat = "{0}\nLife: {1}%\n\nKills: {2}";
displayMessage = string.Format(nameFormat, "Player1", Player1.Life, Player1.Kills);
spriteBatch.DrawString(font, displayMessage, new Vector2(51, 4), Color.Black);
spriteBatch.DrawString(font, displayMessage, new Vector2(50, 5), Color.White);
displayMessage = string.Format(nameFormat, "Player2", Player2.Life, Player2.Kills);
spriteBatch.DrawString(font, displayMessage, new Vector2(251, 4), Color.Black);
spriteBatch.DrawString(font, displayMessage, new Vector2(250, 5), Color.White);
spriteBatch.End();
base.Draw(gameTime);
}
}
}
GameObject代码:
namespace MultiPlayerTanks
{
class GameObj
{
public Vector2 Position //Objektets position
{
get;
set;
}
public Texture2D Gfx //Objektets grafik
{
get;
set;
}
public float Angle //Objektets vinkel
{
get;
set;
}
public virtual void Draw(SpriteBatch spriteBatch, Vector2 DrawOffset)
{
spriteBatch.Draw(Gfx,
Position - DrawOffset + new Vector2(400, 300), null,
Color.White, Angle + (float)Math.PI / 2,
new Vector2(Gfx.Width / 2, Gfx.Height / 2), 1.0f,
SpriteEffects.None, 0);
}
}
}
移动游戏对象代码:
namespace MultiPlayerTanks
{
class MovingGameObj : GameObj
{
public Vector2 Direction //Riktning
{
get;
set;
}
public float spriterotation //Hastighet
{
get;
set;
}
public float Speed //Hastighet
{
get;
set;
}
public virtual void Update(GameTime gameTime)
{
Position += Direction * Speed;
}
}
}
坦克代码:
namespace MultiPlayerTanks
{
class Tank : MovingGameObj
{
public Tank()
{
MaxSpeed = 2.5F;
ShotPower = 0;
prevKs = Keyboard.GetState();
prevKs2 = Keyboard.GetState();
Life = 100F;
Kills = 0;
Angle = -(float)(Math.PI / 2);
}
public bool Enemy
{
get;
set;
}
public float MaxSpeed
{
get;
set;
}
public float ShotPower
{
get;
set;
}
public int WeaponType
{
get;
set;
}
public bool ShotFired
{
get;
set;
}
public float Life
{
get;
set;
}
public int Kills
{
get;
set;
}
protected KeyboardState prevKs;
protected KeyboardState prevKs2;
public void Respawn()
{
Life = 100F;
Random randomerare = new Random();
Position = new Vector2(randomerare.Next(1000), randomerare.Next(1000));
Angle = 0;
}
public override void Update(GameTime gameTime)
{
KeyboardState ks = Keyboard.GetState();
KeyboardState ks2 = Keyboard.GetState();
#region Player 1
if (Enemy == false)
{
if (ks.IsKeyDown(Keys.Up))
{
if (Speed < 0) Speed = 0;
if (Speed < MaxSpeed) Speed = Speed * 1.005F + 0.01F;
else Speed = MaxSpeed;
}
if (ks.IsKeyDown(Keys.Down))
{
if (Speed > -1.0F) Speed -= 0.04F;
else Speed = -1.0F;
}
if (ks.IsKeyUp(Keys.Down) && ks.IsKeyUp(Keys.Up) && Speed > 0)
{
Speed -= 0.01F;
if (Speed <= 0) Speed = 0;
}
if (ks.IsKeyUp(Keys.Down) && ks.IsKeyUp(Keys.Up) && Speed < 0)
{
Speed += 0.01F;
if (Speed >= 0) Speed = 0;
}
if (ks.IsKeyUp(Keys.Left))
{
Angle += 0.02F;
}
if (ks.IsKeyUp(Keys.Right))
{
Angle -= 0.02F;
}
if (ks.IsKeyDown(Keys.Space))
{
if (ShotPower < 100)
ShotPower += 0.5F;
else
ShotPower = 100;
}
if (ks.IsKeyUp(Keys.Space) && prevKs.IsKeyDown(Keys.Space))
{
//ShotPower = 0;
ShotFired = true;
}
}
#endregion
prevKs = ks;
Direction = new Vector2((float)Math.Cos(Angle), (float)Math.Sin(Angle));
base.Update(gameTime);
}
}
}
我尝试过很多不同的东西但似乎没什么用。我想要的是,当我按下W时,“坦克”向其朝向的方向前进。
答案 0 :(得分:2)
我没有深入检查你的代码,但通常它就像
一样简单position = position + directionVector * velocity * deltaTime;
请注意,您可以使用调试程序找到问题,在breakpoint
中添加if(Enemy == false)
以查看您认为哪种情况不起作用。
此外,在这样的代码中,在递增/递减值时始终使用deltaTime
,否则在不同的帧速率下会有不同的结果(例如,游戏在更快的计算机上播放速度更快)
修改:虽然您的代码看起来“功能性”,但请记住,前进 / 后退映射到向上和向下箭头...不是 W 就像你问的问题一样,这是唯一不起作用的吗?如果是这样,只需将Keys.Up
替换为Keys.W
...
答案 1 :(得分:0)
已经很晚了,我很累,所以这就是你想要的答案。
你有一个名为“Angle”的旋转,其偏移量为“PI / 2”我将这个'r'称为旋转,所以:
float r = Angle + (float)Math.PI / 2
你需要做的是旋转一个前向矢量来匹配它,这就是我需要一个快速前向矢量时的方法。首先,我们需要一个标准的前向矢量,它是r = 0的坦克的前向矢量,即:
Vector2 v = new Vector2(0, -1)
这是一个直接向上移动的矢量。如果我们用r旋转它,那么我们有前向向量。我将使用Quaternion这样做。
Quaternion q = Quaternion.CreateFromAxisAngle(new Vector3(0, 0, 1), r);
v = Vector2.Transform(v, q)
这将返回一个旋转的矢量,该矢量将成为坦克的前方。
你可能需要用偏移角调整它,它已经很晚了,我很累,不应该发布真的......