I am making a small game as sort of a test project, nothing major. I just started and am working on the graphics piece, but I'm not sure the best way to draw the graphics to the screen.
It is going to be sort of like the old Zelda, so pretty simple using bitmaps and such. I started thinking that I could just paint to a Picture Box control using Drawing.Graphics with the Handle from the control, but this seems cumbersome. I'm also not sure if I can use double buffering with this method either.
I looked at XNA, but for now I wanted to use a simple method to display everything.
So, my question. Using the current C# windows controls and framework, what is the best approach to displaying game graphics (i.e. Picture Box, build a custom control, etc.)
EDIT:
I will add how I am currently drawing to the picture box. I have a Tile object that just contains the pixels for the tile ( List< List< Color>> texture; ), nothing more for simplicity. I then draw that to the pic box by iterating through the pixels and using the FillRectangle method using a brush with the current pixel color and the size specified by a scale variable:
int scale = 5;
for (int i = 0; i < texture.Width;)
{
for (int j = 0; j < texture.Height; ++j)
{
int x = i * scale;
int y = j * scale;
picBox.FillRectangle(new SolidBrush(currentPixelColor), new Rectangle(x, y, scale, scale));
}
}
Yah, pretty cumbersome. Any suggestions or comments are appreciated.
I would recommend, that you take another look at XNA and try a few samples. It is really simple to make simple games with XNA as long as you stick with 2D. The framework does an excellent job at wrapping all the details in a easy to understand flow, where you basically fill in the blanks so to speak.
I did a complete (but very simple) Xbox game for my son in just 8 hours without little previous experience.
If you move to 3D things become more complex, as you have to understand various view models, shaders and so forth, but for 2D it is really simple to get started.
Another advantage of 2D is that the required tools are easier to get. I did all the graphics using Photoshop, the sounds were MP3s and voices I recorded using the Windows recorder. For 3D you need complex tools for building and exporting models and so forth.
I honestly believe XNA is by far one of the simplest game design frameworks I've used. Aside from that you could utilize WPF to draw objects on screen.
First I strongly recommend using XNA or DirectX for game development...
However, if you do not want XNA nor DirectX help.... then you will be forced to use .Net GDI+ painting tools.....
By this way, you can draw points, lines, circles, rectangles, arcs, bitmaps, texts and many more by GDI+ (that all is -of course- available in C# and .Net...)
You may make a new simple control (or use an existing one such as image box or the form itself !), then you will have to override its OnPaint(PaintEventArgs e) function... Then you will use e.Graphics to draw whatever you want...
Example:
Simple Tetris Game Tutorial in C#
EDIT:
Using a GDI+ to draw pixel by pixel picture is quite a performance drop!!
Better is to draw shapes yourself (circles,.. etc)
Related
First of all, I posted this question here and not at game development because I just started my project and this question is not really about XNA or Monogame libraries.
So, i am trying to make my game compatible with every single screen type.
there are two aspects i need to pay attention to- ratio, and pixels size.
before i'm creating any graphics for my game, ill need to know the dimensions
of every single object in my game,(player,background, etc) and get the right dimensions to match the screen ratio, and change with it as well.
I searched the web looking for XNA/Monogame tutorials that show how to do that and i didn't find a single one. I tried basic fullscreen methods. but as you know, the object stand still and they wont move with the window. And as I mentioned before I need them to move and change size with the window to make my game compatible with every single screen type. (ratio and pixels(inch/cm))
I think the term you're looking for is resolution independence. I wrote a tutorial about it on my blog a while ago.
The way we do it in MonoGame.Extended is by scaling the entire sprite batch using a transformation matrix passed into the SpriteBatch.Begin method. We call them viewport adapters:
_spriteBatch.Begin(transformMatrix: _viewportAdapter.GetScaleMatrix());
What this does is transform everything rendered by a specified scale matrix.
The way it works is that you decide on what the virtual resoultion of your game and position everything relative to that. During the draw call you scale the graphics to match the actual resolution of your device.
For example, you might decide that your virtual resolution is 800x480 but you're rendering to an actual screen size of 1024x768 so the scale would be something like 1.28 x 1.6. Make sense? You can calculate a simple scale matrix like so:
var scaleX = (float)ActualWidth / VirtualWidth;
var scaleY = (float)ActualHeight / VirtualHeight;
var matrix = Matrix.CreateScale(scaleX, scaleY, 1.0f);
_spriteBatch.Begin(transformMatrix: matrix);
This will work as a basic approach. The only other thing you really need to know is that when you're dealing with actual screen coordinates, like the mouse position for example, you'll need to reverse the scaling back to your virtual resolution:
var invertedMatrix = Matrix.Invert(matrix);
virtualMousePosition = Vector2.Transform(new Vector2(x, y), invertedMatrix);
That's it for the basics. Of course, you can also get more sophisticated with letterboxing and pillar boxing approaches like I've described on my blog.
Edit: Bad angle picture was due to Depth Testing. Still need the 'right' way to do 3d text rendering though!
I got 2D text rendering in OpenTK working. It's very simple, I use .NET Graphics class methods to draw a string to Bitmap, which I can load into GPU via OpenTK. Ok great, but how about 3D?
I'm thinking about this in terms of a cylinder. What is a cylinder? It's just a circle stretched out over a certain height. That's EXACTLY what I want to do here! I researched a bunch...but surprisingly there isn't all that much info readily available IMO for such a basic task.
Here's what I've tried:
1) Rendering the bitmap 100 times from Z = 0.0f to 1.0f. This actually works pretty well! For certain rotations anyway.
2) Drawing 16x16x16 Voxels (well, I think I'm drawing voxels). Basically the idea is, use the typical GL.TexCoord3 and GL.Vertex3 methods for drawing the SURFACE of a cube, but because we are drawing so freakin many of them, I figured it would actually give depth to my text. It sort of does, but the results are actually worse than attempt 1.
I want to get this working with a really simple solution, if one exists. I'm using Immediate mode, and if possible I'd like to keep using that.
This is what solution 1 looks like at a good angle:
Bad Angle:
I know that my method is inherently flawed because these bitmaps dont actually have a depth when I draw them, which is why at some critical angles either the text becomes flat looking, or disappears from view.
I am making a WPF program with the possibility to modify data graphically in 3D. In order to give the user the option to select multiple graphical objects at the same time, I want to implement a selection rectangle. (Just like the one in windows explorer.) A common functionality in programs like this one is to have 2 different functions for the selection rectangle, and that the user can somehow choose which of the methods should be used.
Any object that is partially or completely inside the rectangle is selected.
Only objects that are completely inside the rectangle are selected.
The 2nd method is straight forward by using the bounding box of each object, and check if it is inside the rectangle. The 1st one on the other hand, seems to be quite some work. All my graphical objects are complicated 3D figures, and can be rotated by the user in any way. At the moment I am unable to find any other way than checking if any of the triangles in the mesh of any of the objects cross my 2D rectangle, and that can be quite time consuming.
I have little experience with WPF 3D, but I have done this before in OpenGL. Then I could tell OpenGL to draw a specific area of the screen, and the collect a list of objects that was visible in the specific area. All I needed to get the functionality I wanted was about 5 lines of code.
I guess my question is this:
Is there a way to do this with WPF 3D, similar to the OpenGL approach?
If not, is there any other smart way to find all objects (Visual3D) in a viewport that is partially behind a 2D rectangle?
I refuse to believe I am the only one with this kind of problem, so I hope a clever mind can point me in the right direction.
Regards,
Sverre
Thank you for your answer!
The 2D-rectangle is just in front of the camera and extending infinitely forward. I want to get any object that is partially or completely inside that frustum.
The camera we are using is an orthographic or perspective projection camera (System.Windows.Media.Media3D.ProjectionCamera). The reason we are not using the matrix camera is that we are using a 3rd party tool that does not support the matrix camera. But I am sure there is a way to get the matrix from a projection camera as well, so that is hopefully not the problem.
In theory your solution sounds like just what we need, but I am not sure how to proceed. Do you have any links to sample-code, or can you give some more hints on how to actually implement this?
Btw: Since we are working with WPF, we do not have direct access to DirectX. At least that’s what we have concluded after some research. You mention use of the z-buffer, which we haven’t been able to access through WPF. If you know a way to access the z-buffer, it’s greatly appreciated! This is of-topic, but we have struggled to disable the z-buffer for some time, but have given up…
Best regards,
Sverre
Is your intersection region a 2d rectangle or a frustrum based at a 2d rectangle and extending infinitely forward (or perhaps to some clipping limit)? If it can be construed as a viewing frustrum, then you can leverage the existing capabilities of the graphics system to render the scene using a Camera View and Projection that corresponds to your originating rectangle, with all lighting and shading disabled and colors chosen specifically to 'tag' the different objects in your scene. This means you can use the graphics hardware to perform the clipping/projection as a 'rendering' operation, then simply enumerate the pixel values as 'tags' to determine the objects present in the rectangular view.
If you need to restrict selection to an actual 2d slice (or a very shallow frustrum), you can use the Z-buffer (if you can get access to it) to exclude tagged pixels that are outside the Z range of your desired selection frustrum.
The nice thing about this approach is that you probably already have the Camera matrix (it's the same matrix used for your window for selection) and only need to change the Projection matrix to be a sub-set of the viewing window.
A 'smart' way would be to transform the rectangle into a box using the Camera's matrix
And then do a intersection of all the objects and the box.
I am writing a map editing program for a 2D game using XNA. To create a Texture2D for all of the tiles that a map requires takes too long.
Are there any alternatives to using textures for drawing with XNA?
I attempted to create just one texture per tile set instead of a texture for every tile in a tile set, but there is a limit to the size of textures and I could not fit all the tiles of a tile set into one texture.
Currently the program contains all the would-be textures in memory as Bitmap objects. Is there a way to simply draw a Bitmap object to the screen in XNA? I have searched but I cannot find any information on this. This approach would avoid having to create textures altogether, however any tinting or effects I would have to do to the bitmap directly.
Is there any reason you haven't considered loading the image one time and then passing in x and y offset coordinates to the pixel shader?
You would basically set the C# up like this:
myGraphicsDevice.Textures[0] = whateverYourGiantMapTextureIs;
foreach(MapChunk chunk in mapChunks) {
myShader.Effect.Parameters["xOffset"] = chunk.XOffset;
myShader.Effect.Parameters["yOffset"] = chunk.YOffset;
myGraphicsDevice.DrawIndexedPrimitives( your chunk drawing code here );
}
And then the shader code like this:
float4x4 World;
float4x4 View;
float4x4 Projection;
float xOffset;
float yOffset;
sampler TextureSampler;
struct VS_INPUT {
float4 Position : POSITION0;
float4 Color : COLOR0;
};
VS_INPUT Transform(VS_INPUT Input) {
VS_INPUT Output;
float4 worldPosition = mul(Input.Position, World);
float4 viewPosition = mul(worldPosition, View);
Output.Position = mul(viewPosition, Projection);
Output.Color = Input.Color;
return Output;
}
float4 ColorTexture(VS_INPUT Input) : COLOR0{
return Input.Color.rgba * tex2D(TextureSampler, float2(xOffset, yOffset));
}
technique TransformColorTexture {
pass P0 {
VertexShader = compile vs_2_0 Transform();
PixelShader = compile ps_2_0 ColorTexture();
}
}
The shader code might need some fitting into your existing code but otherwise it should do the trick.
Using one texture per tile is not very efficient. Especially since it means you cannot do batching (in any real sense).
If you NEED to have them as separate textures in your content-project for some reason (easier to edit one tile, etc), you can quite easily compile them into tilemaps after loading.
How you do this is basicly:
1: Load a number of tiles (lets say 40 32*32 tiles for now)
2: Figure out a nice texture-size for the tilemap:
square root of 40 is 6.something, so we round up to 7. 7*32 is 224, which is nice, but 256 is nicer, so lets make the texture 256x256. (you can make code that figures out this on the fly)
3: Create a Rendertarget2D which is the desired size.
4: Activate rendertarget.
5: Render tiles on rendertarget:
int x, y = 0;
foreach (var tile in allTiles)
{
RenderTile(tile, x*32, y*32);
x++;
if (x >= 8)
{
x = 0;
y++;
}
}
To betch-render you have a vertex-buffer with 4 * 40 vertices. each set of 4 has a value indicating index of the quad it belongs to (0,1,2,etc...). In your shader you have an array of matrixes[40] for position of the tiles, as well as an array of tileIndex (int[40]) for knowing which tile to render from the tilemap.
I'm sorry, but I don't have time to write all the shader-code right now :s
An other trick I have used in our games is pre-rendering the level onto large tiles (640x360), which reduces the number of draw-calls by a great deal, especially when dealing with 5+ layers of tiles from different tilesets. Only thing is that it does not work with dynamic tiles (animated tiles, etc), but you can mark those and render them normally if you want...
Since you need to use a custom image format, if you want (for speed) you can attempt to write custom content pipeline importers and processors for XNA ( http://msdn.microsoft.com/en-us/library/bb447754.aspx ), but this may be overkill for what you need to do.
I see you want to design the GUI as easily as possible, even if these issues force you to use a language like C++ so you can use DirectX. In Visual C++ you should still be able to take advantage of visual Windows Forms layout if you are using Visual Studio.
Unfortunately, as far as I know, there is no way to directly draw a bitmap to the screen in XNA; it requires that everything is mapped to the Texture objects, which are by default buffered to the graphics card. It sounds like you're talking about a lot of tiles, though, if they won't all fit on the maximum allowed texture (I can't remember whether that was 1024 or 4096 square...) - have you tried having an unbuffered texture for speed purposes? Another alternative would be to lazy-load your tilesets into textures so the user didn't have to wait for them all to load - for an editor, using a bright pink fallback color is usually acceptable while it loads.
Also, is there anything inherently required to write your tool in XNA? Since it sounds like you're writing the tool separately from the game engine itself, you may find some very acceptable solutions in WPF, including drawing directly from BitmapSources and some utilities for your UI.
Assuming all the tiles that a map require existing images that are simply placing on a screen to lay out a tile map? Or are you making images in this map editor and want to save them out?
I read this, and your other post about textures - If they are all ready defined images that you want to use in your game couldnt you just include them in the content folder and reference them there? This allows XNA to compile the textures in the xnb format and you shouldn't have the problems you are explaining.
However if we are talking completely dynamic - or you are crafting one big image from the layout of the tiles (instead of doing something like a tile map) then I am not sure how to approach the issue.
If multiple tiles use the same texture, it will be enough to load it just once.
If the user includes textures in some file format, you could automatically convert it to a texture/image format which is faster for your needs.
Are you trying draw them all using a single thread of execution?
Try multi-threading your game. Threading in C# is quite easy and is supported by XNA.
Instead of looking at your screen as a whole, try splitting it into two (or more) portions. You may need to re-write the function you're using to Draw (I sure hope you didn't just dump everything directly in your Draw() method!!) to take in coordinates setting the boundaries of your draw regions.
I'm quite new to the world of 2D-Engines. I figured out how to load images and display those as sprites and stuff, but theres one question that bugs me.
For instance, when a "rocket" hits an object it will deal damage to it and leave a crater behind. I'd like to have the crater shown on that object. That would require "skipping" some of the pixels of that image when rendering, doesn't it?
My question is, how would you do such a thing? What data strcture would you use to save this? How to display a "broken" sprite?
Create a sprite sheet.
This will contain all the spirites your object, in this case the rocket. Some of these images would be of the rocket smashing into many pieces, fire etc...
Then when your object hits, you play the collision animation. Your method would technically work, but it's overkill. Using a sprite sheet is simple, rather than drawing a massive image, you just draw a portion of the sheet, and to play the animation increment in the X an Y axis of the sheet. This naturally requires the sheet to be layed out even, but it's not too much work.
For some situations, you can simply draw another sprite on top of the original sprite. Alternatively, you can switch between different sprites depending on the state of the object.
I see you have tagged this with XNA, so assume that is your API (though this answer could well be applied to any OpenGL/D3d approach with appropriate calls). If you want to do this in an elegant fashion, I suggest using a temporary RenderState. You would switch to the new RenderState and draw your original background texture, then draw crater sprites over the top (you can modify the AlphaSourceBlend and AlphaDestinationBlend properties of the RenderState to create the subtractive effect you are looking for).
Once you have finished drawing, you can retrieve the RenderState as a texture easily using the GetTexture() function.
Keep in mind that if you are changing the blend modes, your SpriteBatch should be performing in the "immediate" mode (I forget the XNA term, but the one where it doesn't do ordering of sprites for efficiency) else it will be reset unexpectedly.
View this: http://www.riemers.net/eng/Tutorials/XNA/Csharp/Series2D/Adding_craters.php
Slow, but probably fast enough.
public static void Fill(this Texture2D t, Func<int, int, Color> perPixel)
{
var data = new Color[t.Height * t.Width];
for (int y = 0; y < t.Height; y++)
for (int x = 0; x < t.Width; x++)
{
data[x + (y * t.Width)] = perPixel(x, y);
}
t.SetData(data);
}
I was working on something like this on a mobile Java game, a worms/scorched earth clone (actually based on GunBound).
You don't "skip" the pixels in order to leave a crater. You change the pixels in your planet's bitmap, so the crater is now a permanent part of your planet. I assume you know all about bitmaps, blitting transparent, and hit testing.
To create a crater I used a circle-fill algorithm and filled the "explosion area" with the background or transparent color.
So when doing hit-testing you have to do it twice. A bounding-box hit test for speed, then a per-pixel hit test when then bounding boxes overlap.