Pong Challenge

Gamedev.net is starting a challenge forum, and the November 2017 challenge is to re-create Pong.

The full rules on the site are here, with instructions for what must be included.  I’ve written a few Pong clones over the year, so thought this would be a fun challenge to implement.  All total this took about ten hours including the time for this write-up, spread across three evenings.

First Session: Basic Pong.

The rules require:

  • The game must be 2D
  • Art must be your own
  • Start screen
  • Key to return to start screen / abort game
  • Score system
  • AI player
  • Sound effects for ball striking the paddle and for when a player scores
  • Gameplay must happen on a single screen
  • Unique element that makes the game stand out from others

They also require a link to the executable and screenshots, plus request a small writeup including both the good and the bad, and source code link.

So with those rules in place, I started with the basic 2D Pong. I decided to use Unity since it is a great tool for this sort of work.

First stop was Google to look up what Pong is supposed to look like.  There are plenty of pictures of the arcade cabinets, wood on the outside with a big yellow and black “PONG” title on the top.  The graphics have lines along them for the screen’s scan lines, with two paddles, a ball, a dotted line in the center, and the score up top.  I noticed that the ball could go through the numbers. And the game originally went up to the first to 15 points.

I fired up Unity and created a project and the simple directory structure needed for the project.  This is a fast process, perhaps 5-10 minutes tops.

I went to Photoshop to create the gameplay art.  First I created the boundary of a screen so I knew the sizes to work with. Then I created new layers and drew a small square ball, two rectangular paddles, a dotted line in the middle. I also created a layer that simulated scan lines, it was a 4×1 custom brush used to fill the entire area that alternated black and white, set as a partially transparent layer.  I renamed them all to useful names and exported all the layers (trimmed to size) inside my Unity project.  I thought about making text glyphs, but decided to use a simple sans-serif font for the start screen and the scores.  The whole process took about an hour before I was satisfied.

Next up in Unity I configured all of them to be UI sprites and set them to use a common sprite sheet.  I created a UI canvas for the game, and dropped in all the sprites so it looked approximately like a game.  I also positioned the score areas and choose a font that I liked. This took about a half hour.

To keep things simple I created a single script named “pong” that I attached to the canvas.  Inside the script I created variables for the moving elements: the two paddles, the ball, and the scores. I also created and exposed some variables I knew I would need to adjust for where the top and bottom walls were located.  I saw that the walls were not drawn on the original Pong, so I figured I don’t need them either.

I spent just just over 90 minutes writing the game logic, iterating over the game settings to tune the ball’s maximum speed, tuning how much the ball accelerates per bounce, and how the AI would chase the ball but not always keep the ball precisely in the center of the paddle.  For convenience I assigned both sides to run the AI function — six lines of code — so I didn’t need to actually play the game to test things out.

The start screen was a very simple “Press Start”. Pong had no options, just two rotary controllers and a “start game” button. I thought about adding levels of details, but if it was good enough for the original it was good enough for me.

After that was done, I found some simple tone beeps from one of the free sound libraries and incorporated them to the game.

I went over the checklist:  2D game, my own art, start screen, score system, AI player, graphics, sound effects, and single screen display. I realized I was missing a back button and an audio sound on score, but those were easily addressed in the future.  It was nearly bedtime.

The basic game was built in about 3.5 hours total, in one evening between dinner and bedtime.

Adding My Twist

I’ve been working on VR and stereoscopic displays lately.

I started on stereoscopic displays back when the 3DS came out, I was on a team that got the hardware long before it was available to mainstream or even to most developers. The 3DS I used was a single large green board with all the chips soldered on, and the two screens mounted near a corner of the board. The controller used a Wii Classic controller plugged in to a socket on the board. That was for Sims 3 Pets on 3DS, where I spent most of the project working on the UI, making the 3D screen overlays look good when depth was applied.

Over the past year I had also been working on a VR game which used SteamVR and Unity to target the Vive, Oculus, and PSVR systems. So I was fairly comfortable with that.  I had also started my VR Kites project at home.  So the tools were mostly familiar to me.

I figured I could keep the 2D game, but the twist would be to place the 2D game in a full 3D arcade cabinet, just like the original.  Thus my 2D Pong clone could be faithful to the original Pong arcade game, be a 2D game, yet exist realistically in the VR world.

I pulled down the packages for SteamVR and for VRTK, the most amazing toolkit for rapid VR development. I also pulled a 3D video game cabinet model from another project. These were placed in the scene with the earlier Pong canvas.

The first issue was getting the Pong canvas to appear in the arcade cabinet.  My first attempt was to try to get the canvas to draw to a texture, but I gave up on that route. I figured it may be wasteful but I had power to spare, so I moved the canvas below the floor and created a new camera pointed at the Pong game canvas. The camera rendered to a texture, I referenced that texture in a material used for the arcade cabinet’s screen, and then I fine-tuned the position of the camera so the game looked good on arcade cabinet’s screen.

