Dynamically resize texture on the fly - c#

I'm using RenderTarget2D to draw my map to before rendering it to the screen as it changes very rarely and the map itself is made up of a LOT of very small tiles. So rather than drawing all tiles to the buffer every frame, I'm drawing them to a RenderTarget2D which I then draw to the buffer.
My question is in regards to the RenderTarget2D "texture". If the player was to resize the window, which I want to enable at least to play with a little, what is the proper way to modify the RenderTarget2D object in regards to dimensions?
At the moment I'm just recreating the object anytime the window is resized which may be fine, but I figured I should ask to be safe I'm not missing something simpler.
texMap = new RenderTarget2D(GraphicsDevice, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height);

There is no way to resize a render target after it's been created. Call Dispose() on the existing render target, if it exists, and then create a new one.

Related

Sprites blurry when enlarged

In XNA I am trying to create a game using old style Super Mario sprites, but if I try to make them bigger, they get very blurry. I have tried saving the PNG sprites as nearest neighbor, bicubic, and bilinear in photoshop, but they all appear equally blurry. I have also tried compressing the PNG online, which also didn't help.
My knowledge of XNA is somewhat basic, so unless your answer is code I can simply copy paste into my 'main' class, please explain how to use it.
In your draw-function you should only need to change one row of code.
Where you call spritebatch.Begin(); instead call
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.PointClamp, DepthStencilState.Default, RasterizerState.CullCounterClockwise);
This will set your "GraphicsDevice" to render textures without interpolating the colors between whole pixels when the sprites get zoomed.
One other thing that you could do is to use a rendertarget with the resolution you want the game to "emulate" , draw everything on the rendertarget and finally draw that to the screen.
This is a bit out of the scope of this question but it is ideal if you want to create a genuine oldschool experience.

Scaling a Texture2D without Draw()

I am trying to scale a Texture2D without using the Draw() method. The reason being
I am not going to be drawing the Texture2D until I perform further manipulations. I would be saving the Texture2D as a field.
I don't know what kind of image manipulations you want to perform on your image but I highly recommend not performing scaling before you do those manipulations. If there is any way possible to do so, manipulate your image before you scale it. Xna has already taken care of all the dirty work of scaling for you.
If you want to perform specific pixel operations, Texture2D.GetData will work for you but only in small quantities. If you're doing this to hundreds of images, you'll slow down your game drastically. I highly recommend doing some post-processing effects using a customized Effect.
Edit: I just thought of a way to do this the way you want to do it. What you can do is draw your scaled texture to a RenderTarget2D object and then get the color data from it and manipulate the data however you'd like. An example below:
RenderTarget2D renderTarget = new RenderTarget2D(GraphicsDevice, textureWidth, textureHeight, false, GraphicsDevice.PresentationParameters.BackBufferFormat, DepthFormat.Depth24);
GraphicsDevice.SetRenderTarget(renderTarget);
spriteBatch.Begin();
//scale and draw your texture here
spriteBatch.End();
GraphicsDevice.SetRenderTarget(null);
This draws the texture to the render target which you can then draw later just like you would any other texture:
spriteBatch.Draw(renderTarget, new Rectangle(), Color.White);
You can use renderTarget.GetData to get color data just like you would with Texture2D and manipulate it to your liking.
The first thing I can think is to use Texture2D.GetData and store your texture in an array of Color, uint or whatever, and then perform your scale.
This will require some basic computer graphics knowledge, and I don't think that's the better way to do it.

How to delete an image from Graphics

Suppose I use DrawImage a few times to draw a bunch of images.
e.Graphics.DrawImage(newImage, destRect);
How can I delete a specific image from the Graphics paper that I drew it on?
Is there a specific function I can use for deletion?
I have tried dispose and Rectangle.Empty, but they don't actually delete the image I already drew on the paper.
First of all, there's no concept of "delete an object" in GDI+ Graphics. You have to redraw the the entire client area in every frame. You should keep a list of objects and their states in memory and redraw the entire surface in every frame. Beware though, this can lead to flickers and not-so-smooth user experience. Here are a few tips to avoid these:
Make sure your Form or UserControl has its DoubleBuffered property set to True. This will result in a far smoother animation than otherwise.
NEVER EVER call CreateGraphics() to get a reference to the Graphics object in your drawing loop. Update your list of objects and states in your loop and then call Invalidate() on your Control/Form and do the drawing process in Paint event.
One overload of Invalidate() allows you to specify the rectangle that needs to be invalidated (redrawn). You can pass a "safe" rectangle around your bouncing ball's current position (say 20 pixels wider/taller than the ball size) as agrument and then draw only that portion in your Paint event.
To further increase performance you can keep auxilary information such as scores, player names etc. outside the actual "game board" and use normal labels/textboxes for them instead of drawing.
krikara, what you should do is:
Keep track of all the bricks in a list
When the ball hits a brick, remove that brick from the list
Every frame, you must redraw everything from scratch. This includes the ball, the paddle and the list of bricks (and whatever else you need, like score, etc.)
Hope this clears up whatever confusion you had.

Optimal 2D Tile rendering in C#

So I'm making a simple 2D Sidescrolling game in C# however I've found that using Graphics.drawImage doesn't particularly allow me to update the tiles as I wish. For example, I tell it to draw the image and it stays where I tell it to be. I want to be able to move the entire scene left to right. This would be easier if I had to use a for loop or something and define it's position every time it draws the image.
This may be confusing and I'm certain there's a way of doing it, I just don't know how.
So my question to you is: How can I control the positioning of each rectangle drew on a form so that I can scroll the entire scene to the left when I wish?
I'm certainly no game/graphics expert, so take this with a grain of salt.
A couple things spring to mind.
First, you could pre-render the entire level as one bitmap, then just paint the relevent portion into your picturebox.
Second, the Graphics class has a Transforms property (I may have the name wrong). You could add a linear transformation to the graphics object so the painting coordinates of your tiles wouldnt change, but the graphics object would slide, or I think the graphics term is "translate" the output en-masse.

Erase part of RenderTarget when drawing primitives?

I'm creating a paint like application using XNA.
I have a render target which acts as a canvas. When the user draws something I draw corresponding triangles using DrawUserPrimitives and triangle strips to make lines and other curves.
I want to implement an eraser in the application, so that the user can erase the triangles from the texture. I've used OpenGL in the past and there I would just use a blend function like so: glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
How would I do this in XNA? I tried setting the GraphicsDevice blend mode to AlphaBlend, Additive, etc.. but it did not work. Any ideas?
If you change your code to use a Texture2D instead of a RenderTarget2D, you can use RenderTarget2D.GetTexture() to get the pixel data from the RenderTarget2D.
Of course, there will probably be a performance hit, but if you can optimize the code in a way that cuts down on the number of times this is done, like temporarily drawing the background color instead of actually erasing, and then iterating through the pixels after the mouse is released, you could make it work.
There may be a better way, but I couldn't find it.

Categories

Resources