[C#][.NET] Creating a Snake Game

Started by G_G, August 05, 2012, 10:42:12 am

Previous topic - Next topic

G_G

Creating a Snake Game


Quick Navigation
1. Understanding the Concept
2. Setting Up
3. Creating Necessary Classes
4. Creating an Input Manager
5. The Game Loop
6. Rendering Graphics
7. Creating Game Logic

I'm not quite sure why, but I decided to make a tutorial on a Snake game using .NET 4.0. This tutorial might seem a bit lengthy and probably went too in depth in some areas and not enough in others. Some of the code in here might not be "optimized" persay but it works. Anyways, each tutorial is separated into different posts with a quick navigation in each post. I hope this is a one time exception to creating 8 posts in a row. Anyways enjoy!

Download full source here.
Download a wordpad document version here.

G_G

Quick Navigation
1. Understanding the Concept
2. Setting Up
3. Creating Necessary Classes
4. Creating an Input Manager
5. The Game Loop
6. Rendering Graphics
7. Creating Game Logic

1. Understanding the Concept

"Snake" is probably one of the most simplest games to understand (along with many other classic arcade games). Which is why it's a great example to game programming. It requires all of the necessary requirements for a game.

Game Logic
Update
-Check Input
-Update Player
-Check Collision

Render
-Draw Player
-Draw Fruit
-Draw Score

Concept
Snake is an easy game to understand. You start off as a "head" or a really, really small snake, roam around the playing field to collect food and you grow. You try to eat yourself, you die, if you run out of bounds, you die. Not much to it. So let's dig a bit deeper and understand how it works.

Each part of the snake can be considered an instance of an object, we'll call it "SnakePart". Each part follows the part in front of it. The snake and it's body, usually follow along a grid-based path. Each part is assigned an X and a Y coordinate, then gets rendered to that coordinate on screen. The food can be an instance of "SnakePart" rather then creating a new class. Set it's X and Y randomly to fit into the screen and then render it.

That's basically it for the concept of the snake game, can't really go much deeper with it.

G_G

Quick Navigation
1. Understanding the Concept
2. Setting Up
3. Creating Necessary Classes
4. Creating an Input Manager
5. The Game Loop
6. Rendering Graphics
7. Creating Game Logic

2. Setting Up

We're going to be creating this game in .NET 4.0 C# with Visual Studio 2010. The rendering method of choice will be GDI+. GDI isn't really meant to be used to render games, but it'll work perfeclty for a lightweight game like this. Before moving on, I'm going to assume that you have a basic knowledge of C# and understand how to work with Visual Studio.

Creating the Project
Creating the project is easy.
File > New > Project...
Be sure to select "Windows Forms Application" and then choose your desired Project Name and Solution Name.
Spoiler: ShowHide


Creating the Form
Creating the form is easy. All we need are two controls. A PictureBox, for rendering the game, and a timer, for updating the game every X miliseconds. Go ahead and drag a PictureBox and a Timer onto your form. We'll be modifying some of it's properties, we'll also be modifying some of the Form properties. (Feel free to change any of these properties, these are just for personal preference and you can design yours to however you choose.)

Form Properties
FormBorderStyle  FixedSingle
MaximizeBox      False
Size             362, 304
StartPosition    CenterScreen
Text             Snake


PictureBox Properties
(Name)           pbCanvas
BackColor        CornFlowerBlue
Location         13, 13
Margin           4, 4, 4, 4
Size             320, 240


Timer Properties
(Name)           gameTimer
(We're going to create the rest of the timer inside the actual code)


If you chose to follow my settings, you should end up with a form that looks like so.
Spoiler: ShowHide

G_G

August 05, 2012, 10:43:22 am #3 Last Edit: August 05, 2012, 10:46:49 am by gameus
Quick Navigation
1. Understanding the Concept
2. Setting Up
3. Creating Necessary Classes
4. Creating an Input Manager
5. The Game Loop
6. Rendering Graphics
7. Creating Game Logic

3. Creating Necessary Classes

Before we actually can start creating the game, we need to create a couple of classes. Go ahead and add these classes to your project.

SnakePart.cs
Input.cs


These are the only two main classes we'll need for the game itself. The food will be an instance of "SnakePart" as well as the snake itself. The Input class will be a static class that keeps track of key presses and key releases. We're just going to focus on SnakPart right now, we'll deal with Input a little later.

What we're going to do is create two getters/setters in our SnakePart class. This class only needs two variables, an X and Y coordinate.

    class SnakePart
   {
       public int X { get; set; } // X Coordinate for Snake Part
       public int Y { get; set; } // Y Coordinate for Snake Part

       // Constructor
       public SnakePart()
       {
           X = 0;
           Y = 0;
       }
   }

G_G

August 05, 2012, 10:43:40 am #4 Last Edit: August 05, 2012, 10:47:05 am by gameus
Quick Navigation
1. Understanding the Concept
2. Setting Up
3. Creating Necessary Classes
4. Creating an Input Manager
5. The Game Loop
6. Rendering Graphics
7. Creating Game Logic

4. Creating an Input Manager

Now we move onto the Input class. This won't be detecting Input right off the bat, we're just going to set it up so it can properly keep track of keys. WinForms basically runs off of events, so we'll be using the "Key Down" and "Key Up" events with our form. Once any of these events are fired, the key that was pressed/released will get sent to our Input manager which keeps track of every key.

Go ahead and create methods for the events "KeyUp" and "KeyDown" for your form. Here is all of the code we'll need to place in them.

        private void Form1_KeyDown(object sender, KeyEventArgs e)
       {
           Input.ChangeState(e.KeyCode, true);
       }

       private void Form1_KeyUp(object sender, KeyEventArgs e)
       {
           Input.ChangeState(e.KeyCode, false);
       }


Simple enough, right? Now Let's open up our Input class and create some code. First off, we'll need to create a variable to keep track of the keys. My personal preference would be to use a hashtable. Oh and since this is a static class, set the variable to a static so we don't have to initialize the class to use it.

        private static Hashtable keys = new Hashtable();


We're going to need the following namespaces imported into this class.

	using System.Collections;
using System.Windows.Forms;


Now we create our ChangeState method, this also has to be static. This won't be returning any values. All this method will do is set the "key" in our hashtable to a boolean value. In this case, our "key" will be an actual keyboard key passed through our method.

        public static void ChangeState(Keys key, bool state)
       {
           keys[key] = state;
       }


Simple as that. Now we need one more method to return these values when as ask for a key state. Again, this will be a static method, the return value a boolean. First we have to check to see if the "key" exists in the hashtable, if it doesn't just return a false value. If it does exist, we'll return the value of "key". Remember, a hashtable is just a list of objects, so we have to cast the value to a boolean.

        public static bool Pressed(Keys key)
       {
           if (keys[key] == null)
               return false;
           return (bool)keys[key];
       }


And that's it for our Input class. It is now ready to be used to detect Input in our loop.

G_G

August 05, 2012, 10:44:00 am #5 Last Edit: August 05, 2012, 10:47:35 am by gameus
Quick Navigation
1. Understanding the Concept
2. Setting Up
3. Creating Necessary Classes
4. Creating an Input Manager
5. The Game Loop
6. Rendering Graphics
7. Creating Game Logic

5. The Game Loop

Now the fun part, we're going to finish creating our gameTimer, by adding proper events and setting the tick interval. Using the timer class, it will fire an event after every X miliseconds, this event will be our Update method.

FrameRate
Most games run at 60 frames per second, that means the game will have updated and been rendered roughly 60 times every second. We're going to set the timer's interval to run at 60FPS. Since the timer's interval is in miliseconds, we'll take 1000 (miliseconds) / 60 (desired frame rate) and that'll be that. Go ahead and set this in our Form constructor.

Tick Event
Now we need to create a "Tick" method. Go ahead and create the following method.

        private void Update(object sender, EventArgs e)
       {
           // Update Logic here
       }


This will be our update method, and the event for gameTImer's tick. Go ahead and add this method to gameTImer in our constructor. And we'll go ahead and start the timer here as well.

        public Form1()
       {
           InitializeComponent();
           gameTimer.Interval = 1000 / 60;
           gameTimer.Tick += new EventHandler(Update);
           gameTimer.Start();
       }


Now once we start up the application, the timer will call the update method. That's pretty much it for our game loop, other than the fact that we still need to create render methods.  Throw this line in our "Update" method.

            pbCanvas.Invalidate();


Every update, this will force our picture box to invalidate, which when that happens, the picture box will need to be re-rendered onto the form. Now onto rendering!

G_G

August 05, 2012, 10:44:23 am #6 Last Edit: August 05, 2012, 10:47:52 am by gameus
Quick Navigation
1. Understanding the Concept
2. Setting Up
3. Creating Necessary Classes
4. Creating an Input Manager
5. The Game Loop
6. Rendering Graphics
7. Creating Game Logic

6. Rendering Graphics

The Paint Event
We'll need to take advantage of the picture box's "Paint" event. This event will get fired when the control needs to be painted or re-painted. Go ahead and create a method for this event. Inside the method, we'll be grabbing the Graphics value from our event arguments. With an instance of the Graphics class, we'll be able to draw on the picture box itself.

        private void pbCanvas_Paint(object sender, PaintEventArgs e)
       {
           Graphics canvas = e.Graphics;
       }


And now we have a complete game loop. Let's go ahead and test it out shall we?

Experimenting
Create two new variables in our Form class, "square_x" and "square_y". These will just be integers. Set them to 0 or whatever preferred number I suppose. In our Paint method, add this line.

            canvas.FillRectangle(Brushes.Red, new Rectangle(square_x, square_y, 16, 16));


Now let's go up to our Update method and test out our Input manager we created. We're going to check Input from the Arrow Keys and then change the values of square_x and square_y. Here is where we use our Input manager "Pressed" method.

        private void Update(object sender, EventArgs e)
       {
           if (Input.Pressed(Keys.Right))
               square_x += 4;
           if (Input.Pressed(Keys.Left))
               square_x -= 4;
           if (Input.Pressed(Keys.Up))
               square_y -= 4;
           if (Input.Pressed(Keys.Down))
               square_y += 4;
           pbCanvas.Invalidate();
       }


Go ahead and run the project. You should end up with something like this, you should be able to move the square around. Be sure to remove the experimental code before moving on.
Spoiler: ShowHide

G_G

August 05, 2012, 10:44:43 am #7 Last Edit: August 05, 2012, 10:48:07 am by gameus
Quick Navigation
1. Understanding the Concept
2. Setting Up
3. Creating Necessary Classes
4. Creating an Input Manager
5. The Game Loop
6. Rendering Graphics
7. Creating Game Logic

7. Creating Game Logic

This is the lengthy part of the tutorial. Here we will create all the necessary game logic for our Snake game. This includes :

  • 4-way grid movement

  • Food generation/Snake growth

  • Collision and Gameover

  • Score


Setting up the Snake
Remember that SnakePart class? Well we're going to start using it now. What we're going to do is create a List of SnakeParts. This will be the easiest way to create a dynamic snake. Go ahead and create the follow variable.

	List<SnakePart> snake = new List<SnakePart>();


This will be our list of parts. Now before we move on, I think it'd be best to explain the level size. The size of my picture box is 320x240, I'm groing to break this up into tiles since we're making this grid-based. Each tile with be 16x16 pixels, which leaves 20 tiles across, and 15 tiles down. In case you choose to change any of this later, we're going to create some constants as well.

        const int tile_width = 16;
       const int tile_height = 16;


This way, in case you decided to go with a bigger picture box or you want larger tiles, you can change any of these values. We have a few more variables we need to create for the game.

        bool gameover = false;
       int score = 0;
       int direction = 0; // Down = 0, Left = 1, Right = 2, Up = 3
       SnakePart food_piece = new SnakePart();


Now we need to create a "StartGame" method. This method will reset all values and start the game. In this method, we'll also be creating the head of our snake. The following clears the list of snake parts, then creates the head. The head will appear in the center near the top of the screen. Starting in the down direction.

        private void StartGame()
       {
           gameover = false;
           score = 0;
           direction = 0;
           snake.Clear();
           SnakePart head = new SnakePart();
           head.X = 20;
           head.Y = 5;
           snake.Add(head);
           GenerateFood();
       }


Notice the GenerateFood() line. We'll be creating that in a minute. Let's go ahead and add in the rendering for our snake. For our rendering, we'll be using a "for i in 0...size" iteration. Using this method, we can have our snake's head a different color from the rest of the body. Hop down to our picture box's Paint method.

        private void pbCanvas_Paint(object sender, PaintEventArgs e)
       {
           Graphics canvas = e.Graphics;
           for (int i = 0; i < snake.Count; i++)
           {
               Brush snake_color = i == 0 ? Brushes.Red : Brushes.Black;
               canvas.FillRectangle(snake_color, new Rectangle(snake[i].X * tile_width, snake[i].Y * tile_height, tile_width, tile_height));
           }
       }


This loops through every part, checks to see what "i" is and sets the color based on it. Then it draws a fill rectangle according to the current part's x and y with accordance to the tile size.

Generating Food
Time to generate some food! This method is extremely easy to create. What we're going to do here is make an instance of Random and have a number randomly generate to the canvas's bounds. Using our tile size constants and grabbing the size of the picture box, we'll be able to figure out our tile limit.

        private void GenerateFood()
       {
           int max_tile_w = pbCanvas.Size.Width / tile_width;
           int max_tile_h = pbCanvas.Size.Height / tile_height;
           Random random = new Random();
           food_piece = new SnakePart();
           food_piece.X = random.Next(0, max_tile_w);
           food_piece.Y = random.Next(0, max_tile_h);
       }


With some simple math, we figured out how many tiles there are vertically and horizontally. With this info, we create a new instance of SnakePart and assign it a random x and y in relevance to our bounds. Hop back into our Paint method. We have to make it draw our food now. Add this to the bottom of the method.

canvas.FillRectangle(Brushes.Orange, new Rectangle(food_piece.X * tile_width, 	food_piece.Y *tile_height, tile_width, tile_height));


Feel free to change the Brush. Now all that's left is to Check Input, Update the Snake, Check for Collision, and Gameover. We're almost done.

Check Input
This part is pretty easy. Remember earlier when we tested out the Input Manager? Well we're basically going to be doing that. Except, we're going to add a couple of more "if" branches. These extra branches will prevent the snake from moving right when he's going left, and moving down when he's already going up, and vica versa.

Things to keep in mind: Point A) We're doing this so the player can't kill himself by accidentally pressing the opposite direction. Point B) We can't have this limitation when the size of our snake is only 1. How are we going to tackle this? Easy.

