Game Development Tutorial

Everything a total beginner needs for game programing!

Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts

26. Pythagoras, Firefighers and Math

The last and, in my oppinion, the coolest part of this tutorial is making our doggy splash water from his fire-hose. There are a lot of ways to do this… My first idea was to make him splash a stream of water in a horizontal line… But I wasn't satisfied. Then, i figured out how to make him splash wather at an angle… But that didn't make me satisfied either. Then I decided to renew my high school math knowlege, and to force this dog to splash water to the exact point where the player would click the mouse… And, how does this look in theory? Here's a drawing…

 

Here's a little legend: Point B is the point where player clicked. Point A is the starting point of the splash. So, that makes the blue line c our splash. Angle alpha is the angle of the splash. It can be positive, or negative. So, how can we figure out the lenght of the splash (c), and it's angle (alpha)??? Just a little math. Our points are defined with x and y coordinates. So, if we know the horizontal coordinate for B, and the width of our game field, then we know the lenght of the red line b. And on the same priciple, we can find the lenght of the red line a. Calculating splash lenght c is just a matter of Pythagoras. Remember that jibberish your math teacher filled your hed with? I hate to admit it, but, it came useful. So, here's the equation:

(Pythagoras' theorem):

That's how we would write it on a peace of paper. And to make our C# understand it, we can write it like this:

int c = (int)Math.Sqrt(a * a + b * b); 

And if we have two sides of the triangle calculated, we can determine the angle with another math operation… Uff… Here's the equation:

Again, translated into C# il would look like this:

float alpha = (float)Math.Atan
((double)a / (double)b); 

To rotate an image, we'll use matrix translations… More math… Ah well… So, now when we finally have everything, we can write the code. Here it is. Enjoy it, it's your last peace of code in this tutorial. 

private void Splash(int MouseY, int MouseX)
{
  // Point A:
  Point pStart = new Point
  (picGameField.Width - 1, 195);

  // Calculating the lenght of the splash,
  // and other sides of the triangle:

  int a = (picGameField.Height - MouseX
  - (picGameField.Height - 215));

  int b = (picGameField.Width - MouseY);
  int c = (int)Math.Sqrt(a * a + b * b);
  
  // Calculating the angle of the splash:
  float alpha = (float)Math.Atan
  ((double)a / (double)b);

  
  // Convert from Radians to Degrees
  alpha = alpha * (float)(180.0 / Math.PI);
  
  int x = picGameField.Width - c;
  int y = 195;

  // Defining the position of our splash image:
  Rectangle rSplash = new Rectangle(x,y,c,50);
  Graphics gSplash = picGameField.CreateGraphics();

  // Matrix rotations:
  Matrix X = new Matrix();
  X.RotateAt(alpha, pStart, MatrixOrder.Append);
  gSplash.Transform = X;
  
  // Drawing our image to the screen:
  gSplash.DrawImage(picSplash.Image, rSplash);
  // Pause for a moment:
  System.Threading.Thread.Sleep(100);
  // Getting rid of our splash image:
  gSplash.Dispose();
}

Obviously, we need some mouse coordinates for this code to work... In the next (probably the last) post - I'll post the whole source code for the project. With a download link... :) I know I skipped a few parts of the code, so, you'll be able to 'grab' them from actual project files! :)

17. To help, or not to help

So, our game is almost playable… Well, it is, but there's a lot of stuff to add… Like, random blocks appearing on the game field. The game I 'borrowed' the idea from, had these blocks apearing at radnom time intervals and random places on the game field… And those fields were cool, because, sometimes, they helped to clear you some additional blocks, and sometimes, they filled that valuable empty columns… Ok, back to the drawing board. Litteraly. Here are two examples, first one that shows when the block is helpful, and another one wich shows when it's not that helpful.

Take a look at the picture. The player has only two empty columns left. Let's think about the next situaion:  

a) Let's imagine that in this moment, our game 'spawns' a red field at [4,5]. That would help the player, since he would be able to clear that red field, and the field one block to the right. (the one under [5,4]). The result would be - three empty columns.

b) If we would spawn a blue field at [4,5] - that wouldn't affect the player a lot - he would clear the field, and the blue one on the left. The result would be the same: Two empty columns.
 
