How to approach drawing shapes in C# to make a tetris clone? - c#

I would first like to note that I am NOT using any XNA or LINQ in this small project. Basically, I want to make a clone of Tetris using C# windows application. I have already drawn out my grid, my picturebox size 250x500, making each square block 25 pixels x 25 pixels.
Now, I am an amateur at drawing shapes. I can draw lines and rectangles, circles, ellipses, and polygons on a grid, and I can fill them in with a color, etc. That's it really. I cannot do much else with drawing. Basic shapes in other words, using Points I created to draw polygons such as the "T" shape in tetris.
My question is, when making my Tetris shapes, should I draw them using the Drawing methods in C# or should I create and import bitmap pictures of the tetris shapes and use those to create my tetris clone?
Once I can figure out how to draw shapes, the rest I can figure out on my own. Also, when doing work on the game grid, do I inherit the Picturebox Properties from my class called GameGrid?

Using bitmap and prerendered images are preferred, becuase it speeds up rendering of each frame. This is what most of such a games do.

The way that you render the shapes will have an effect on your collision detection. For instance, if you a bitmap of the T shape, you will have to have a method of detecting when the T has collided by perhaps per-pixel collision or a seperate structure which maintains the specific shape. Whereas, if you simply maintain a list of the blocks in use, collision detection becomes far simpler.
If you have your shapes as a matrix of blocks, much like the original game, you may find the rendering, handling and collision far easier.
For instance, have a look at the following pseudo-code:
class Shape
{
bool [3][3] Blocks;
Pos pos;
}
Shape T = new Shape();
T.Blocks[0][0] = true;
T.Blocks[0][1] = true;
T.Blocks[0][2] = true;
T.Blocks[1][0] = false;
T.Blocks[1][1] = true;
T.Blocks[1][2] = false;
T.Blocks[2][0] = false;
T.Blocks[2][1] = true;
T.Blocks[2][2] = false;
When rendering, you can do something along the following lines:
foreach(Shape s in currentBlocks)
{
for(int x = 0; i < 3)
{
for(int y = 0; y < 3; y++)
{
if(s.Blocks[x][y])
{
gameGrid.Render(s.Pos.X + x, s.Pos.Y + y);
}
}
}
}

Related

How can I draw a Line animation to outline various shapes?