Next, the arcade cabinet outside texture needed to be fixed. As it was the arcade case was bright and colorful. I needed it to appear as paneled wood with a bright yellow title.  I wasn’t sure exactly how the UV mapping on the texture would work out, so I took a chance for the quick-and-dirty solution.  I opened the texture in Photoshop, added a wood paneling background in the direction that aligned with most of the texture, then erased the sections of the texture that looked like the sides, back, and top of the cabinet, letting the wooden texture appear instead. Saved this out, opened it in game, and it looked nice.  It didn’t look perfect, but it was good enough for the project.  I didn’t need to do any of the difficult texture painting that relies on the texture being mapped already, or any other trickery that I’m not good at.  Added the bright yellow title, wrote “PONG” on top, and called it good enough.  The texturing took me about an hour because I’m not an artist. I figure a real artist could have done that in minutes.

I dropped in the VR rig and hand controllers from VRTK. No need to re-invent them. I put on the headset, fired up the game, and watched as a life-size PONG cabinet played an AI versus AI game.

I added in a slider control and hooked it up where the arcade cabinet’s controller was. Since my model did not have an articulated stick or buttons, and this wasn’t to be a polished project, I didn’t mind that it didn’t exactly match. I tuned the min and max values for the slider, exposed a variable on my Pong script, and linked the controller to Pong. A slight modification to the game pulled in the player’s input. I also dropped in a button on the arcade cabinet to start the game.

The first thing I noticed was that even though the AI was good at the game, it was difficult to control in VR.  So my first tuning change was to make the paddles a little bigger, about 1.5x the size of the original pong paddles.  The game was difficult, but not too hard to play.

At that point it was bedtime again. About 3.5 more hours down, seven hours total.

Polish and Write-up

Now that I had my game that mostly met the requirements, it was time to go back and fix the few missing elements.  I needed a button to end the game, that was fairly easy. I needed another sound, again quite easy.

The game needed some tuning, so I adjusted the speeds for the ball and paddles. The ball moved too fast initially, slowed it down some, and made the ball accelerate a bit more (5%) every bounce. You can tune a game forever, I figured about an hour for this quick project was sufficient.

With the game out of the way, I needed to write a post on how I created the game.  The writing was easy, but it took some time to upload the videos I took during the process.  About an hour later, I’m wrapping up the document you’ve just read.

Since they asked for these specifically, I’ll call them out:

What Went Right

Pong is a simple game and I’ve implemented it a few times before. I knew it is easy to over-engineer. It is easy to get carried away with encapsulated objects for a ball, reused complex objects for each paddle that have fancy abstract controllers implemented by an AI instance or a player controller instance, and much more.

So instead, I kept it simple. I developed it in Unity so I didn’t need to implement any of the engine stuff, no graphics libraries, no audio libraries, no file processing.  It took about 150 lines of code, plus a few lines to hook up game object variables.

I got lucky with the arcade cabinet textures. I was fortunate that I could drop in the wood texture directly. If the UV mapping was more complicated it could have taken some time to lay the panels out, to squish them to the right locations, or to remap the UV values.

What Went Wrong

I do some art, but I’m not ultra-familiar with the tools. I’ve got no problems using Lightroom but some tasks on Photoshop took longer than I wanted. For example, I needed to look up how to create a dotted-line proper-width bar for the center screen. That took about 20 minutes where someone familiar with the tools could have picked the right options in the Line tool in a matter of seconds.

All total I spent about 2 hours in Photoshop for both the 2D game art and the 3D world art, someone comfortable with the tools could have done it in perhaps 10 minutes.

The other thing that went somewhat wrong, costing me some time, was getting the game panel to appear properly on the 3D mesh of the arcade monitor screen. I’m not fully satisfied with the camera technique I’m using, and I’m pretty sure there are some good techniques to render a 2D panel to a texture, but I don’t particularly care to look them up.

Put together the 10 hours spent on the project could probably have been reduced to 8 or 7 hours. May not sound like much, but that’s a 20% to 30% reduction in development time.

Any Nifty Tricks

The best advice I’ve got is to use established libraries.  I’ve written pong several times before. I wrote it one time using OpenGL directly, and system calls for audio.  It took a few weeks of evenings and weekends.  I’ve written it using Windows API calls, it took quite some time as well.   By using Unity for the engine, and using VRTK to handle the VR stuff, I could focus entirely on the game code and game art.

After reading several other people’s projects on Gamedev.net, I can also warn about overengineering. I overengineered my own OpenGL Pong game, but it was fairly small. Some of the suggestions on the site were far more complex than was actually needed.  Always remember the scope of the project. This is not a major commercial endeavor needing years of support. This is a very simple program with three moving objects and two score values.

Source Code

To be posted after the competition complete.  No peeking.

Executable

I could reduce the size of textures and figure out which VRTK assets I don’t need.  I’m not up to that tonight — the end of my third night on this, so I’m posting the big file.

FrobVrPong.zip (39 MB)

Leave a Reply

Your email address will not be published. Required fields are marked *

Time limit is exhausted. Please reload CAPTCHA.