Sign in to follow this  
Dieseltjuh

[XNA] How to ? (remove sprites)

Recommended Posts

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.

Share this post


Link to post
Share on other sites
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 class
bool spriteXshoulddraw;

// in draw of game class
if(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 class
sprite 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,...);
}

Share this post


Link to post
Share on other sites
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 :/

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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();

Share this post


Link to post
Share on other sites
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 sprites
private 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 list
protected 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 method
private 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

Share this post


Link to post
Share on other sites
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!

Share this post


Link to post
Share on other sites
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 like

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




Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this