2
votes

(Cross post from Gamedevs)

I'm working with Monogame to do a 2d sprite engine. I've gotten it work pretty well where I can move lots of sprites around the screen with the effects and positions that I want.

Last night I tried to add a feature and I can't quite get it to work right. I'm trying to create permanent trails that the moving sprites can leave behind. So I have a mostly transparent PNG with some white lines on it called "streak". The idea is that I set up a new Texture2D surface (called streakoverlay) and I draw the streaks on to it.

I switch back to the back buffer and draw: The background, the streakoverlay, and finally the sprite on top of it. The streaks should build up over time. It almost works, but the trouble I have is that streakOverlay seems to clear itself every time. How I'd like it to behave would be the same behaviour as having the graphics display without this line GraphicsDevice.Clear(Color.White); - everything would just pile up in it.

Instead it resets back to the Purple transparent color that is the default for that texture. Any suggestions? Here's the core piece of the rendering engine:

GraphicsDeviceManager graphics;
RenderTarget2D streakOverlay;
SpriteBatch spriteBatch;

private Texture2D bkg;
private Texture2D prototype;
private Texture2D streak;

//Initialize 
graphics = new GraphicsDeviceManager(this);
GraphicsDevice.Clear(Color.Transparent);
streakOverlay = new RenderTarget2D(GraphicsDevice, 200,200);

//Load Content
bkg = Content.Load<Texture2D>("bkg"); //Background image
prototype = Content.Load<Texture2D>("prototype"); //Prototype sprite that moves around
streak = Content.Load<Texture2D>("blueStreak"); //Trails being left by Prototype sprite

graphics.GraphicsDevice.SetRenderTarget(streakOverlay); 
GraphicsDevice.Clear(Color.Transparent); //Attempt to make the streakoverlay is fully transparent.
graphics.GraphicsDevice.SetRenderTarget(null);

//Draw
Random r = new Random();
graphics.GraphicsDevice.SetRenderTarget(streakOverlay); //Switch to drawing to the streakoverlay

spriteBatch.Begin();
//Draw some streaks that should accumulate
spriteBatch.Draw(streak, new Vector2(r.Next(0, 200), r.Next(0, 200)), null, Color.White, 0f, new Vector2(25, 25), 1f, SpriteEffects.None, 1f);
spriteBatch.End();

//Switch back to drawing on the back buffer.
graphics.GraphicsDevice.SetRenderTarget(null);

spriteBatch.Begin();
spriteBatch.Draw(bkg, new Rectangle(0, 0, 2000, 2000), Color.White);    //Draw our background
spriteBatch.Draw(streakOverlay, new Vector2(0, 0), Color.White); //Put the overlay on top of it
spriteBatch.Draw(prototype, new Vector2(_spritePrototype.getX, _spritePrototype.getY), null, Color.White, DegreeToRadian(rotationSprite), new Vector2(25, 25), .5f, SpriteEffects.None, 0f); //Draw the sprite that's moving around.
spriteBatch.End();

base.Draw(gameTime);
1

1 Answers

2
votes

You need to use the extended constructor for RenderTarget2D that takes 4 parameters and specify PreserveContents. The assumption is that render targets are often reused and so when it is set it gets cleared automatically unless this flag is set.