c) If we wolud spawn a green field at that location, that would be the worst case scenario for the player. He would be stuck with only one empty column.
 
Looking at the Field[5,4], the best thing for the player would be, if we created a red block there. In that case, he could empty the #5 column. Spawning a green block wouldn't make a big difference. When the columns would be moved to the right, the green fields could be cleared. Creating a blue field there would be the worst thing for the player, but that wouldn't mean any disadvantages for him. The empty column count would stay the same.

So, the code for creating a 'random' block:(Put it in the DropBlock() method)

// Once again, we'll use the
// random function. We'll
// generate a random color,
// and a random position for
// our new block.

Random Rndm = new Random();

// Increasing the random range
// decreases the chance to drop
// the block.

int R = Rndm.Next(1, 3);

switch (R)
{
  case 1:
    // Drop the block!
    // Generate the position:

    int RX = Rndm.Next(iHeight - 1);
    int RY = Rndm.Next(iWidth - 2);

    // We dont allow the new block to
    // spawn in the last column - so
    // we don't cause possible gameover's ;)


    // We have to see if the field is empty...
    // So we don't overwrite some other field.
    // This also affects the possibility
    // of creating a random block...

    if (Field[RX, RY] == 0)
    {
      // Fill the block with a random
      // color;

      Field[RX, RY] =
      Rndm.Next(1, iColor + 1);
      // Make it fall down...
      GoGravity();
    }
    break;

    default:
      break;

 
In the next chapter, we'll make a score method, so we can let the player know how succesful he was...

13. Chasing the mouse

In our game, we'll use the mouse as an input device. Player will be able to click anywhere in the game field, and we'll have to figure out if he clicked a block, or an empty field. If the player clicks on the block, we'll have to check if it's connected with any other block of the same color, and we'll have to destroy the blocks if so. And to add a little feature, we'll take away one point for every mouse click. (Wich reminds me… We'll have to make a score counter, real soon.) So, how the hell can we find out where the user clicked? Lucky for us, the Picture Box in wich we draw our game field, has a MouseClick event. So, we'll use it to see if the user clicked anywhere on the game field. But how to find out on what block the user clicked? A little basic math will help us solve this problem. We already have defined that the block field is 32 pixels in width/height. And lucky for us, VS.net can give us the coordinates of the mouse pointer on the screen, and in relation to the clicked object. That means, that VS will give us the distance from the top and left borders of the picture box, measured in pixels. So, those are the ingreedients. Let's mix them all together and see how they work. First of all, go to your design window, select the Picture Box, and then, go to your Properties window. Just above the properties list ther is a little icon of lightning. Click on it, and you'll see the events list. Find the MouseClick event, and double-click on it's name. This should give you the code editor window with the method already in place. Here's the code for it:

// We find the X and the Y coordinate of 
// the mouse using the mouse event arguments
// (called 'e'). We'll store them into some 
// variables. Note, how we switched X and Y's 
// place – that's because we declared our game
// field in the opposite way – X for height 
// and Y for width. I know… Goofy…

int mx = e.Location.Y;
int my = e.Location.X;

// The next step is to divide the mouse 
// coordinates with the block/field size,
// so we'll get the coordinates of our field.

decimal x = mx / iFieldSize;
decimal y = my / iFieldSize;

/ And to round them up (since they came 
// back as numbers with decimals) we 
// convert them right back into intigers.
// Not to mention that we need them as 
// integers, to define our fields.

int ix = (int)x;
int iy = (int)y;

This code will give you exact coordinates of the block player clicked. Ok, what's next? Obviously, we'll have to see if the block player clicked, is actualy connected to other blocks of the same color. And we'll do just that – in the next chapter.

9. Our first gameplay stuff

One of the rules of our gameplay is the one saying that the game sends in new columns of blocks from the left. And it does so until the player runs out of empty columns… We'll divide this into three basic steps. And later on, we'll add a timer to our game. A timer will make sure that a new column will be created every time at a specified interval. These are the steps for our basic gameplay:

  1. Create new column with random colors
  2. Move existing columns to the right to make some room for the new column
  3. If we can't move any columns – Game Over!
  4. If the player cleared a certain ammount of columns – move him to a new level

And to make this work we'll declare some more variables – like the number of different colors allowed in the new column. By increasing this number, the game becomes more difficult to play. And one other way to make the game more difficult to play is by shortening the time interval between new column creation. The third way to make our game harder is to increase the number of columns needed to be cleared in a level. Later on, we'll incorporate all this stuff in our game. So, our game will become more and more difficult – from level to level.

Back to the code – here's what we need to add to our declarations:

// Declare the number of different colors
// that are used in the current level.
// We'll set it to 4 - for now:

int iColor = 4;
// Declare the counter that we'll use
// for changing colors every X levels.

int iColors;

// Declare the  integer that will hold
// the number of columns created  in
// the current level:

int iColumn;// Declare the integer that will hold
// the total number of columns in
// the current level.

int iColumns;

Add these lines of code right under the Game Field Height, Width, and Field Size declarations. Before moving on, we have to add a label to our form. So, add a label to the form, and then set it's properties like shown in the next list:

Label

  • (name): lblColumn
  • BackgroundColor: Web > Transparent
  • Location: 555; 97
  • Font: Microsoft Sans Serif; 9,75pt; style=Bold
  • Text: 0/0

Finally, the code that will create our new column. Put it in your CreateNewColumn() function.

if (iColumn < iColumns)
{
 
// Initializing the random function.
 
// It will come up with random  
  // numbers every time we call it.

 
Random Rnd = new Random();

 
// We have to create 10 new fields.
  // (Our column is 10 fields high.)

  for
(int p = 0; p < iHeight; p++)
  {
   
// We set the random function in
    // a way, so it couldn't return
    // a value larger than we declared
    // it in the beginning, and it
    // couldn't return 0 (wich means –
    // empty field).
    Field[p, 0] = Rnd.Next(1, iColor + 1);
  }

 
// Increase the number of columns created
  iColumn++;
  // Display the column count in the new
  // label on our form.

  lblColumn.Text = iColumn.ToString() +
  "/" + iColumns.ToString();
}
else
{
  // The level is over when the number
  // of columns created in the current

  // level is equal to the total number
  // of columns predicted for that level.
  // When the level is over, we call our
  // methods for counting bonus points
  // and switching to a new level.

  LevelScore();
  NewLevel();
}


That's it for this chapter. In the next one, we'll add a timer to our game, and add some code to make it create new colums every second. We'll also start talking about moving all existing colums to the right.

7. Showing our field

When we wrote the code for our CreateField() method, we didn't write any code for displaying the field to the user. We'll do it in this chapter. We'll take a look at graphic programming, GDI+… So, let's fill our DrawField() method. Here's the code – go trough it, read the comments (the green stuff), and hopefully, you'll get it. :) I did write a lot of comments. I hope they help.

// Define a Brush – an object that will
// hold the color value for our Game 
// Field background.

Brush Background = Brushes.PowderBlue;

// We want to show our field inside the 
// Picture Box, so we create a graphich 
// object inside our Picture Box.

Graphics gField = picGameField.CreateGraphics();

// We'll go trough all of our fields, and we'll 
// display them one by one (taking into consideration
// the color value each field contains). We have 150 
// fields, so, we'll do this with the help of two loops.
// It woud be painfull to do it manually.

// First loop that is going trough every line.

for (int v = 0; v <>
{
  // Second loop – this one is going
  // trough every column.

  for (int s = 0; s < iWidth; s++)
  {
        // We define a small rectangle, for
    // every field in our game field. We'll
    // use the variable that contains the
    // rectangle's width/height. If you
    // remember, we defined it in our first
    // lines of code.

    Rectangle rtgField = new Rectangle
    (s * iFieldSize, v * iFieldSize,

     FieldSize, iFieldSize);
  
    // First of all, we'll fill our rectangles 
    // with our background color.

    gField.FillRectangle(Background, rtgField);
   
    // And now, we'll fill the field with the color 
    // that is defined with the fields value.

    switch (Field[v, s])
    {
      case 0:
        // Draw empty field...
        break;
      case 1:
        // I've decided that color #1 is Blue. So, if 
        // the field holds a value of 1 – We'll color it 
        // blue. And we'll do the same for all
        // other colors.

        gField.FillRectangle(Brushes.Blue, rtgField);
        break;
      case 2:
        // If the field contains value 2:
        // we'll fill it red.

        gField.FillRectangle(Brushes.Red, rtgField);
        break;
      case 3:
        // If the field contains value 3:
        // we'll fill it green.

        gField.FillRectangle(Brushes.Green, rtgField);
        break;
      case 4:
        // If the field contains value 4:
        // we'll fill it yellow.

        gField.FillRectangle(Brushes.Yellow, rtgField);
        break;
      case 5:
        // If the field contains value 5:
        // we'll fill it purple.

        gField.FillRectangle(Brushes.Purple, rtgField);
        break;
      case 6:
        // If the field contains value 6:
        // we'll fill it black.

        gField.FillRectangle(Brushes.Black, rtgField);
        break;
      case 7:
        // If the field contains value 7:
        // we'll fill it orange.

        gField.FillRectangle(Brushes.Orange, rtgField);
        break;
      case 8:
        // If the field contains value 8:
        // we'll fill it gray.

        gField.FillRectangle(Brushes.Gray, rtgField);
        break;
      case 9:
        // If the field contains value 9:
        // we'll fill it dark blue.

        gField.FillRectangle(Brushes.DarkBlue, rtgField);
        break;
      case 10:
        // If the field contains value 10:
        // we'll fill it pink.

        gField.FillRectangle(Brushes.Pink, rtgField);
        break;
      default:
        // If our program comes to this point of the code,
        // something's gone wrong! ;) XD

        break;
    }
  }
}


Now, you're just a few steps away from seeing it on the screen. Go back to your Design View by clicking the tab 'frmMain.cs [design]' on top of the code window. Double click on the 'New Game' button, and you should wind up right back in the 'code' window. But, this time, you'll see some extra lines of code that were generated by the VS.net. The new lines are:

private void butGame_Click(object sender, EventArgs e)
{
}

Add this line of code in between the two curly brackets:

DrawField();

And run your game! (Click on the green 'Play' button in your toolbar). Click on the button, and you should see this:



In the next chapter: We'll fill our CreateGrid() function, and play a little with our blocks... :)

2. Tools of the trade

A screenshot of the VC# Express ED;

So, what do you need to follow this tutorial?

This tutorial is based on Microsoft's Visual C#, wich is a part of Microsoft's Visual Studio. I guess that any version of C# will do. I've tried my code on two machines: One with MS VC# 2005 Proffesional Edition, and one with MS VC# 2008 Express Edition installed. And it works just fine on both of them. So, my advice to you would be to go to Microsoft's web site and download the latest C# Express Edition. Yes - It's FREE! And no, it's not a demo. It's a fully funcional development tool for personal use. Once you download and install C# - you're ready to rock!

(the URL is www.microsoft.com - in case you didn't know ;)

Where to begin?

First, open that freshly installed C# and look around... Try to familiarize yourself with the interface. The next thing would be to get a notebook - an old fashioned one, and a couple of pencils... They help you organise your thoughts. ;) And that's it. We're ready to design our first game.



Downloads

Downloads
Finished Bubble Splash Game

Followers

Translate

Blog Directories

Programming Blogs - BlogCatalog Blog Directory
blog directory
Software Computers Business Directory - BTS Local
Top Blogs GoLedy.com
TopOfBlogs DigNow.net
Blog Directory blog search directory
Top Computers blogs Add to Technorati Favorites
Computers Blogs Blog Directory
blogsbycategory.com Blog Directory & Search engine
Blog Flux Directory Programming Blog Directory
Join My Community at MyBloglog! BlogRankers.com
Technology Blogs - Blog Rankings Blog Directory
C# Game programming tutorial Blogs lists and reviews
Bloglisting.net - The internets fastest growing blog directory Blog Directory - photarium
blogarama - the blog directory Blog Toplist
Blog directory Computers (Linux) - TOP.ORG
Blog Ratings si.blogs
Blogz game, development, programming, c#, visual studio, tutorial, source code
On our way to 1,000,000 rss feeds - millionrss.com
RSSMountain
TopBlogLists.com - Blog Search