My problem is that I have an object I want to move forward in the direction it's facing, right now I'm able to rotate it, but unable to make it move forward. can anyone tell me how to fix this ? Some of the code (the comments are in Swedish, but it should be understandable what the function do)
Game Code:
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 Code:
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);
}
}
}
Moving Game Object Code:
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;
}
}
}
Tank Code:
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);
}
}
}
I have tried many different things but nothing seems to work. What I want is that when I press W the "tank" moves forward in the direction its facing.
I haven't checked your code deeply, but usually it's as simple as
position = position + directionVector * velocity * deltaTime;
Keep in mind that you can use a debugger to locate the problem, adding a breakpoint
in the if(Enemy == false)
to see which condition you assume works that doesn't.
Also, in code like this, always use your deltaTime
when incrementing / decrementing values, otherwise you will have different results on different frame rates (for example, the game will play faster on a faster computer)
Edit : while your code looks "functional" to me, keep in mind that going forward / backward is mapped on the Up and Down arrows... not W like you are asking in the question, is this the only thing not working? If so, simply replace Keys.Up
to Keys.W
...
It is late and I am tired so here is the answer you want to work with.
You have a rotation called "Angle" with an offset of "PI / 2" I am going to call this 'r' for rotation, so:
float r = Angle + (float)Math.PI / 2
What you need to do is rotate a forward vector to match it, this is how I do it when I need a quick forward vector. To begin with, we need a standard forward vector, which would be the forward vector of a tank with r = 0, ie:
Vector2 v = new Vector2(0, -1)
This is a vector going straight up the screen. If we rotate this by r, then we have the forward vector. I am going to use a Quaternion to do so.
Quaternion q = Quaternion.CreateFromAxisAngle(new Vector3(0, 0, 1), r);
v = Vector2.Transform(v, q)
This will return a rotated vector that will be the forward of the tank.
You may need to tweak it with an offset angle, it is late and I am very tired and shouldn't be posting really...
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.