When moving right, we'll check to see if the size is less than 2 or if the head and the 2nd part are on the same X. If either of these conditions meet, we change directions.

We apply these conditions (and slightly modify them) to all other directions. In our Update method, we need to check for "gameover" before we start updating. Then we add our Input logic into the else branch.

        private void Update(object sender, EventArgs e)
       {
           if (gameover)
           {
               // Gameover Logic
           }
           else
           {
               // Input and Snake Logic
           }
           pbCanvas.Invalidate();
       }


Now let's go ahead and create our Input logic. Keep this logic in mind.

Left and Right will check to make sure the head and second part's X match.
Up and Down will check to make sure the head and second part's Y match.
The above logic will be ignored it the snake's size is less than 2.


        private void Update(object sender, EventArgs e)
       {
           if (gameover)
           {
               // Gameover Logic
           }
           else
           {
               if (Input.Pressed(Keys.Right))
               {
                   if (snake.Count < 2 || snake[0].X == snake[1].X)
                       direction = 2;
               }
               else if (Input.Pressed(Keys.Left))
               {
                   if (snake.Count < 2 || snake[0].X == snake[1].X)
                       direction = 1;
               }
               else if (Input.Pressed(Keys.Up))
               {
                   if (snake.Count < 2 || snake[0].Y == snake[1].Y)
                       direction = 3;
               }
               else if (Input.Pressed(Keys.Down))
               {
                   if (snake.Count < 2 || snake[0].Y == snake[1].Y)
                       direction = 0;
               }
               UpdateSnake();
           }
           pbCanvas.Invalidate();
       }


That's all we need for input (for now). Notice I added the line "UpdateSnake()", just to keep organized, we're going to update the snake in another method.

Moving the Snake
Since each part of the snake is it's own part, we have to loop through the list of snake parts and update each one. How are we going to update the snake exactly? We're going to be using this logic.

Loop through the snake starting from the back.
Set the current part's X and Y to the part in front of it.
Move the head in accordance to it's current direction.


Basically, we'll start from the back of the snake. We'll grab the part that's in front of the current part we're on and copy it's coordinates.  In our for loop, we'll need to check to see if "i" is equal to 0 or not. In order to start from the back of our snake, we need to set "i" to the size of our snake, minus one, check if it's greater than or equal to zero, then minus one each loop.

        private void UpdateSnake()
       {
           for (int i = snake.Count - 1; i >= 0; i--)
           {
               if (i == 0)
               {
                   // Head Logic
               }
               else
               {
                   // Body Logic
               }
           }
       }


Let's go ahead and do the body logic right now, this part is sweet and short.

            snake[i].X = snake[i - 1].X;
           snake[i].Y = snake[i - 1].Y;


    Now let's go and do the head logic. In the head logic, we'll need to do a bit more work.

Update head's position.
Check for collision with the body.
Check for collision outside of the level.
Check for collision with the food object.[/li][/list]

