Sunday, March 9, 2014

Game A Week - #1 - Pong

I've read about many different indie developers making a game a week, but it was this recent article on Gamasutra that really sold me on the idea.  I decided that I would try to do it myself, using it to strengthen my game design skills as well beefing up my Dart knowledge.

I was tempted to tackle this challenge using Unity, as I have vast knowledge of the ins and outs of that engine, but in the end I decided it would be more educational for me to use something I was not very familiar with.  I figured it would force me to think outside the box to come up with solutions.

Here is how the past week went: (Play the game here!)

The first issue was figuring out what game to make.  I assumed that making a clone would be best to start off with, and a very simple one at that.  Pong seemed appropriate for many different reasons.

Once I had chosen the game,  I had to set up the basic Dart project structure.  This was rather difficult just because of the Dart Editor.  (I had decided to use the Dart Editor instead of Cloud 9 while I learn the ins and outs of Dart.)  Dart would constantly take up massive amounts of RAM (2.3 GB) and CPU (87%), which would cause it to come to a crawl and even crash repeatedly on my PC.

I also had quite a bit of difficulty trying to load assets in Dart.  I'm developing the base engine as a Dart lib, so I first tried putting the shader files directly in the lib folder.  I couldn't figure out any way to actually access them at run-time, so I tried putting them in the asset folder, since that is what is described here.  That also didn't work since it requires pub build which apparently doesn't work on Dart libs.  So, I ended up simply putting them in the example folder.  It's not ideal, but it works for the present.

I eventually figured out how to make the Dart Editor stable.  I deleted all of the metadata under C:/Users/[user]/DartEditor and then deleted all of the packages folders in my project, since they are generated by Dart anyway.  I rebooted the Dart Editor and pulled in my project.  It ran smoothly after that.

I didn't get as far as I had planned since I was battling against the Dart Editor most of  the time.  I did end up with a square and triangle rendering via WebGL in Dart using my own custom shader loading.

The next major part to implement was an actual game loop instead of having one single Render call.  I set up requestAnimationFrame to achieve this, which was relatively straight-forward.  It currently calls both Update and Render at the same framerate.  I may change this in the future, since most engines/APIs have Update called much more often than Render, but it works fine for me now.

I then created a GameObject base class as well as Renderer and Transform components that can be attached to GameObjects.  I updated the square and triangle test from Monday to use these new structures which greatly simplified the set up code.

A small tweak was made so that the WebGL rendering context (Canvas) will be automatically resized along with the browser window.

It doesn't really look like a productive day, but I actually accomplished a lot by putting in those base components.  It should make all future work much easier.

I didn't get much time to work on the game due to other things in life, but I did get some important pieces in. I created a Camera component to help alleviate the hassle of dealing with projection and view matrices all the time.  I created a Scene manager to manage GameObjects and to automatically call their Update and Render methods.  I also created a very simple Color class that acts as a simple wrapper around Vector4 to provide static properties to commonly used colors.  The square and triangle test is now only a few lines of code to set up.

It was another short day for me, yet very productive.  I implemented Keyboard class to handle all keyboard input.  I created a Paddle component that uses the keyboard to move up and down. I created a Ball component that moves across the screen and detects collision with the screen edges and the paddles.

I didn't even touch Pong on Friday because I went out for pizza and beer with my girlfriend. I don't want to sacrifice my social life for the sake of a game a week.

I spent most of the day going for a long bike-ride.  I tried fixing some issues, which was mainly fruitless.  I tried forcing the canvas to have focus as soon as the webpage loads so that it immediately can accept keyboard input.  It works most of the time, however it doesn't work when the browser is first loaded, which is quite common when debugging using the Dart Editor.  I tried fixing some wonky collision behavior between the ball and paddle.  I made it a little better, but it's still nowhere near perfect.  I also added in simple scaling to the Transform component to allow easily re-scaling the paddles.  It works well right now for axis-aligned 2D shapes, but it may have to be re-visited in the future to be more robust.  Also, scaling currently only scales the rendering mesh, not the collider mesh.

I spent the afternoon at a friend's house playing various board games.  I set up a scoring system with normal HTML used for displaying the score.  I implemented a crude AI system so that you are playing against the computer.  This brought to light a big bug with the collision system.  I had to put in a hack to alleviate that.  I also added in a random element to the ball velocity after a player scores.  I then adjusted collision between the ball & paddles with the screen edges.  Finally, I deployed the game to my server.

Play the game here!

Final Thoughts
I was surprised by how little time I actually had put into the game over the past week.  It is an incredibly difficult task balancing my time between my full time job, my bike-riding, my girlfriend, my friends, etc.  I had hoped to accomplish much, much more.

I have an entire list of features I had hoped to put in, including:
Networking - Allow multiple players across various web browsers
Different Paddle Shapes - Not just | shapes, but < and > and curved surfaces
Increasing Speeds - Make the ball go faster as the score increased
Varying Angles - Make the angles of the ball not always 90 degree bounces
Sound - Simplistic sounds to indicate when the ball hits a paddle
Circle Ball - Use an actual circle mesh for the ball instead of a square
Scale Properly - Currently the game doesn't scale the collision zones with the visible window

In the end, I did get a working (albeit simplistic) version of Pong up and running via Dart and WebGL.  I suppose that's as good of a first Game A Week as I can get.  I'm already looking forward to the next game! (Whatever it may be.)

No comments: