首页 > 解决方案 > 在 Monogame 中制作 Kitty Cannon,我如何将炮弹与其大炮对齐?

问题描述

正如标题所说,我正在尝试制作一个类似于 Monogame 中的 Kitty Cannon 的简单 2D 游戏。但是,我无法将炮弹与管道对齐,因为它是可旋转的。如何将炮弹的生成点与正确的角度和位置连接起来?我在下面发布我目前拥有的代码,希望它可以理解!

class CannonBallSprite
{
    private Texture2D texture;public bool shootingActive = false;
    public bool shootCannon = false;
    public bool keyPressed = false;

    public Vector2 position;
    public Vector2 origin;
    public Vector2 speed = new Vector2(0, 0.1f);
    public Vector2 originalSpeed = new Vector2(0, 0.1f);
    public Vector2 angle; //Trajectory
    public float scale;
    public float minPower = 10;
    public float maxPower = 15;
    public float power = 10;

    public CannonBallSprite(Texture2D texture)
    {
        this.texture = texture;
    }

    public void Update(float rotation, Sprite sprite)
    {

        if (Keyboard.GetState().IsKeyDown(Keys.Left) && power > minPower && !keyPressed)
        {
            power -= 1;
            keyPressed = true;
        }
        else if (Keyboard.GetState().IsKeyDown(Keys.Right) && power < maxPower && !keyPressed)
        {
            power += 1;
            keyPressed = true;
        }

        if (Keyboard.GetState().IsKeyUp(Keys.Left) && keyPressed)
        {
            System.Threading.Thread.Sleep(300);
            keyPressed = false;
        }
        else if(Keyboard.GetState().IsKeyUp(Keys.Right) && keyPressed)
        {
            System.Threading.Thread.Sleep(300);
            keyPressed = false;
        }

        if (Keyboard.GetState().IsKeyDown(Keys.Space) && !shootingActive)
        {
            position = new Vector2(107, 365);                                   // here maybe?
            sprite.hasHit = false;
            shootCannon = true;
        }

        if(shootCannon)
        {
            Move(angle, power);

            speed += new Vector2(0, 0.1f); //standard gravitation
            angle = new Vector2((float)Math.Cos(rotation), (float)Math.Sin(rotation));
                Debug.Write("test");

            position += speed; //Definiera marken
        }
        else
        {
            speed = originalSpeed;
        }

    }

    public void Move(Vector2 rot, float shootPower)
    {
        position.X += rot.X * shootPower;
        position.Y += rot.Y * shootPower;
    }

    public void Draw(SpriteBatch spriteBatch)
    {
        spriteBatch.Draw(texture, position, null, Color.White, 0, origin, scale, SpriteEffects.None, 0f);
    }
}

游戏1类:

 namespace CannonShoot
 {
    public class Game1 : Game
    {
        private GraphicsDeviceManager graphics;
        private SpriteBatch spriteBatch;
        private Texture2D cannon;
        private Texture2D cannonball;
        private Texture2D man;
        private SpriteFont font;
        private Sprite spriteCannon;
        private Sprite manSprite;
        private CannonBallSprite cannonBallSprite;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            IsMouseVisible = true;
        }

        protected override void Initialize()
        {
            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
            font = Content.Load<SpriteFont>("fontfile");       
            cannon = Content.Load<Texture2D>("cannon");
            cannonball = Content.Load<Texture2D>("cannonball");
            man = Content.Load<Texture2D>("man");

            spriteCannon = new Sprite(cannon)
            {
                position = new Vector2(100, 400),
                origin = new Vector2(cannon.Width / 2, cannon.Height / 2),
                scale = 0.12f
            };

            cannonBallSprite = new CannonBallSprite(cannonball)
            {

                position = new Vector2(1150, 3750),
                scale = 0.2f
            };

            manSprite = new Sprite(man)
            {
                position = new Vector2(700, 250),
                origin = new Vector2(man.Width / 2, man.Height / 2),
                scale = 0.4f
            };

        }

        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
                Exit();
            
            if(!cannonBallSprite.shootCannon)
            {
                spriteCannon.Update();
            }

            //cannonBallSprite = (spriteCannon.position.X, spriteCannon.position.Y); 

            cannonBallSprite.Update(spriteCannon.rotation, manSprite);
            manSprite.UpdateHitbox(cannonBallSprite);

            if(cannonBallSprite.position.X >= 1000 || cannonBallSprite.position.Y >= 600) //respawn
            {
               
                cannonBallSprite.shootCannon = false;
            }

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            spriteBatch.Begin();
            spriteCannon.Draw(spriteBatch);
            manSprite.Draw(spriteBatch);
            cannonBallSprite.Draw(spriteBatch);
            spriteBatch.DrawString(font, "Power: " + cannonBallSprite.power, new Vector2(16, 16), Color.Black);
            spriteBatch.DrawString(font, "Hits: " + manSprite.hit, new Vector2(16, 62), Color.Black);
            spriteBatch.End();

            base.Draw(gameTime);
        }
    }
}

精灵类:

namespace CannonShoot
{
    class Sprite
    {
        private Texture2D texture;

        public Vector2 position;
        public Vector2 origin;
        public float scale;

        public float rotationVelocity = 3f;
        public float linearVelocity = 4f;

        public float minRot = -1f;
        public float maxRot = 0f;
        public float rotation;


        public float hit = 0;
        public bool hasHit = false;

        public Sprite(Texture2D texture)
        {
            this.texture = texture;
        }

        public void Update()
        {
            if (rotation <= maxRot && rotation >= minRot)
            {
                if (Keyboard.GetState().IsKeyDown(Keys.Up))
                {
                    rotation -= MathHelper.ToRadians(rotationVelocity);

                }
                else if (Keyboard.GetState().IsKeyDown(Keys.Down))
                {
                    rotation += MathHelper.ToRadians(rotationVelocity);

                }

                if(rotation < minRot)
                {
                    rotation = minRot;
                }
                
                if (rotation > maxRot)
                {
                    rotation = maxRot;
                }
            }

           
        }

        public void UpdateHitbox(CannonBallSprite cbSprite) //hitbox och 
        {
            if(cbSprite.position.X >= 700 && cbSprite.position.Y <= 350 && cbSprite.position.Y >= 150 && !hasHit)
            {
                hit++;
                hasHit = true;
                cbSprite.shootCannon = false;
            }
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(texture, position, null, Color.White, rotation, origin, scale, SpriteEffects.None, 0f);
        }
    }
}

标签: c#monogame

解决方案


获取旋转物体的桶位置的代码:

  angle = new Vector2((float)Math.Cos(rotation), (float)Math.Sin(rotation));
  SpawnPosition = position + angle * TextureWidth * scale; // + .5f * TextureHeight * scale; if origin is at 0,0.

宽度和高度基于指向右侧的大炮纹理。


推荐阅读