0

私の問題は、オブジェクトが向いている方向に前進したいということです。現在、回転させることはできますが、前進させることはできません。誰でもこれを修正する方法を教えてもらえますか? コードの一部 (コメントはスウェーデン語ですが、関数が何をするかは理解できるはずです)

ゲームコード:

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

ゲームオブジェクト コード:

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を押すと、「タンク」が向いている方向に前進することです。

4

2 に答える 2

2

私はあなたのコードを深くチェックしていませんが、通常は次のように単純です

position = position + directionVector * velocity * deltaTime;

デバッガーを使用して問題を特定できることに注意してbreakpointくださいif(Enemy == false)

また、このようなコードでは、deltaTime値をインクリメント/デクリメントするときに常にを使用してください。そうしないと、異なるフレーム レートで異なる結果が得られます (たとえば、ゲームはより高速なコンピューターでより高速に再生されます)。

編集:あなたのコードは私には「機能的」に見えますが、前進/後退は上矢印と下矢印にマッピングされていること注意してください...質問で尋ねているようにWではありませんが、これだけが機能していませんか? Keys.Upもしそうなら、単に...に置き換えKeys.Wます

于 2012-11-27T14:22:08.920 に答える
0

遅くて疲れているので、ここであなたが働きたい答えです。

「PI / 2」のオフセットを持つ「角度」と呼ばれる回転があります。これを回転のために「r」と呼ぶことにします。

float r = Angle + (float)Math.PI / 2

あなたがする必要があるのは、前方ベクトルを回転させて一致させることです。これは、迅速な前方ベクトルが必要なときに行う方法です。まず、標準の前方ベクトルが必要です。これは、r = 0 のタンクの前方ベクトルになります。つまり、次のようになります。

Vector2 v = new Vector2(0, -1)

これは、画面をまっすぐ上るベクトルです。これを r だけ回転すると、前方ベクトルが得られます。そのためにクォータニオンを使用します。

Quaternion q = Quaternion.CreateFromAxisAngle(new Vector3(0, 0, 1), r);

v = Vector2.Transform(v, q)

これは、タンクの前方になる回転したベクトルを返します。

オフセット角度で微調整する必要があるかもしれません。遅れており、非常に疲れているため、実際に投稿するべきではありません...

于 2012-11-27T14:28:02.810 に答える