This is a clone of the Original Frogger by Atari. This is my first game using C#. I hope, after you read this article, you take with you some skills needed to make your own fun games. The clipart is believed to be of public domain taken off of free clipart sites. I have used timers and
OnPaint events to draw the images using the GDI double-buffering to reduce flicker. I have used both Quartz.dll and my own personal class (tonysound.cs), which I wrote an article on, to play sound events and background music. Click on my articles link to find this article.
I have set up several variables for speed as you can see in the code
variables. The speed variable is to control the increments of the
Image object being drawn. For instance, if I want the object to move slow, you would have a low number increment so it does move across the screen as fast. For each level of the game, I will add one to the current speed. This will increase the object movement increments and make the object appear to be move faster.
X Coordinates The X coordinates like
Lane1var1 and so on are for the X coordinate on the playfield. Each object has a location of its X,Y coordinate. So if we move the x, it will obviously go either left or right. This is how the frogs and cars move. I increment the x for the
Image object inside the timer, for example:
As you can see here, I check to see if the first log in the first row is less than 672. If it is, then I add the
logset1speed to it causing it to change its x position. Otherwise, I reset it to its starting position as -71. I do the same for the other logs as well.
Now, the Frog I move get his x value inside the
KeyEvent, and then when the
timer1 calls the
drawstuff(g) function, it will get the updated x value of the frog and plot the graphic accordingly.
public void OnKeyPress(object sender,System.Windows.Forms.KeyEventArgs e)
if (e.KeyCode == System.Windows.Forms.Keys.Left)
PlaySoundFlags.SND_FILENAME | PlaySoundFlags.SND_ASYNC |
What happens above is the
keypress event is fired with each key press. I then check to see if the left arrow is pressed, the right arrow and so on. I then move the frog's coordinates based on the arrow. If it's left, then I subtract its move increment from its original x location. If it's right, then I add.
Bool values for the Target Taken and Snake Taken.. I have
bool values like
bool Target1taken and
bool Snake1Taken. What this does is sets a
false to determine if the frog can enter the home base. If the target is taken, this means the frog has already made it here and can't reenter again. Now if a snake is there, well he kills the frog, so we test to see if he is there, so if the frog jumps in the space he dies.
Static variable for score and why... If you are wondering why I made the score variable
static, here is why. If you are on another form that uses the same namespace, you can't use the variable from the other form without making an instance of an object. So I cheat a little and make the variable of type
static, then all I have to do is type the formname.variablename; for example,
Form1.Score, and I don't have to make an instance of the form, in say,
Form4 at all.
WHAT'S THAT NOISE? Well, just like pretty much any game, you have sound events and you have background music. Well, here is no exception. If you read my article about adding sound to C#, you will get an idea of what I have done. I used my class tonysound.cs that uses the winmm.dll to play my sound events, like the frog hopping and dying. Now, the background is a little different. You see, winmm.dll doesn't support sounds being played in parallel. So I had to come up with something a little different for the background. I hear you over there asking how, so let's dive into it.
In order to use Quartz.dll, we have to add it to the references of our project. To do this, we go to the main project name in Source Explorer and hit Add reference. When the dialog box pops up, we then hit the Browse button and go to windows\system32 directory and find the quartz.dll. Once it's added, then hit OK. You will then see
QuartzTypeLib has been added. Now we are ready to get busy with making some sound play with this cool DLL. Well, like pretty much everything else, we need an object, so let's make one.
public QuartzTypeLib.FilgraphManagerClass mc;
Now that we have the object, we need to do a few more things before we actually get the sound playing.
QuartzTypeLib.FilgraphManager graphManager =
What we have done above is made a
Graphmanager needed for playing the sound. You will notice, I assign
mc the value of
graphManager which has been recast to the type of
filgraphManagerClass. Now that this is done, we are ready to rock and roll with the
mc object that's going to play our sound for us. So we have to make thread that calls
soundbackground to play our sound.
backgroundplay = new Thread (new ThreadStart(soundbackground));
Before calling this thread, we want to make it run in the background. So, when we close our program, we do not get processes not closing. So, to do this, we do the following before starting the thread:
mc.WaitForCompletion(-1, out soundvar);
Image Object and Checking Their Bounds
If you look under the
#region section called
Images, you will see where I have made some image objects. These are the images which you see on the screen. To test the bounds, we have to make image in the form of a rectangle. Look at the
#region Bounds and you see the declarations.
public System.Drawing.Rectangle RectangleFrog;
public System.Drawing.Rectangle RectangleCar3;
public System.Drawing.Rectangle RectangleCar2;
public System.Drawing.Rectangle RectangleCar1;
public System.Drawing.Rectangle RectangleFastCar;
public System.Drawing.Rectangle RectangleTractor;
public System.Drawing.Rectangle RectangleCow;
Now that we have declared the object, we need to define it. So, we do the following. You will see this in the
tickme sections. I could have placed it elsewhere, but I didn't.
RectangleCar1 = new Rectangle( Lane1var1, 312, Jeep1_Lane1.Width,
RectangleCar2 = new Rectangle( Lane1var2, 312, Jeep2_Lane1.Width,
RectangleCar3 = new Rectangle( Lane1var3, 312, Jeep2_Lane1.Width,
RectangleFastCar = new Rectangle(Lane2var,350,FastCar.Width,FastCar.Height);
RectangleTractor = new Rectangle(Lane3var,370,Tracter.Width,Tracter.Height);
RectangleCow = new Rectangle(Lane3var2,370,Cow.Width-10,Cow.Height-10);
Now that we have our rectangle bounds defined for our objects, we can test to see if they intersect with other objects. This is useful because, if say the frog intersects with the car, then we obviously want the frog to die. So C# makes this easy for us by allowing us to use a function called
IntersectsWith. If you look in the
tickme function, you will see where I check to see if the frog is hit by cars on logs etc.
What the above does is it checks to see if the frog image touches one of the cars or the cow or the tractor. If it does, then we are going to reduce our lives by one and then call the
lives function to see if we are out of lives.
Double Buffering for Graphics
I will not go into great detail on this because I wrote an article on it already. Please look at the AntiFlicker Graphics article here. After reading the aforementioned article, you will see you have to enable double buffering because it is off by default. Also, you have to make an
onpaint event and then call the
DrawStuff function from a timer to get the graphics to move without flicker and lag.
Keeping Score in a text file:Reading Method
The high-score is read in line for line from a simple text file. I thought about using a database but scratched the idea simply because I didn't see the need. I also thought about making the file binary which I may still do in future versions of this. Yeah, I know you're saying stop rambling. I want to see how this is done, so here we go...
StreamReader s = File.OpenText("Score.txt");
MessageBox.Show("Can't find Score.txt");
So, let's take a look at what is going on here. First, we make our
catch so if the score.txt file is missing, then we want to tell the user the reason the program has crashed. We then make sure up top we have
using System.IO;, so we can use the
StreamReader. So, we make a variable of type
StreamReader and link it to the path of score.txt. Once this is done, we then assign
line1 the value of the first read, which is line one. Then do the same for
line2. Then I take and convert
line2 which contains the score to an integer and store it in the
scorecompair, so we can compare the high-score to the current score later. Then, I simply take and place the high-score name and the high-score score in their respective label text.
Keeping Score in a Text file: Write Method
Well, you are probably wondering how did we go about making this score.txt file? OK, if you look closely at the code, you will notice that if the
scorecompare is less than the current score, then the current player has the highest score, so we simply display a form that gets the
score; remember, we made it
static so we could use it? Well, after we have the score, we want the user's name. After all this is in place, we have a submit button that does the following:
private void button1_Click(object sender, System.EventArgs e)
FileInfo f = new FileInfo("Score.txt");
StreamWriter w = f.CreateText();
Note from Author
The Quartz.dll is pretty interesting to mess with. I realized, with it, I could easily make a media player. I thought about making one of my dogs wag his tail as the music plays. This project was pretty fun for me and a great learning experience. I always wanted to learn C# and make a game. With the help of Code Project's members, you know who you are, I was able to put that dream into reality. One thing that still puzzles me is winmm.dll. I have heard that it will play two sounds in parallel from individuals on IRC but I have never seen any working code on how it is done. Because, from what I see, it doesn't have a blocking method, so when another event fires, the one that was last called takes priority. Another thing that kills me. I wanted to do Direct X and still will. I might have to get the newest version of Visual Studio though, but anyway, here is the deal. I have tried every method I know of to get DirectX to install correctly. It simply refuses to do so. I followed several methods like registering the DLLs, copying the DLLs, and so forth. So after I get a little less busy, I'm going to uninstall VS and reinstall it all and see if that works. One other thing. I am now a big fan of timers. They made my life a lot easier. Oh, I did learn one interesting thing. If you include
using System.Diagnostics;, you can then call
process.Start("a url"); and it will let your users email you or go to your website or whatever.
Hopefully after reading this article, you will have taken with you some ideas to make some fantastic games for your family and even yourself. I always wanted the old style frogger and sure I could have bought it, but I figured why don't I learn how to make it, so there you have it. My version of Frogger. I'm sure there are bugs in this software and they will be corrected as I find them. If you like this code, do me a favor. Send me an email to Junkmail4tony@comcast.net and let me know how you like it.