Jump to content

  • Log In with Google      Sign In   
  • Create Account

XNA - Making A Sprite Fire A Projectile


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
7 replies to this topic

#1 mistervirtue   Members   -  Reputation: 590

Like
0Likes
Like

Posted 03 June 2013 - 08:34 AM

Hello Fellow GameDev'ers,

 

I am working on my personal project and I have hit a serious road block. I am trying to making the player fire projectiles, but I can't really make it work. I have searched online for tutorials, but I can't seem to find any that make use of SpriteManager like I am doing. I am trying to make it as Object-Oriented as possible but I don't really know what to do.

 

I currently have a base Sprite.cs, a UserControlled.cs, and now a ProjectileSprite.cs, and a game component called SpriteManager.cs. I figure should model my ProjectileSprite.cs similarly to my other sprites and then add it to the SpriteManager.cs. But I also don't know how to make it interact with the UserControlled.cs so it will shoot when you want it to.

 

Does GameDev.net have any resources on this kind of problem? If anyone can give me any hints/points/shoves in the right direction that would be awesome.



Sponsor:

#2 adt7   Members   -  Reputation: 425

Like
0Likes
Like

Posted 03 June 2013 - 09:05 AM

Without seeing any code it's hard to give any advice on how to fit it into your existing setup.

Coudl you post snippets of the relavent parts of your Sprite, SpriteManager, UserController and ProjectileSprite classes? Or at least the parts that seem to be causing you difficulty?

#3 Aurioch   Crossbones+   -  Reputation: 1304

Like
2Likes
Like

Posted 03 June 2013 - 11:50 AM

Hello

 