For now, we're just going to update the snake's head. We'll worry about collision a bit later. We'll be using a switch statement in relation to our "direction" variable. This code goes in place of our head logic.

                    switch (direction)
                   {
                       case 0: // Down
                           snake[i].Y++;
                           break;
                       case 1: // Left
                           snake[i].X--;
                           break;
                       case 2: // Right
                           snake[i].X++;
                           break;
                       case 3: // Up
                           snake[i].Y--;
                           break;
                   }


Revisiting the Frame Rate
Now we're almost ready to test this out, however we have to change the frames-per-second. Earlier we set it up so it'd run 60 frames per second. With a game like snake, we don't need it that high and we certainly don't want it. THe snake would move roughly 60 times every second. Let's try something along the lines of like 4 times every second. In our constructor, just change the gameTimer.Interval.

            gameTimer.Interval = 1000 / 4;


One more thing, add "StartGame();" right under gameTimer.Start(), now run your project. You should have perfectly working snake movement.

Collision
Collision is easy. All collision checking will be done inside the head logic. First we'll check to see if the head is outside the screen. Then we'll do another for loop with the body and check to see if the head collided with it's body, then we'll check collision with the food.

Let's start with checking the bounds. We'll use the same simple math we used to generate food to grab the number of vertical and horizontal tiles. Then we'll check to see if the head's X and Y is less than zero or exceeds the number of tiles. Then set the gameover flag to true.