I am trying to draw a line animation outline various shapes as in the image below. I am very well aware that it's best practice that I mention what I've been able to achieve to get specific help, but I am not sure where to begin, just that I know that using a Line Renderer could be a good approach to achieving this. That said, how can I achieve this?
UPDATE
I think I didn't explain a few things clearly enough. I am interested in animating the outline of objects without arrows, just a line traced round the outline like the image below:
I would do the following: (pseudocode, untested)
For every prefab or gameobject, store a List of edges that define your outline.
I wouldn't recommend using the mesh's edges, it's probably better to have a specific predefined list of edges per shape to avoid the inner edges of the object. Every entry in the list is defined by two Vector3's which are the two vertices.
List<Vector3[]> outline = new List<Vector3[]>();
Now, you have many ways to actually draw the arrows, like having them as individual gameobjects (probably not a good idea), particle system, or just drawn automatically from the parent objects update function. I would recommend the latter.
Now you would store a bunch of floats that define where your arrows are
public List<float> arrow_locations = new List<float>();
//adding one arrow
arrow_locations.Add(0.0);
//now in the update function of your parent object, update the arrow locations
private float cycle = 0.0f;
void Update()
{
float segment_size = 360.0f/outline.Count;
for(int i=0; i < arrow_locations.Count; i++)
{
arrow_locations[i] += 0.05f; //speed of spinning
if( arrow_locations[i] >= 360.0f ) arrow_locations[i] = 0;
//now to get the actual location of the arrow
int which_edge = Mathf.Floor((arrow_locations[i]/360.0f)*outline.Count);
//this will give us a number 0..1 telling us where along the edge the arrow is
float weight_within_edge=(arrow_locations[i] - segment_size*which_edge)/segment_size;
//here we lerp between the two vertices of the edge
Vector3 new_loc = outline[which_edge][0]*(1.0-weight_within_edge) + outline[which_edge][1]*(weight_within_edge);
//now that we have the location of the arrow, draw it
//note, you can get more efficient if using instancing for all arrows
//You can also use line drawing, but i wouldn't recommend that.
DrawMesh(arrow_mesh, new_loc, Quaternion.identity);
}
}
Please note, that when you have the positions of the arrows, you can opt to draw them in 2D in the UI by projecting them onto the camera plane. The lines aside from the arrows are themselves static, so you can draw them as part of the mesh very easily. Also note, I make no mention of the objects position, all values should probably be defined in local space, then transformed with the object. You can transform the drawn stuff in the the DrawMesh function by supplying a a transform matrix.
I think a shader with a parameterized radial mask would be the best way to do this. I have never done one myself, so I only have a general idea of how it's done, but here is how it would work AFAIK:
Create some kind of cell shader that can draw the edges of objects.
Create a filter/mask that has an angle shape extruding radially from the center to the edges; you can control the shape/angle using a parameter. Unity already has something similar to this in the Tanks! tutorial - Tank Health lesson.
Note: The tutorial might even be exactly this idea, but I don't remember with enough details to confirm; I'll update the answer after I take a look again.
The tutorial has the same idea, but it applies it using unity's builtin UI stuff.
Using this mask, only the masked area of the shape's edge will be drawn the screen.
By increasing the angle parameter of the mask over time, you can create the effect of the edge of the object getting revealed radially over time. Which seems to be exactly what you want.
To help visualize, a very professional diagram made in paint:
light blue = mask.
dark blue = "revealed" part of the mask (angle parameter). Plus how it would behave if the angle is increased (arrow).
green = object.
black = outline being drawn to the screen.

How can i show all edges in monogame?

I am using Monogame 3.5 and i have simple model of cube. I use BasicEffect to draw it. I want it transparent so i use effect.Alpha = 0.5f. Is it possible to show all edges something like on picture?
There's two ways to do this depending on what you're looking for. You can either set the rendering rastersizer state to show wireframe, or you can get a list of your edges and draw a set of VertexPositionColor using GraphicsDevice.DrawIndexedPrimitives.
Raster Sizer State
You can draw the cube transparent, and then, assuming you're using the BasicEffect, you can turn off all of the shading and set the colour to white.
You can then redraw the cube with the new rastersizer state set to FillMode.Wireframe. here's some pseudo code.
//Draw the Cube Transparent
DrawCubeTransparent();
//Now save the Rastersizer state for later
RasterizerState originalRasterizerState = GraphicsDevice.RasterizerState;
//Now set the RasterizerState too WireFrame
RasterizerState newRasterizerState = new RasterizerState();
newRasterizerState.FillMode = FillMode.WireFrame;
GraphicsDevice.RasterizerState = newRasterizerState;
//Now redraw the cube as wireframe with the shading off and colour set to white
DrawCubeWireFrame();
//Now reset the Rastersizer fill state
raphicsDevice.RasterizerState = originalRasterizerState;
DrawIndexedPrimitives
The previous method might not be ideal, because it will draw all triangular faces, so there wil be a diagonal line through your cube faces.
The other way is to find out which edges you want to draw and then use DrawIndexedPrimitives to draw an array of Vertices which contain all of your edges.
A simple google search will give you a ton of examples in using this.

3D shapes and Cellophane glasses