I believe I can help you with basics (since tags mention C# and XNA), because my current project involves lots of projectiles.

 

Basically, what you need is to make a projectile as a separate object:

public class Projectile()
{
     Texture2D projectileSprite;
     Rectangle projectileHitBox; // assuming you're going with hit box collision, otherwise use commented block below
     /*
     Vector2 projectilePosition;
     Vector2 projectileOrigin;
     float projectileScale;
     float projectileRotation;
     */

     // rest of the code
}

As you can see, that class will hold all relevant information for your projectile.

 

For creation of new projectile, you'll need a constructor which will allow you to create new projectile fast:

public Projectile(Texture2D spriteTexture, Vector2 projectilePosition) // change parameters as you see fit
{
     projectileSprite = spriteTexture;
     // insert additional code here, such as creation of hitbox
}

 

In your main code now you can manipulate projectiles:

Projectile Bullet; // declaration of single bullet
List<Projectile> Bullets; // if you plan to track multiple bullets at the same time

public override void Update(GameTime gameTime)
{
// code snippet

// Creation of new bullet
Bullet = new Projectile(bulletTexture, currentPlayerPosition);

// If you need to add to the list
Bullets.Add(new Projectile(bulletTexture, currentPlayerPosition)); // or in this case just add Bullet

// code snippet; bullet update code
}

 

Drawing is done the same way; first in Projectile class write separate Draw method:

public void Draw(SpriteBatch spriteBatch)
{
    spriteBatch.Draw(bulletTexture, bulletHitBox, Color.White); // this one is simplest; use other Draw overrides if you need to
}

 

Then in your main Draw function just call the above method:

public override void Draw (GameTime gameTime)
{
// code snippet; spriteBatch.Begin is somewhere here if spriteBatch exists

Projectile.Draw(spriteBatch)

//code snippet; spriteBatch.End is somewhere here
}

 

How to destroy projectile?

// if single projectile
Bullet = null;

// if using lists
Bullets.Remove(Bullet) // removal by specific object
Bullets.RemoveAt(bulletIndex) // removal by index of relevant projectile

 

I have no idea how you modelled your classes (and also, those names are fairly suspicious, probably just me/my style of coding) so if you plan to use any of this code, you'll need it to adapt to your own setup. I could show you my code if you're interested (be it PM or forum post) but my setup is completely different than yours.



#4 mistervirtue   Members   -  Reputation: 590

Like
1Likes
Like

Posted 03 June 2013 - 12:24 PM

Here is my code for the most part

 

--------- SpriteManager ---------

    public class SpriteManager : Microsoft.Xna.Framework.DrawableGameComponent
    {

        SpriteBatch spriteBatch;
        UserControlledSprite player;
        Texture2D testingRec;
        Texture2D projectileSprite;
        List<Sprite> spriteList = new List<Sprite>();

        public SpriteManager(Game game)
            : base(game)
        {
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(Game.GraphicsDevice);

            player = new UserControlledSprite(Game.Content.Load<Texture2D>(@"images/SmallHero"),
                Vector2.Zero, new Point(85, 97), 1, new Point(0, 0), new Point(1, 1), new Vector2(3, 3));
            
            testingRec = Game.Content.Load<Texture2D>(@"images/testRec");

            projectileSprite = Game.Content.Load<Texture2D>(@"images/fireblast");

            base.LoadContent();

        }

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

        public override void Update(GameTime gameTime)
        {
            player.Update(gameTime, Game.Window.ClientBounds);
            base.Update(gameTime);
        }

        public override void Draw(GameTime gameTime)
        {
            spriteBatch.Begin();

            player.Draw(gameTime, spriteBatch);

            spriteBatch.Draw(testingRec,player.collisionRect ,Color.White);

            spriteBatch.End();

            base.Draw(gameTime);
        }
    }

 

----- My base Sprite Class -------

namespace ProjectGaslightKnights
{
    abstract class Sprite
    {
        public Texture2D textureImage;
        protected Vector2 position;
        protected Point frameSize;
        int collisionOffset;
        public Point currentFrame;
        public Point sheetSize;
        int timeSinceLastFrame = 0;
        protected Vector2 speed;
        int milisecondsPerFrame;
        const int defaultMillisecondsPerFrame = 16;


        SpriteEffects myEffect;
        Texture2D testingRecTexture;

        public Sprite(Texture2D textureImage, Vector2 position, Point frameSize,
            int collisionOffset, Point currentFrame, Point sheetSize, Vector2 speed)
            : this(textureImage, position, frameSize, collisionOffset, currentFrame, sheetSize, speed, defaultMillisecondsPerFrame)
        {

        }

        public Sprite(Texture2D textureImage, Vector2 position, Point frameSize, int collisionOffset, Point currentFrame,
            Point sheetSize, Vector2 speed, int millisecondsPerFrame)
        {
            this.textureImage = textureImage;
            this.position = position;
            this.frameSize = frameSize;
            this.collisionOffset = collisionOffset;
            this.currentFrame = currentFrame;
            this.sheetSize = sheetSize;
            this.speed = speed;
            this.milisecondsPerFrame = milisecondsPerFrame;
        }

        public virtual void Update(GameTime gameTime, Rectangle ClientBounds)
        {
            timeSinceLastFrame += gameTime.ElapsedGameTime.Milliseconds;
            if (timeSinceLastFrame > milisecondsPerFrame)
            {
                timeSinceLastFrame = 0;
                ++currentFrame.X;
                if (currentFrame.X >= sheetSize.X)
                {
                    currentFrame.X = 0;
                    ++currentFrame.Y;
                    if (currentFrame.Y >= sheetSize.Y)
                    {
                        currentFrame.Y = 0;
                    }
                }
            }
        }

        public virtual void Draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(textureImage, position,
                new Rectangle(currentFrame.X * frameSize.X, currentFrame.Y * frameSize.Y,
                    frameSize.X, frameSize.Y), Color.White, 0, Vector2.Zero, 1f, myEffect, 0);

            spriteBatch.Draw(testingRecTexture, collisionRect, Color.White);
        }


        public abstract Vector2 direction
        {
            get;
        }


        public Rectangle collisionRect
        {
            get
            {
                return new Rectangle(
                    (int)position.X + collisionOffset,
                    (int)position.Y + collisionOffset,
                    frameSize.X - (collisionOffset * 2),
                    frameSize.Y - (collisionOffset * 2));
            }
        }

        internal void Update(GameTime gameTime)
        {
            throw new NotImplementedException();
        }
    }
}