int max_tile_w = pbCanvas.Size.Width / tile_width;
int max_tile_h = pbCanvas.Size.Height / tile_height;
if (snake[i].X < 0 || snake[i].X >= max_tile_w || snake[i].Y < 0 || snake[i].Y >= max_tile_h)
         gameover = true;


Alright, time to update with the body.  Collision with the body is simple. We create another for loop that starts from "1" and climbs up through the snake's body. For each index, we check to see if the head's coordinates match any of the others.

            for (int j = 1; j < snake.Count; j++)
               if (snake[i].X == snake[j].X && snake[i].Y == snake[j].Y)
                   gameover = true;


Now food collision and snake growth. All we do here is check the head's X and Y with the food's X and Y. If collision occurs, we create another instance of "SnakePart". It's coordinates will be set to the last part in the snake's coordinates. Along with adding a new part, we also have to generate a new piece of food and add 1 to our score.

            if (snake[i].X == food_piece.X && snake[i].Y == food_piece.Y)
           {
               SnakePart part = new SnakePart();
               part.X = snake[snake.Count - 1].X;
               part.Y = snake[snake.Count - 1].Y;
               snake.Add(part);
               GenerateFood();
               score++;
           }


And that's it for collision. So what's left? Our DoGameover() method. Then starting a new game when the gameover occurs. Drawing the score in the top corner would be nice as well. Before we move on, feel free to try out what we have so far. You should have a completely working snake that grows as he eats food. Dying works properly as well. You'll notice the game freeze whenever you die.

Gameover
All we're doing here is trying the player's final score, text saying "Gameover" then some text saying "Press Enter to Start Over". Then of course we actually have to detect input. We have to add an "if else" branch in our Paint method as we forgot to do so earlier.

Graphics canvas = e.Graphics;
if (gameover)
{

}
else
{
   for (int i = 0; i < snake.Count; i++)
   {
       Brush snake_color = i == 0 ? Brushes.Red : Brushes.Black;
       canvas.FillRectangle(snake_color, new Rectangle(snake[i].X * tile_width, snake[i].Y * tile_height, tile_width, tile_height));
   }
   canvas.FillRectangle(Brushes.Orange, new Rectangle(food_piece.X * tile_width, food_piece.Y * tile_height, tile_width, tile_height));
}


In the gameover branch, we'll be drawing some text in the center of the screen. We're just going to be using the font attached to our form. We'll go ahead and create our messages as well.

        Font font = this.Font;
       string gameover_msg = "Gameover";
       string score_msg = "Score: " + score.ToString();
       string newgame_msg = "Press Enter to Start Over";


Now to center it in the screen horizontally, we need to measure the size of the string. The Graphics class comes with a nice MeasureString method. We'll also need to know the center of the screen so we take the width of our picture box and divide it by 2. We'll start off by measuring our gameover_msg and then drawing that.

            SizeF msg_size = canvas.MeasureString(gameover_msg, font);
           PointF msg_point = new PointF(center_width - msg_size.Width / 2, 16);
           canvas.DrawString(gameover_msg, font, Brushes.White, msg_point);


