0
votes

Okay so I'm making a space invader type game in visual studio 2010 c# with xna studio, currently stuck on the bullet class it spawns the bullet but doesn't fire it off in the direction that the sprite is pointing. The bullet class says the Public Vector2 origin; isn't being assigned to anything & is remaining at its default value however I don't know what could be causing it.

Code for bullet

   class Bullets
    {
        public Texture2D texture;

        public Vector2 position;
        public Vector2 velocity;
        public Vector2 origin;

        public bool isVisible;

        public Bullets(Texture2D newTexture)
        {
            texture = newTexture;
            isVisible = false;
        }




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

    }

Code for the game is:

namespace Rotationgame
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        Vector2 spriteVelocity;
        const float tangentialVelocity = 0f;
        float friction = 1f;

        Texture2D spriteTexture;
        Rectangle spriteRectangle;

        Rectangle screenRectangle;

        // The centre of the image
        Vector2 spriteOrigin;

        Vector2 spritePosition;
        float rotation;

        // Background
        Texture2D backgroundTexture;
        Rectangle backgroundRectangle;


        // Shield
        Texture2D shieldTexture;
        Rectangle shieldRectangle;

        // Bullets
        List<Bullets> bullets = new List<Bullets>();
        KeyboardState pastKey;



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

            graphics.PreferredBackBufferWidth = 1250;
            graphics.PreferredBackBufferHeight = 930;

            screenRectangle = new Rectangle(
                0,
                0,
                graphics.PreferredBackBufferWidth,
                graphics.PreferredBackBufferHeight);
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            shieldTexture = Content.Load<Texture2D>("Shield");
            shieldRectangle = new Rectangle(517, 345, 250, 220);

            spriteTexture = Content.Load<Texture2D>("PlayerShipup");
            spritePosition = new Vector2(640, 450);

            backgroundTexture = Content.Load<Texture2D>("Background");
            backgroundRectangle = new Rectangle(0, 0, 1250, 930);

            // TODO: use this.Content to load your game content here
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (Keyboard.GetState().IsKeyDown(Keys.Escape))
                this.Exit();

            // TODO: Add your update logic here

            if (Keyboard.GetState().IsKeyDown(Keys.Space) && pastKey.IsKeyUp(Keys.Space))
                Shoot();
            pastKey = Keyboard.GetState();

            spritePosition = spriteVelocity + spritePosition;

            spriteRectangle = new Rectangle((int)spritePosition.X, (int)spritePosition.Y,
                spriteTexture.Width, spriteTexture.Height);
            spriteOrigin = new Vector2(spriteRectangle.Width / 2, spriteRectangle.Height / 2);

            if (Keyboard.GetState().IsKeyDown(Keys.Right)) rotation += 0.025f;
            if (Keyboard.GetState().IsKeyDown(Keys.Left)) rotation -= 0.025f;

            if (Keyboard.GetState().IsKeyDown(Keys.Up))
            {
                spriteVelocity.X = (float)Math.Cos(rotation) * tangentialVelocity;
                spriteVelocity.Y = (float)Math.Sin(rotation) * tangentialVelocity;
            }
            else if (Vector2.Zero != spriteVelocity)
            {
                float i = spriteVelocity.X;
                float j = spriteVelocity.Y;

                spriteVelocity.X = i -= friction * i;
                spriteVelocity.Y = j -= friction * j;


                base.Update(gameTime);

            }
        }

        public void UpdateBullets()
        {
            foreach (Bullets bullet in bullets)
            {
                bullet.position += bullet.velocity;
                if (Vector2.Distance(bullet.position, spritePosition) > 100)
                    bullet.isVisible = false;
            }
            for (int i = 0; i < bullets.Count; i++)
            {
                if(!bullets[i].isVisible)
                {
                    bullets.RemoveAt(i);
                    i--;


                }


            }
        }

        public void Shoot()
        {
            Bullets newBullet = new Bullets(Content.Load<Texture2D>("ball"));
            newBullet.velocity = new Vector2((float)Math.Cos(rotation),(float)Math.Sin(rotation)) * 5f + spriteVelocity;
            newBullet.position = spritePosition + newBullet.velocity * 5;
            newBullet.isVisible = true;

            if(bullets.Count() < 20)
                bullets.Add(newBullet);
        }



        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            spriteBatch.Begin();
            spriteBatch.Draw(backgroundTexture, backgroundRectangle, Color.White);
            spriteBatch.Draw(shieldTexture, shieldRectangle, Color.White);
            foreach (Bullets bullet in bullets)
                bullet.Draw(spriteBatch);
            spriteBatch.Draw(spriteTexture, spritePosition, null, Color.White, rotation, spriteOrigin, 1f, SpriteEffects.None, 0);
            spriteBatch.End();


            // TODO: Add your drawing code here

            base.Draw(gameTime);
        }
    }