How do I generate basic 3D shapes (red and blue) that can be seen as 3D with cellophane 3D glasses, using C# in a desktop app? (Note that this question is not limited to any particular language. If I can get a head start in any language, then that's great. I can always learn from that and eventually know enough to attempt to implement this in my desired language.)
I've seen so many questions about this, but the answers seem very complicated and don't lead me to anywhere in the end. I can't even find any docs or articles about this.
To generate Anaglyph 3D images, you first have to render the scene from two slightly different viewports, one for each eye. The further apart they are, the smaller the scene will look, and the higher the 3D-sense will be.
The easiest method would be to use some existing library to render the images. Using a "camera", position it slightly to the left (and right) of the center of view. Render two images, and get the pixels.
The second step is to combine the two images into an Anaglyph 3D image. One way to do this, is to combine the red channel from one image with the green and blue channels from the other.
(Pseduo-C#:)
Color Combine(Color left, Color right)
{
return new Color(left.Red, right.Green, right.Blue);
}
Image Combine(Image left, Image right)
{
Image result = new Image(left.Width, left.Height);
for (int y = 0; y < left.Height; y++)
for (int x = 0; x < left.Width; x++)
{
result.SetPixel(x, y, Combine(left.GetPixel(x, y), right.GetPixel(x, y)));
}
}

Drawing a GUI in XNA

I'm currently working on making an XNA 2D platformer, and I'm wondering if it's possible to draw a kind of static GUI over the game?
What i mean here is that while the game updates and the players position changes etc, the GUI would be drawn on a kind of static layer (overlay?), that would be the size of the window the game is being run in. That way the game wouldn't have to constantly update the GUI's position and thus be a little bit nicer to handle.
Any ideas?
Thanks for your time
Yeah, you can just draw them using spritebatch :)
//HudTexture is a transparent texture the size of the window/screen, with hud drawn onto it.
SpriteBatch.Draw(HudTexture, Vector2.Zero, Color.White);
//Let's say that it works well to draw your score at [100,100].
SpriteBatch.DrawString(HudFont, Points.ToString(), new Vector2(100,100), Color.White);
if you plan on making more GUI (buttons etc) you might want to check out this answer I wrote to an other post:
XNA DrawString() draws only a partial string
Also; For drawing scores etc, I have experienced quite a bit of boxing/unboxing because of ToString. For that reason, I have often had an array of strings to represent the score:
String[] ScoreText = new String[100000]; //As big as your max score
//In Initializing method:
for (int i = 0; i < ScoreText.Length; i++)
ScoreText[i] = i.ToString();
//In draw:
SpriteBatch.DrawString(HudFont, ScoreText[Points], new Vector2(100,100), Color.White);
Sure, you can draw any sprites wherever you want using a SpriteBatch for example.
How you manage it is up to you. Just don't give any transformation matrices and things will be drawn at the coordinates you specify.
You'd end up with drawing your level (which would be offset by some camera position for example), then draw your GUI elements on top of that, with no offsets.

Using Stencils in XNA to Draw a texture in circles

I'm trying to make a small XNA-based game, and I need to be able to draw a single texture inside multiple mobile circles around the screen, as if they were 'spotlights' revealing parts of a bigger picture.
While searching for how I would be able to do that, I found that stencils might be able to help me accomplish that, but I have no idea on how I'd use the stencils to do that.
If anyone has any information or ideas on how I can do that, I'd be very grateful.
Edit: I forgot to mention the game is in 2D.
To start with, you need a mesh in the shape of the desired stencil, in this case a circle. XNA doesn't support many primitives, so you will need to approximate the circle with triangles.
Next, you render that mesh almost as normal but with:
graphics.DepthStencilState.DepthBufferFunction = CompareFunction.Never;
graphics.DepthStencilState.StencilEnable = true;
graphics.DepthStencilState.ReferenceStencil = 1;
graphics.DepthStencilState.StencilPass = StencilOperation.Replace;
Now you have a stencil with the holes.
Then, you render the texture through the stencil, with normal settings but with:
graphics.DepthStencilState.StencilEnable = true;
graphics.DepthStencilState.ReferenceStencil = 1;
graphics.DepthStencilState.StencilFunction = CompareFunction.Equal;
For more information see the reference for the DepthStencilState class.
This is based on my knowledge of 3D. You may have to do more stuff if you want to use sprites.

Categories