Now we do the same for our score_msg and newgame_msg.

            msg_size = canvas.MeasureString(score_msg, font);
           msg_point = new PointF(center_width - msg_size.Width / 2, 32);
           canvas.DrawString(score_msg, font, Brushes.White, msg_point);
           msg_size = canvas.MeasureString(newgame_msg, font);
           msg_point = new PointF(center_width - msg_size.Width / 2, 48);
           canvas.DrawString(newgame_msg, font, Brushes.White, msg_point);


That's it for drawing our gameover screen. Feel free to test it out. While we're here in the paint method, let's go ahead and draw the player's score while the game is playing. In the "else" branch of our Paint method, add this to the bottom.

            canvas.DrawString("Score: " + score.ToString(), this.Font, Brushes.White, new PointF(4, 4));


And now all that's left is to add our logic to start a new game. This part's really easy. Go into our Update method and all we need are these two lines placed in our Gameover logic.

                if (Input.Pressed(Keys.Enter))
                   StartGame();


And bam! That's it! Our Snake game is completely done! Well, we're done with this tutorial anyways. That doesn't mean you have to be done. Here are a list of things you can do to improve on this.

  • When generating food, add a check to make sure it doesn't spawn on the snake's body
  • Make the snake move faster after every piece of food it collects (this is done by altering the gameTimer's interval)
  • Implement a highscore system of some kind.

    I hope you enjoyed the tutorial. If you have any questions feel freek to ask! Also, if you need/want it, the source can be downloaded from the first post.

stripe103

I was expecting it to be in XNA but I guess that can be easily converted. Nevertheless it was a good tutorial.
just one little change I made was to change direction in the KeyDown event instead so you don't need to hold down the key. Just thought it made it harder having to time every press to the game update tick.

Still though, a great tutorial that every new programmer should go through if they want to get into game programming.

G_G

Quote from: stripe103 on August 05, 2012, 04:24:42 pm
I was expecting it to be in XNA but I guess that can be easily converted. Nevertheless it was a good tutorial.
just one little change I made was to change direction in the KeyDown event instead so you don't need to hold down the key. Just thought it made it harder having to time every press to the game update tick.

Still though, a great tutorial that every new programmer should go through if they want to get into game programming.


Yeah this was an issue I ran into, but figured if anyone had experience at all they could fix it. The reason it does this is because it's only being updated 4 times every second. If you go with a traditional 60 FPS, you'd have to apply another timer to the snake so it wouldn't move 60 times a second. But yeah, I'm with you on that.

And thanks so much for the feedback. ^_^

ForeverZer0

Very nice tut, G_G. ++
I like that it is not in XNA, which is overkill for such a thing and simply adds dependencies. Not to mention that it teaches the same logic without the extra confusion of teaching basic XNA on top of it.
I am done scripting for RMXP. I will likely not offer support for even my own scripts anymore, but feel free to ask on the forum, there are plenty of other talented scripters that can help you.

G_G

Quote from: ForeverZer0 on August 05, 2012, 06:22:43 pm
Very nice tut, G_G. ++
I like that it is not in XNA, which is overkill for such a thing and simply adds dependencies. Not to mention that it teaches the same logic without the extra confusion of teaching basic XNA on top of it.


Thanks. And agreed. With XNA we would have had to gone through texture loading and font loading and so much more just to get this result. GDI+ can work great for a lot of 2D games depending on how much you need/have going on.

Apidcloud

A really nice tutorial by g_g. Have you considered on doing the same thing using videos? like the ones you made to game maker, I really liked them

I'm going to follow it as soon as I got some free time  :)
Instead of wanting to be somebody else, rather become somebody else



"I will treasure the knowledge like a squirrel treasures acorns."


Gibbo Glast 2D Engine - The sky is no longer a limit

G_G

I should start doing video tutorials again. I enjoy doing them, just a lot of times I can't find the time to do them and finish the actual series.

Apidcloud

Sorry for asking, - got no time to search for you on youtube and actually search for it - did you finish that game maker series?

Well, I find your video tutorials really interesting - you speak clearly, have good accent, which really helps - so you should, definitely, make them more often  :)
Instead of wanting to be somebody else, rather become somebody else



"I will treasure the knowledge like a squirrel treasures acorns."


Gibbo Glast 2D Engine - The sky is no longer a limit

G_G