Where am I going wrong?

2
A quick review of your game class and I don't seem to see where you call UpdateBullets?borrillis
Halfway down the code it says Public void UpdateBullets()Marc Brooks
@MarcBrooks You've defined the method but you don't seem to be calling it in your code.Matt Hogan-Jones

2 Answers

2
votes

When you draw the bullet you pass origin as an argument but never set a value to it. You should find the point on the image which you want to be the origin (so if you place the bullet at 0,0 that part of the image will be on 0,0).

If you don't set a value for a variable and then try and pass it into a function if it's needed by the function then this will cause the program to crash.

Try 0,0 first so in the class

Vector2 origin=new Vector2(0,0);

That should make your code work, tweak the origin based on your preferences.

Also instead of making these variables public it is far better practise to make the private and create get and set functions in bullet to set them or get the values. This minimises the risk of unpredictable access and modification

EDIT: looked again realised that although a problem was not THE problem.

    protected override void Update(GameTime gameTime)
    {
        // Allows the game to exit
        if (Keyboard.GetState().IsKeyDown(Keys.Escape))
            this.Exit();

        updateBullets();
        ...
    }

You need to actually call updateBullets in your update function, it won't get called automatically

0
votes

I modified your Game classes Update method to call your UpdateBullets method and now the bullet sprites will travel in a direction and then disappear.

I have also fixed the Shoot() method to properly direct the bullets according to the direction the ship is rotated to.

    protected override void Update(GameTime gameTime)
    {
        // Allows the game to exit
        if (Keyboard.GetState().IsKeyDown(Keys.Escape))
            this.Exit();

        // TODO: Add your update logic here

        if (Keyboard.GetState().IsKeyDown(Keys.Space) && pastKey.IsKeyUp(Keys.Space))
            Shoot();
        pastKey = Keyboard.GetState();

        spritePosition = spriteVelocity + spritePosition;

        spriteRectangle = new Rectangle((int)spritePosition.X, (int)spritePosition.Y,
            spriteTexture.Width, spriteTexture.Height);
        spriteOrigin = new Vector2(spriteRectangle.Width / 2, spriteRectangle.Height / 2);

        if (Keyboard.GetState().IsKeyDown(Keys.Right)) rotation += 0.025f;
        if (Keyboard.GetState().IsKeyDown(Keys.Left)) rotation -= 0.025f;

        if (Keyboard.GetState().IsKeyDown(Keys.Up))
        {
            spriteVelocity.X = (float)Math.Cos(rotation) * tangentialVelocity;
            spriteVelocity.Y = (float)Math.Sin(rotation) * tangentialVelocity;
        }
        else if (Vector2.Zero != spriteVelocity)
        {
            float i = spriteVelocity.X;
            float j = spriteVelocity.Y;

            spriteVelocity.X = i -= friction * i;
            spriteVelocity.Y = j -= friction * j;


            base.Update(gameTime);

        }
        UpdateBullets();
    }
    public void Shoot()
    {
        Bullets newBullet = new Bullets(Content.Load<Texture2D>("ball"));
        newBullet.velocity = new Vector2((float)Math.Sin(rotation), (float)Math.Cos(rotation)) * new Vector2(5f,-5f) + spriteVelocity;
        newBullet.position = spritePosition + newBullet.velocity * 5;
        newBullet.isVisible = true;

        if (bullets.Count < 20)
            bullets.Add(newBullet);
    }