Hello there! Welcome to Programming Shenanigans! This is a blog documenting the trials and tribulations of two novice programmers as we try to navigate the weird and wondrous world of game coding.
Tuesday, May 18, 2010
Game Logic of Tetris
Once the game state entered the activegame, the first thing the game would do, is instantiate the playing field. This consisted of rendering the HUD that contained simply a window for the game world array, a fancy little title and a window to display what the next block would be, standard Tetris stuff. It would than create an element in every position in the rectangular array. The reason for this was twofold. First, when I was designing this system, I thought, though it may not be much, perhaps it might be more effective to pre-create all the blocks at the beginning of the game and never have to worry about creating and destroying objects throughout the code, it might even improve game performance during play, since that piece of CPU allocation never had to be dealt with again for the lifetime of the game. Though that seemed like a valid train of thought, I retroactively came to the realization that memory is a much more precious resource than CPU; objects should only be in existence when required.
But what’s done is done, that is how the system is. So the way I differentiated between my various blocks was through the use of an int identifier. A field inside the block class would keep track of the color code of the block. Each color co-responded to a different tetrimino. This color code would also be kept inside a global variable, in the form of Currentcode and Nextcode. The second variable contains a randomly generated number that displays an image showing the players what the next block would be. Once it’s time for the next piece to drop, the Currentcode is set equal to the Nextcode, and a new number is generated for the NextCode.
The game itself runs even without user input. The active block is always falling down. What the user can control however, is whether or not the block moves sideways at all, as well as the ability to speed up the rate that the block can fall. For the blocks fall speed, I had a counter that read the GameTime and would only allow the block update method to run once every second. User input would change the time the amount of time in between each update cycle, in milliseconds.
The way the lateral movement was implemented was to check for one of the left or arrow keys to be pressed. One key press would allow the block to shift one column over. In retrospect, I should have implemented the lateral movement the same way I did the vertical movement. Where keeping the side arrow keys depressed continuously would allow the game to call a lateral update method periodically.
The rotation of the blocks is a completely hard coded feature. For a specific block, in a specific orientation, where would each of the 4 blocks go in the next rotation. For laziness sake, only clockwise turns were implemented. If I were to redesign this, I would have used a database of this information that would have been called by various turn methods, rather have hard coding nested If statements.
One problem I encountered was that when I tried to replace the contents of one block with the contents of another, the objects would be passed by reference. As of the writing of this post, I’m still unsure as to how to fix this. The hack that I had to put in was to individually update the fields of the blocks.
I hope this provides a good introduction of the thought process I went through when making this game. I apologize for the lack of detail, seeing as I only thought to write this all up after the fact. For my next project, documentation is a priority.
Sunday, May 16, 2010
Tetris - ROTATIONS
What i did was, to make a routine for each block that calculates where each of the 4 squares (all tetris blocks are made of 4 squares) would rotate to. I.E. what to add to x,y values. As you can probably guess, the worst case scenario has 3/4 blocks moving with 4 orientations for each block! Lots of horrendous brute forcing. The worst part was all the checking, in bounds and not over other blocks, that had to be done as well.
Initially, we had the idea of having a BlockKeeper (4x4 class of squares) that would fit al the blocks within it resulting in a common usable rotation between them all. However, deciding it would be better to have individual blocks, we scrapped that idea. Horrid.... Must have stuck to that plan. GENERALIZATION IS GOOD!
Need too make more general methods to override for later use!
Thursday, May 13, 2010
It's all about that score
So in my last post, I discussed getting a Menu Image to display on the screen. At this point, we must add some functionality to the program. First, consider the situation the game is in. When you take in user input to either start viewing the high score or being paying the game, you no longer care about anything that happens in the main menu, you only care about the things that occur in the option that the user chose. So in this way, we should keep all 3 of these states separate. In the past, I had always used simply an INT variable to keep track of the state, performance wise, it’s a good idea, however for maintenance and code legibility, I decided to create an ENUM to encapsulate the 3 states that I wanted my game to be in. The first state would be the main menu, second would be the game, and third would be the hi-score window.
One major advantage in using these states is the way the Update method is called. There is only one update method that constantly runs, but using states, we can put all 3 modes into one method, and then divide the method into 3 independent sections that run only when an the variable tracking the state passes each of the respective modes.
Moving to another state
Within the update method provided, each of the three modes will have a method that is called only when the mode is active. The method for the hi-score mode is the one I chose to start making first, for the obvious reason that it is infinitely simpler than the game mode. For storing a high score, I decided to record the high score in arrays containing the name and score.
As far as printing it on the screen goes, that was a more difficult task. In beginner programming classes, you were heavily dependent on Conesole.WriteLine(“”) to give output. In XNA, no such method exists. There is a similar function, albeit one that is far more complicated. You call it from SpriteBatch.DrawString();. To be able to use the Draw String method, you must first create a font object and load a font into it. It is done much the same way as one would load an image into a Texture2D object. Now that we have a hi-score in the game, we must find a way to track the high score even when the game is off. I did this the only way I knew how, by storing data in a CSV(Comma Separated Values) file. The high score update method would check for the existence of a CSV file that stores the current hi scores. If no such file exists, it would then proceed to create one and initialize all values as something standard. Reading and Writing external files is done using the StreamReader and StreamWriter classes.
And finally for the high score state, you have one last method that checks for the ESC button being pressed. When it detects this, it changes the mode variable back to main menu. And thus, the high score mode won’t run on the next cycle.
Wednesday, May 12, 2010
Let’s get the balls rolling with Tetris
Despite what I just said about Tetris being really easy to program, that is a misconception that I quickly dismissed, in abstract terms, it’s easy to understand, but when you break it down into code, there are so many steps to consider in even the simplest step of the game. It’s scary to think about how bad a game like Pac-Man might be, where there is AI involved.
Regardless, I felt that diving headlong into coding the gameplay would be redundant. Seeing as this whole project is a way to push my programming experience, I felt that I should really try to reproduce Tetris in its entirety, not just the gameplay of it.
When taking on a project of this magnitude, there should always be a fair amount of planning before the first line of code is written. I only realize this in hindsight. Though my professors always stress the importance of this, It never really sinks in until you experience it all for yourself, more on that in a later post.
Like the noob that I am, I just jumped right in and created a game project in Visual Studio without much planning, hoping to wing it as I go, I had a rough idea of what I wanted to do as I went along. The first thing I wanted to do, was to display an opening screen onto a window. To allow this to happen, I recreated much of the Sprite class that was covered in those tutorials I mentioned in the second post. For those of you who haven’t read that tutorial, I will run over the key concepts of that topic.
Sprite Class
An object of the Sprite class will have various variables and methods available to it to allow it to be able to display a 2-D image onto the game window. This will be a super general object that really has no function to it. The sprite class will be widely inherited to allow for Sprite objects that are really far more beefed up and are really the core of what I used to build my game. Though, in the future when the games get more complicated, it may not be wise to inherit the Sprite class to create your gameplay objects, it might be more prudent to create Sprite objects inside your more prominent classes.
To see the specifics of this class – take a look at the Source Code I will upload.
At this point in my programming, I did not know how to print Text to the screen, So I simply printed an image with pre-rendered Text on it.
I’m going to split the discussion of the Tetris project down into smaller posts, So that you guys don’t have to deal with giant walls of text.
Getting started with XNA
So there I was, filled with ambition and completely clueless. My first train of thought was “hmm okay, making games, let’s forget about gameplay for now, and start basic, draw a dot on the screen, and control it with arrow keys.” Of course that was a far cry from anything I had previously done in class. No matter how advanced my coursework got, it was always still just console applications. Feeling overwhelmed, I decided I would consult a friend of mine who was more experienced than I in this field. His interest in this was enough that rather than just giving me advice on this, he is now my partner for all future developments, all documented in this blog.
Though more experienced than I, working on something of this nature was still outside his field of expertise. When in doubt, hit the Google button. It’s a philosophy I follow almost religiously. After spending maybe 5 minutes on Google, I found the website that would allow me to get a foothold on game programming, http://www.xnadevelopment.com/. This blog has excellent tutorials starting from complete scratch and advancing all the way to what I considered at the time advanced programming techniques such as RTS style unit selection and a primitive manner of 2-D collision detection.
While running through these tutorials, you really feel as though you accomplished something. From only programming applications that run in the console, to seeing your little wizard guy shooting fireballs, is an amazing moment. The XNA framework takes care of a great amount of grunt work required to make a game. So the transition isn’t as bad as many would think.
Beginning of the Shenanigans
Why hello thar,
For the first official post of this blog, let me tell you a little about myself and my partner. My name is Xin, We are soon to be 2nd year Electrical/Computer students at University of Waterloo. I am a complete novice at programming, my only exposure to the field is really the one course that I took after entering university. The code I post and the points of view i put up will reflect that. My thought process will be that of somebody figuring everything out for the first time, any beginners reading this will feel right at home with the level of content that I post. For those more advanced, who knows, maybe I'll be able to give a fresh perspective on a tired subject. Feel free to comment and criticize my work.
The language that you will be seeing all our code in will be C#, as that's what we use in school. In the future, we might switch over to C++, but that's distant in the future, mostly owing to the fact that we will be using Visual Studio to do all our work in. We will be using the XNA framework to code all our games for the foreseeable future. XNA only has full support for C# so we wont be leaving C# until we're good enough to code without depending on the XNA framework.