November 15, 2012, 08:27:33 pm #15 Last Edit: November 15, 2012, 08:29:39 pm by gameus
Unfortunately, I never finished the series. I got extremely bored with Game Maker. It's a very powerful tool and it's pretty limitless, but there are so many restrictions with it as well. They could have chosen a better scripting language, one that supported object orientation. If I do decide to do some tutorials, I'm not sure what I'll do.

Game Maker back then, back before they started overcharging the fuck out of it, was good. It used to only be 25 dollars. You look on their site now, it's so fucking expensive, and it's the same damn engine as it was before. Just with improvements. Game Maker 8 and 7 users got screwed over when they released Studio. They pretty much dropped support for it and started overcharging for their software. I don't really like the path YoYoGanes has taken.

Apidcloud

November 15, 2012, 08:35:29 pm #16 Last Edit: November 15, 2012, 08:38:03 pm by Apidcloud
Oh well, I wasn't aware of any of that. I don't think that Ruby - rgss most likely - would do the job either, since you can do everything with a variable and can be as careless as you want -.-

How about XNA? Didn't you start working on it a while ago?

Edit:
Or even Android :D Android's 4.2 SDK was released yesterday I think
Instead of wanting to be somebody else, rather become somebody else



"I will treasure the knowledge like a squirrel treasures acorns."


Gibbo Glast 2D Engine - The sky is no longer a limit

G_G

Ruby is object oriented. It would have been a pretty suitable language for Game Maker. And just because you can be careless with your code, doesn't mean it's not a great language. As for XNA, I could probably do some XNA tutorials. I might even do some Android SDK tutorials. I'd have to get back into Java though. Anyways, thanks for the ideas Apid, maybe I'll do some this weekend. :3

Apidcloud

Quote from: gameus on November 15, 2012, 09:14:55 pm
And just because you can be careless with your code, doesn't mean it's not a great language.

True story xD

Quote from: gameus on November 15, 2012, 09:14:55 pmmaybe I'll do some this weekend. :3

Looking forward to it ;)
Instead of wanting to be somebody else, rather become somebody else



"I will treasure the knowledge like a squirrel treasures acorns."


Gibbo Glast 2D Engine - The sky is no longer a limit

Blizzard

The Android SDK is only a set of supporting tools for developing and building apps and games for Android. It's not a game engine, keep that in mind. Just like installing Windows SDK (now called Windows Kit since Windows 8, it comes as integral part of Visual Studio 2012) is for development on Windows platforms. XNA is a bit more specific, it's a game development SDK (even though you can technically do any kind of 3D stuff in there), but still not a game engine.

If you want a good game engine, I can recommend Unity. I haven't tried it myself, but a colleague at work is using it on a regular basis and from this "second hand" experience it seems not only pretty good, it also incorporates the latest industry standards and technologies related to 3D, physics and other segments. Not only that, it is multi-platform, you can even run your games in a web browser through their Web Player.
Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

G_G

I know XNA and Android aren't engines themselves, but you can create engines with them. I've tried Unity several times but I never get anywhere with it just for the lack of 3D knowledge. I eventually want to get into 3D development, but every time I try, I always end up giving up, mostly over silly things. I think I may take another shot at Unity.

Apidcloud

Ah yes, im aware of that, but when i suggested android I wasnt specifically talking about game, even though its the funniest thing xd about unity, i havent tried it either but a new version has been released like 2 days ago or something, it would be interesting to work with it
Instead of wanting to be somebody else, rather become somebody else



"I will treasure the knowledge like a squirrel treasures acorns."


Gibbo Glast 2D Engine - The sky is no longer a limit

DaJoker

hello gameus,
your Snake Game Tutorial is wonderful i can't thank you enough  :-* for making one of the best tutorials i have seen on the internet for this game.
but i was wondering  :???: and trying to find a way to modify the game to Generate more Food and have maybe some way to add difficulty to change snake speed when you press one of 3 buttons (easy, medium, and hard) to make the game more interesting and challenging.

and i am sorry if i revived such a dead post in anyway  :^_^':

G_G

Here's what I'd do.

For the food:

  • Create a food array or a food list, and in the generate food method, generate how ever many pieces

  • In the collision check method, you'll have to iterate through the array of food instead of checking just one piece of food

  • You can even randomize colors if you'd like, just add a Color variable to the Food (snake piece) class



Making the Snake move faster

  • In the tutorial, I only used one timer, it'd be easier if I had used two timers. One for the Game logic/rendering and one for moving the snake

  • I'd create another timer for snake movement only, and everytime it ticks, it'll move the snake. Allowing you to modify the tick speed, the lower it is, the faster the snake.

  • Modify the first timer so it runs at a constant FPS (such as 30 or 60)



These are good things to learn and to practice your programming skills.

DaJoker

 oh wow thanks mate cant be more grateful for your ideas and advice's on the topic  :bow:  but if u can show me your ways of implementing the codes with your codes
because some how i am not able to achieve it :negative:

G_G

I don't really have the time or want to create add-on code. This tutorial is meant for people to work on and improve the code themselves. It's as simple as that.

leona313

July 31, 2014, 02:28:44 am #26 Last Edit: July 31, 2014, 02:30:40 am by leona313
i heart the barcode can be used in games visual basic 2d bar code generator

PhoenixFire

Quote from: Subsonic_Noise on July 01, 2011, 02:42:19 amNext off, how to create a first person shooter using microsoft excel.

Quote from: Zeriab on September 09, 2011, 02:58:58 pm<Remember when computers had turbo buttons?

Blizzard

Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

dobzik

Quote from: gameus on August 05, 2012, 10:44:23 am
Quick Navigation
1. Understanding the Concept
2. Setting Up
3. Creating Necessary Classes
4. Creating an Input Manager
5. The Game Loop
6. Rendering Graphics
7. Creating Game Logic

6. Rendering Graphics

The Paint Event
We'll need to take advantage of the picture box's "Paint" event. This event will get fired when the control needs to be painted or re-painted. Go ahead and create a method for this event. Inside the method, we'll be grabbing the Graphics value from our event arguments. With an instance of the Graphics class, we'll be able to draw on the picture box itself.

        private void pbCanvas_Paint(object sender, PaintEventArgs e)
       {
           Graphics canvas = e.Graphics;
       }


And now we have a complete game loop. Let's go ahead and test it out shall we?

Experimenting
Create two new variables in our Form class, "square_x" and "square_y". These will just be integers. Set them to 0 or whatever preferred number I suppose. In our Paint method, add this line.

            canvas.FillRectangle(Brushes.Red, new Rectangle(square_x, square_y, 16, 16));


Now let's go up to our Update method and test out our Input manager we created. We're going to check Input from the Arrow Keys and then change the values of square_x and square_y. Here is where we use our Input manager "Pressed" method.

        private void Update(object sender, EventArgs e)
       {
           if (Input.Pressed(Keys.Right))
               square_x += 4;
           if (Input.Pressed(Keys.Left))
               square_x -= 4;
           if (Input.Pressed(Keys.Up))
               square_y -= 4;
           if (Input.Pressed(Keys.Down))
               square_y += 4;
           pbCanvas.Invalidate();
       }


Go ahead and run the project. You should end up with something like this, you should be able to move the square around. Be sure to remove the experimental code before moving on.
Spoiler: ShowHide



Hi, I have followed the code and I could not get the red square in the middle, can you please help me? Here's my code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections;

namespace Snake
{
    public partial class Form1 : Form
    {
        private static Hashtable keys = new Hashtable();
        private int square_x=5;
        private int square_y=5;
        public Form1()
                 {
           
            InitializeComponent();
            timer1.Start();
            timer1.Interval = 1000 / 60;
            timer1.Tick += new EventHandler(Update);
        }
        class snake
        {

            public int x { get; set; }
            public int y { get; set; }
            public snake(int x, int y)
            {
                x = 0;
                y = 0;
            }
        }
        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            Input.ChangeState(e.KeyCode, true);
        }

        private void Form1_KeyUp(object sender, KeyEventArgs e)
        {
            Input.ChangeState(e.KeyCode, false);
        }

   
        class Input
        {
     
            public static void ChangeState(Keys key, bool state)
            {
                keys[key] = state;
            }
            public static bool Pressed(Keys key)
            {
                if (keys[key] == null)
                    return false;
                return (bool)keys[key];
            }
        }

     
       
        private void pbCanvas_Paint(object sender, PaintEventArgs e)
        {
            Graphics canvas = e.Graphics;
            canvas.FillRectangle(Brushes.Red, new Rectangle(square_x, square_y, 16, 16));
        }
        private void Update(object sender, EventArgs e)
        {

            if (Input.Pressed(Keys.Right))
                square_x += 4;
            if (Input.Pressed(Keys.Left))
                square_x -= 4;
            if (Input.Pressed(Keys.Up))
                square_y -= 4;
            if (Input.Pressed(Keys.Down))
                square_y += 4;
            pbCanvas.Invalidate();
        }

    }
}