About this blog
Documenting the process of breaking down game development into small task.
Entries in this blog
An old boss of mine once told me "Software is never finished. It's just abandoned." What he meant by that is that there has never been any software where everyone invovled has said "This is perfect. We're done. There's nothing more I'd want to add."
In that sense, PlanetBall is done. I'd like to make the asteroids spin. I'd like to make the sound engine use ogg vorbis files instead of huge wav files. I want to clean up the key assignment code. But I'll do that on my next game. I'm going to call PlanetBall done.
And you can have it right here: http://www.brouelette.com/downloads/
It's a java game so you need to have Java installed and in your path. TO test this just open up a CMD window on your PC and type:
If you see something like :
java version "1.7.0_01"
Java(TM) SE Runtime Environment (build 1.7.0_01-b08)
Java HotSpot(TM) Client VM (build 21.1-b02, mixed mode, sharing)
Then you're good.
If you see:
'java' is not recognized as an internal or external command, operable program or batch file.
Then you need to install either the JDK (if you want to write Java programs) or the JRE (if you just want to run them) from here:
As I've mentioned in this blog PlanetBall is a 2 player game where both users use the same keyboard to move their planets around in space.
The concept is "What if you were playing the game Pong. But instead of the paddle, you were the ball?"
One player uses ASDW to move and B to brake. The other player uses the arrow keys and Number Pad 0 to brake.
If you capture a planetoid of your own color you gain 10 points.
Capture the wrong color you lose 5 points.
Bump the other player and you both lose 2 points.
Capturing your own color asteroid gives you 25 points
Capturing the wrong color loses 15 points
If you get sucked into a black hole the nicest thing which will happen to you is you lose 20 points.
I have 4 levels of increasing difficulty. I was able to use OpenAL to get the sounds working and overall, I think it's a playable game.
It's all coming together.
In the past week or 2 I was able to add a black hole to the game. At first, the only consequence of touching the black hole is that you would bounce off of it using the inelastic collision algorithm I finally got working. You would also lose 20 points.
But then I asked some friends to play it and every one of them said the same thing: "Does the black hole suck you in?"
Ok, I need to add gravity.
Thinking back to my physics class in college I remembered that the force of gravity is G times ((m1*m2) / R^2). I already had mass defined for my entities because I needed it to calculate the inelastic collisions (billiard ball bouncing). So I plugged in the gravity calculation and would you believe it, the planets started flowing towards the black hole. WIth a bit of tweaking to the G gravitational constant I was able to make the planets be drawn to the black hole at a force which caused some change to the game mechanics without being too difficult for the user.
So what should happen when the planet touches the black hole now? I added an animation to show your planet being shurnk down to nothing. Your planet then reappears at a new place on the board and it grows back to full size (and you still lose 20 points). But when I was testing it odd things happened. The planet would bounce wildly all over the screen. When I caught a collision with the black hole I had to do the following:
Turn collision handling off for that planet (Check)
Disable player control (Check)
Set the X and Y speed to zero (Check)
Animate the shrinking (Check)
Find a new spot on the screen which is away from the other player and the black hole (Check)
Animate the growing planet (Check)
Enable collision detection (Check)
Enable player control (Check)
So where the hell was the bouncing coming from? It turns out that gravity works. When you touched the black hole the R component (distance between the entities) was very small which made the force of gravity very large. Gravity was literally tossing the planet back and forth across the sky. This was quickly fixed by temporaily turning gravity off for the captured planet while I did the animations and repositioning.
Meanwhile, as I was adding the animation code to both the player entity and the planet entity I found myself copying the same code into two different objects. Any time you see yourself repeating code it's a good sign that you should push that code down into a base class. I see more refactoring in my future. This is another great example of why I'm building a proof of concept project before my main project. You only learn this kind of thing by writing the code and trying things out.
Finally, I made some changes to my OpenAL sound engine so I now share the same sound engine across all my scenes. One of the many benefits of this is that I can have one piece of music play across multiple levels. The sound doesn't restart every time you replay a level.
I think my proof of concept game is nearly done. This entire project was created so I could learn about game loops, double buffering, the update-render-paint loop, image manipulation and other basic game progamming concepts. I've certainly achieved that goal. What I got out of it was a huge learning experience and a fairly fun mini game. I think the next step will be to make the engine handle scrollable tiled backgrounds. Then it's time to move on to building [secret awesome game idea] which spawned this process in the first place.
Programming is the act of breaking up a big problem into tiny steps. This weekend was spent coding tiny steps:
1: A state machine.
Now I can have a menu system where you enter X number of text entities with their x/y locations. These "SelectableEntity" types have 2 images. One for selected; one for unselected. They also have an abstract doAction method. The state machine keeps track of which menu item is selected and handles the up and down key press to change which item is selected. It also catches the enter key and fires off the doAction method of the currently selected choice.
2. Next scene, what a pain.
Because I'm using property change events to fire off timer events and collision events I ran into a lot of interactions which I hadn't thought about when moving to the next scene (level). Now the scene manager knows to unregister the listeners for level X when we move to level Y. I also more correctly clean up the Open AL buffers and sources so I can load the new buffers and sources. Now that I have a generic sound engine it's very easy to load up and play new sounds. I'm using SFXR to create cool 8 bit style sound effects. Finally, the paint command in the game loop was having a concurrent modification error when I was deleting the old entities and entering the new entities for the new scene. That took a little clean up work as well.
3. Build a new level.
Now that the engine and scene manager are becoming more mature I shoudl be able to build new levels more quickly. Here's what I have so far for my proof of concept game Planet Ball.
Title Screen : Press any key to begin (I need to add an exit command and credit screen)
Level 1: Green and Red planets can be controlled to capture the appropriate colored mini planet. Capture your own color gives you +10 points. Capturing the wrong color gives you -5 points. Bouncing off the other player's planet subtracts 2 points from both scores.
Level 2: Same as Level one with different music and your planets are smaller. Also, at random times a small jagged asteroid of a player color will cross the screen. Capture your color gives you +20. Capturing the wrong color subtracts 15 points.
Level 3: Same as level 2 but now I have a slow moving black hole. Touch the black hole and you lose 30 points AND you bounce off at a high speed which can cause all sorts of chaos.
Clean up the random start code for the occasional asteroids.
Clean up the code which determines if the asteroid is fully off the screen.
Make the asteroids spin.
At this point I have to decide how far I want to go with the proof of concept game. My real goal was to learn about the game engine and also to develop a generic 2D game engine which will allow me to write a future game idea. That future game idea needs a scrolling tiled background and some additional collision logic. However, Planet Ball is becoming a fun game. We're even going to have a single elimination Planet Ball competition at work. So I'd like to get at least these three levels completed.
Next goal: Can I create a simple Breakout style game using this engine? If so then my game loop, entity code, scene manager, timer event and collision mapping code would seem to be pretty complete.
Add tiles backdrops and scrolling tiled backdrops.
Add testing code which can jump directly to a particular scene.
Add a debug screen which shows me the collision rectangles (done), Frames per second, skipped frames and memory usage (not done)
Wow, that seems like a lot more coding than I had thought. I'll just keep eating this elephant one bite at a time.
I wanted to make my game code seperate from the generic engine code. The first Idea I had was to have a completely generic engine system which I could use to load any one of a set of games which I would write later. The engine could access a number of jar files, each of which had game code in it, and the user could select from any of the games which ran under this engine.
I had a "Games" directory underneath the directory with my engine jar file. Into that Games directory I would place several jar files each one with a different game. The engine would then look for all files with the file name *.jar, load them as a ZipFile object. Once I have that object I could look at the Manifest file for each jar. In that manifest file I added lines for "Loader Name", "Loader Image Path", and "Game Config Class Name".
The Loader Name is what displays in the game selection panel. The loader image is the image which shows below the game's name. The game config class name is the file in the jar which extends my GameConfig class. That's my entry point into the game via a generic class which the engine understands. When the user selects the game I load that jar file into the classloader and then build (via reflection and introspection) an instance of that game's class which extended GameConfig.
Here's a test where I had one legitimate jarfile for PlanetBall and 3 fake jar files with nothing more than the display data in the manifest and the loader image. This was just a test of the technology to see if I could do it.
So that's a cool idea and it looks great. I'm building a generic game engine which can run any number of games all of which reuse the generic code. But how marketable is that? Although it's a cool technical idea, I know from personal experience at work how often architects will design overly complex systems which leave open the possibility of doing anything they may want to do in the future while sacrificing the ability to easily do the very thing you set out to do in the first place.
Am I really going to ask a potential customer to download the engine code separately from the game code? Wouldn't most customers simply want to play the specific game they asked for?
It was a cool idea and an interesting technical problem. But it's not a great idea from a customer experience point of view. I went ahead and simply added an entry point class with a main method which created the GameConfig class manually and started the game. Cleaner, easier, and all the code can stay in one jar file.
HOWEVER: This wasn't a complete waste of time. In order to make my basic game function I had to completely seperate the engine code from the game specific code. That refactoring cleaned up my code quite a bit so this little programming "side quest" actually did spawn some good ideas.
Once again. I've benefited from making a prototype. If it doesn't work then throw it away and learn from it.
As I look through the forum post here I often see a questions along the lines of "I have an awesome game idea but don't know how to program. What language should I learn?" Those of us who write code for a living realize that learning to code is a journey which takes years (and truely never ends). Also, even though I've been writing code literally for decades, when diving into a new area like game programming there's still a learning curve to go through.
This blog will look at that learning curve.
There's a great article here on gamedev which talks about how you should forget about trying to write the next great MMORPG and instead try to write Pong just to build your skill set. Coincidentally enough, my first game project was essentially a Pong game as well. I call it "Planet Ball".
The concept is simple. The 2 players each control a planet. The planets can accelerate in whatever direction they move their controller and they have a brake key which will slow the planet down quickly. There are small asteroids of a matching color. Every time a player captures a planet of a matching color they get 10 points. If they capture their opponent's asteroid they lose 5 points. If the planets bump into each other both players lose 2 points.
Let's look at what bits of code need to be written just to do this simple game:
- A game loop which can handle the update, render, paint sequence and maintain a consistant number of frames per second.
- A double buffering painting system.
- A series of Entity classes (essentially sprites) such as (base class) Entity, MoveableEntity, ControllableEntity etc.
- Collision detection
- A score system.
- A timer event system to start and stop the game
- A system to assign key strokes to an entity action.
- If I want a title page then I need a way to define each scene (Title, game play, config, credits, etc) and a scene manager to know which scene plays in what order.
- I need sound when objects collide and for background music.
Even this simple game can become overwhelming. As it turns out, I wrote the game twice, and for reasons to be explained in the future, I'm about to write it a 3rd time. But lets start with the first iteration.
I code in Java at work so I'm most familiar with that language. So I bought the book "Killer java game programming" by Andrew Davison, I read the preview of the book on O'Reilly's web site and I liked the way he went into detail on the timing of the game loop. For example, I had no idea that the standard Java call System.currentTimeMillis() is only accurate to about 50 milliseconds. That only gives you a granularity of about 20 frames per second. You need to use getNanoTime and then divide by 1000000 to get accurate milliseconds.
I chose my weapons and started to code. Everything I used was free:
Java jdk to compile and build
Eclipse editor to write code
Gimp to create images
XMind to keep track of task and ideas
NMind to design class diagrams
I wrote the first version of the game and it worked. But the code was too tightly integrated. The paint command in the game loop knew too much about the specifics of the objects, the planets, the score text and so on. A better design would be to have the engine be completely agnostic as to what the game is. Are planets colliding or are bullets hitting a target? It shouldn't care. My code was far too knowledgable about the specific game. If I wanted to write a breakout style game next I couldn't reuse much of my code, I'd have to refactor too much. I should be able to have a single jar file with the engine code in it and then have my game specific code simply reuse that jar.
So I threw the first draft away and started again.
In extreme programming this is called a technology spike. A technology spike is when there's an aspect of the project which you don't know how to do. So you build a prototype to learn how to do it. But that prototype is never very optimal because as you're writing it you're learning. So once it's built you throw it away and write it again now that you understand the problem better.
In the next blog I'll talk about the second version of the game and what I learned from it's design.