-------And my user Class -------

   class UserControlledSprite : Sprite
    {
        SpriteEffects myEffect;

        public UserControlledSprite(Texture2D textureImage, Vector2 position,
            Point frameSize, int collisionOffset, Point currentFrame, Point sheetSize,
            Vector2 speed)
            : base(textureImage, position, frameSize, collisionOffset,
            currentFrame, sheetSize, speed)
        {
        }

        public UserControlledSprite(Texture2D textureImage, Vector2 position,
             Point frameSize, int collisionOffset, Point currentFrame, Point sheetSize,
             Vector2 speed, int millisecondsPerFrame)
            : base(textureImage, position, frameSize, collisionOffset,
            currentFrame, sheetSize, speed, millisecondsPerFrame)
        {
        }

        public override Vector2 direction
        {
            get
            {
                Vector2 inputDirection = Vector2.Zero;

                if (Keyboard.GetState().IsKeyDown(Keys.Left))
                {
                    inputDirection.X -= 1;

                }
                if (Keyboard.GetState().IsKeyDown(Keys.Right))
                {
                    inputDirection.X += 1;

                }
                if (Keyboard.GetState().IsKeyDown(Keys.Down))
                {
                    inputDirection.Y += 1;

                }
                if (Keyboard.GetState().IsKeyDown(Keys.Up))
                {
                    inputDirection.Y -= 1;

                }

                return inputDirection * speed;
            }
        }


        public override void Update(GameTime gameTime, Rectangle ClientBounds)
        {
            //Move the spite according to the direction property
            position += direction;

            //If the player is facing left, flip it horizontally
            if (direction.X < 0)
            {
                this.myEffect = SpriteEffects.FlipHorizontally;
            }

            //If The player is facing right, no effect
            if (direction.X > 0)
            {
                this.myEffect = SpriteEffects.None;
            }

            //If the player leaves bounds off the screen put it back in play
            if (position.X < 0)
            {
                position.X = 0;
            }

            if (position.Y < 0)
            {
                position.Y = 0;
            }

            if (position.X > ClientBounds.Width - (frameSize.X))
            {
                position.X = ClientBounds.Width - (frameSize.X );
            }

            if (position.Y > ClientBounds.Height - (frameSize.Y))
            {
                position.Y = ClientBounds.Height - (frameSize.Y);

            }

            base.Update(gameTime, ClientBounds);
        }

       public override void Draw(GameTime gameTime, SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(textureImage, position,
              new Rectangle(currentFrame.X * frameSize.X, currentFrame.Y * frameSize.Y,
        frameSize.X, frameSize.Y), Color.White, 0, Vector2.Zero, 1, myEffect, 0);

        }
    }

 

I feel like I am cheating though. This isn't a school project or anything but all my professers tell me that Programmers need to learn to solve their own problems. But I think problem solving should involve other people, see as most of us want to work with other programmers. Anyway I am trying to build it such that my UserClass will be able to fire projectiles. So i Think the way I am going to model my ProjecticleSprite with a it's own draw(), and Update() and not inherit from the base class sprite. Thanks for your help everyone.



#5 SelethD   Members   -  Reputation: 390

Like
1Likes
Like

Posted 03 June 2013 - 09:55 PM

I didnt look through all the code posted, so not sure if this will help.  However, this is how I would do it.

 

Since you have a sprite manager, you need to be able to 'create' sprites, manage them while they are alive, and eventually destroy them after a certain time, or condition.

 

For the projectile, you need to 'create' it at the location of your player, and let your sprites hold a heading and velocity.

 

so when player fires, create projectile sprite, set its heading to whatever heading your player has, set its velocity to something fast, then let the sprite manager, continue to update its movement, check collisions, and draw the projecting, until it gets off screen or hits something, etc... then let the sprite manager destory the object.



#6 Gorge Express   Members   -  Reputation: 179

Like
0Likes
Like

Posted 04 June 2013 - 04:53 AM

For something simple like shooting a projectile, i'd just give the class dealing with input access to the sprite manager so that it can create the projectile sprite.  The sprite manager should be able to do the rest, storing the sprite in some structure and iterating over that structure calling each sprite's update method each frame. 

 

Also you should probably store the player's direction in a variable. If you can only face right or left, you can use a boolean. 



#7 LordRhys   Members   -  Reputation: 354

Like
0Likes
Like

Posted 04 June 2013 - 07:17 AM

For a perfecty example of what you want check out XNA-40-Game-Development-by-Example-Beginners-Guide, the second example project uses a ShotManager class which manageds the bullets being shot by the Player and the author uses it in the next project to manage shots by the player and by enemies.

#8 DishSoap   Members   -  Reputation: 360

Like
0Likes
Like

Posted 04 June 2013 - 03:20 PM

For projectiles you are going to want to have an acceleration, velocity and position vector. I would argue for all physical objects in your world you will want these three vectors and integrate them according to some law such as Euler or RK4.

 

When I create my games I tend to have some base class, "MoveableObject" or PhysicalObject, that simply holds these three vectors and is responsible for integrating them.

 

class MoveableObject
{
public:
    integrate(dt)
    {
        position += velocity * dt;
        velocity += velocity + acceleration * dt;
    };

    Vector2 position;
    Vector2 velocity;
    Vector2 acceleration;
};

 

If you choose to add gravity to your projectile all you'd have to do is set the acceleration vector accordingly.

 

This way every moving object in your world has some base object you can access these variables by. A projectile would have this as a base class and would simply be integrated just like any other moving object in your would.

 

Here is a great article on it! http://gafferongames.com/game-physics/integration-basics/


Edited by DishSoap, 04 June 2013 - 03:21 PM.





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS