[XNA] How to ? (remove sprites)

Started by
8 comments, last by remigius 15 years, 11 months ago
First of all, sory i double posted, but im not sure where to put this question... Hi all, i've got a question regarding to a 2d game im making... i've got this sprite which is "killed" at some point in my code, but i cant seem to find a way to remove the prite from the spritebatch... (im using XNA refresh 1.0) if any1 can help me, its gladly appreciated :) if you need more info, feel free to ask and ill post it :) Thanks in advance, Dieseltjuh.
-Please rate me if you find my replies useful.
Advertisement
What do you mean by "remove" the sprite? A sprite won't be drawn by the sprite batch unless you add it with SpriteBatch.Draw in between every Begin/End pair.
I think the SpriteBatch implementation is a bit counter intuitive myself because you would think you would have a Sprite and just draw it but you don't. What you have got is a Spritebatch that has a draw method which takes among other parameters a Texture2D which is the image you saee on screen.

There are a number of ways to get round this.

1) wrap the SpriteBatch draw statement in an if statement:

// at top of game classbool spriteXshoulddraw;// in draw of game classif(spriteXshoulddraw){SpriteBatchObject.Draw(...);}


2) write a sprite class.

class sprite{   public drawMe;   public Texture2D yourSpriteImage;   // other SpriteBatch.Draw parameters here}


Used like this:

// in game classsprite spriteObj;// in LoadContent of game class initialise the sprite, three "." would be rest//of Draw parameters stored in spriteObj;spriteObj = new sprite(yourSpriteImage,...)// in draw method of game class.if(spriteObj.drawMe){spritebatchObj.Draw(spriteObj.yourSpriteImage,...);}
"I have more fingers in more pies than a leper at a bakery!"
well, i have the sprite loaded in the spritebatch, and loaded.

but at some point, the sprite leaves the screen, and then it needs to be removed.
i read something bout making the image 100% opacity. but i cant seem to get that working :/
-Please rate me if you find my replies useful.
SpriteBatch has 7 overloaded Draw methods that means 7 different methods all called draw that each take a different set of parameters. That being said can you see the tint parameter as a Vector4 or Color object?

The tint parameter is the thing that changes the opacity of the sprite and its colouration. Opacity is changed using the "a" variable of the Color type or the "w" variable of the Vector4 type.

Some form of if statement or wrapper class mentioned in my previous post would be needed to change the tint value by the desired amount when you want it to occur.

"I have more fingers in more pies than a leper at a bakery!"
Quote:Original post by Dieseltjuh
well, i have the sprite loaded in the spritebatch, and loaded.


I think we're having a good bit of miscommunication here [smile]

What do you mean by 'having the sprite loaded in the spritebatch'? As MJP and fanaticlatic have pointed out, the spritebatch is only a means to draw a Texture to the current rendertarget (ie. your screen) and doesn't 'load sprites into it'. If you could clarify what you mean by this, we might be able to provide some more useful hints.

Perhaps it helps to point out that an XNA game runs through the Draw code each frame (at some 60 frames/sec), so drawing a texture to a spritebatch once doesn't 'load it onto it' or make it a permanent feature on your screen. XNA starts each frame by clearing the screen, so you have to draw your texture to the spritebatch each frame to keep it visible. If you don't draw it, it just won't be there. The point being, your own code should handle which textures get drawn onto the spritebatch and remove them if necessary.

Typically you'd use some list (an array or ArrayList) with Textures that all get drawn to the spritebatch each frame. Then you could loop over all your Textures in the Update() method and remove the ones that should be removed from your list. You could wrap the textures in some Sprite class of your own like fanaticlatic proposes, to store things like position etc in the list as well.
Rim van Wersch [ MDXInfo ] [ XNAInfo ] [ YouTube ] - Do yourself a favor and bookmark this excellent free online D3D/shader book!
well, i use the LoadGraphicsContent method to load all my textures into texture2d variables (which i declared at the top of the page) as shown below.


protected override void LoadGraphicsContent(bool loadAllContent)
{
if (loadAllContent)
{
foregroundBatch = new SpriteBatch(graphics.GraphicsDevice);
fTexture = content.Load<Texture2D>("sprites/fsprite");
menuTexture = content.Load<Texture2D>("sprites/menu");
mTexture = content.Load<Texture2D>("sprites/m placeholder");
instructionsTexture = content.Load<Texture2D>("sprites/instructions placeholder");
wTexture = content.Load<Texture2D>("sprites/W");
w2Texture = content.Load<Texture2D>("sprites/W2");
choiceTexture = content.Load<Texture2D>("sprites/y");
}
}


and then in my draw() method i use:

foregroundBatch.Begin();
foregroundBatch.Draw(menuTexture, defaultPosition, Color.White);
foregroundBatch.Draw(choiceTexture, menuRectangle, Color.Yellow);
foregroundBatch.End();
-Please rate me if you find my replies useful.
I think your best option is to go with what fanaticlatic said - make a seperate class for your sprites that have a flag that indicates if they are still alive or not. Then check against this flag when drawing / collision checking your sprites. An example might look like this:

Sprite class:
public class Sprite{    // Field indicating sprites status - initialised to false.    private bool _alive;    // Field to hold the 2d texture represented by this sprite.    private Texture2D _spriteTexture;    // Field to contain the sprites position.    private Vector2 _position;    // Field to hold the color used when drawing the sprite.    private Color _drawColor;    // Public property used to set / get the alive flag.    public bool Alive    {        set{ _alive = value; }        get{ return _alive; }    }    // Public property used to set / get the 2D texture.    public Texture2D SpriteTexture    {        set{ _spriteTexture = value; }        get{ return _spriteTexture; }    }    // Public property used to set / get the position.    public bool Vector2 Position    {        set{ _position = value; }        get{ return _position; }    }    // Public property used to set / get the draw color.    public Color DrawColor    {        set{ _drawColor = value; }        get{ return _drawColor; }    }    // Default constructor.    public Sprite()    {    }    // Constructor used to setup the object.    public Sprite(bool alive, Texture2D spriteTexture, Vector2 position, Color drawColor)    {        // Set the properties        this.Alive = alive;        this.SpriteTexture = spriteTexture;        this.Position = position;        this.DrawColor = drawColor;    }}


A sample of what the main code may look like:
// Create a list of spritesprivate List<Sprite> _listOfSprites = new List<Sprite>();// Create some sprites (1 done here as example)private Sprite _fTexture;// Repeat above for all sprites...// Do your content loading and setting up of your sprite listprotected override void LoadGraphicsContent(bool loadAllContent){    if (loadAllContent)    {        // Setup the sprite batch        foregroundBatch = new SpriteBatch(graphics.GraphicsDevice);        // Setup the fTexture sprite to be alive and give it a texture        _fTexture = new Sprite(true, content.Load<Texture2D>("sprites/fsprite"), new Vector2(0,0), Color.White);        // Add the sprite to the list        _listOfSprites.Add(_fTexture);        // Repeat above for all sprites...    } }// Render methodprivate void RenderSprites(){    // Begin    foregroundBatch.Begin();    // Go through your list of sprites    foreach(Sprite s in _listOfSprites)    {        // Check if the sprite is still alive        if(s.Alive)        {            // Draw the sprite            foregroundBatch.Draw(s.SpriteTexture, s.Position, s.DrawColor);        }    }    // End    foregroundBatch.End();}


See if you can implement something similar to the above, it should help you overcome your problem.

Cheers,

James
Really thanks to every1`who replyd,

i made a boolean variable isKilled and instanciate it to false, then when it moves off the screen i set isKilled to true. Then in the draw method i used an if statement, to only draw the textute if isKilled is false, and it works perfectly :)

now i need to complete my project in a week and some people mentioned to split it up into seperate classes, but should i still do this ? (i think it gives me more work, and i also need that time completing the project)

also as others mentioned, future projects i will make in XNA 2.0 thanks for the tips on that :)

I got one last question i ran into and that's how should i wait for a period of time? (for example i want to spawn 2 enemy's, im able to, but i want them to spawn 5 seconds after eachother)
i tried using a timer, but i failed :x and i tried to use a game loop to add i until 5000 and then draw the other sprite, but this is unreliable i think because it will be depentant on processor speed then and not realtime.

Thanks to all that replyed!
-Please rate me if you find my replies useful.
Quote:now i need to complete my project in a week and some people mentioned to split it up into seperate classes, but should i still do this ? (i think it gives me more work, and i also need that time completing the project)


It would be more elegant design to do so, but I think it's best you stay on your current track. Not only considering your time limit, but it should also prove valuable material to reflect on once you do start working with classes. This way the advantages of classes will be clearer to you then, instead of implementing them now just because you're told it's the 'right thing'.

Quote:i tried using a timer, but i failed :x and i tried to use a game loop to add i until 5000 and then draw the other sprite, but this is unreliable i think because it will be depentant on processor speed then and not realtime.


That's correct (unless you use fixed timesteps with VSyncing, but forget about that for now [wink]).

XNA makes it easy to work with time though, since every Draw and Update call you get all the time info you'd want. For delays, you could use the gameTime.TotalGameTime.TotalSeconds to see how long ago you spawned anything. When you do spawn something, you store this 'spawntime' in a local variable and use it to check if an x number of seconds has passed since the last spawn. Something like this:

[source lang=csharp]private double lastSpawnTime = 0;private double spawnInterval = 5; // in seconds, value can be anything you likeprotected override void Update(GameTime gameTime){    // Other update code here    double currentGameTime = gameTime.TotalGameTime.TotalSeconds;    // Note the greather than (>) instead of equals (==). Using equals     // is a common pitfall, since floating point inaccuracy basically     // guarantees that the comparants won't ever be equal     if ((currentGameTime - lastSpawnTime) > spawnInterval)    {        lastSpawnTime = currentGameTime;        // add your spawning code here        CallMethodToDoSpawning();    }    base.Update(gameTime);}
Rim van Wersch [ MDXInfo ] [ XNAInfo ] [ YouTube ] - Do yourself a favor and bookmark this excellent free online D3D/shader book!

This topic is closed to new replies.

Advertisement