So, you want to make a game, huh?
Most of the time when you hit that point the best thing you can do is pick up an existing set of tools or code base and run with it. While you'll probably never find a pre-built toolkit that will fit your vision exactly (and if you DO, why are you building your game? It's already been made!) there is a lot to be gained by picking up Unity or UDK or even something a little less recent like the Quake 3 Source and hitting the ground running. You'll inherit a tested, robust tools pipeline to handle things like level building and model importing. You'll benefit from the experience of veteran developers in the code base. You'll have a large community of people playing with the same tools that you can turn to to ask questions. In short, you'll skip over all the boring, tedious parts of painstakingly tweaking the technology to the point that it's game-ready and focus instead on doing something that makes your game unique.
Essentially: You're going to be very hard pressed to come up with a good reason for NOT building on someone else's work. Save yourself a lot of heartache and try an existing solution first, because you'd have to be insane to want to start your own game from scratch...
In other words, you'd have to be me!
Yes, I'm one of the crazy ones, but I want to make it clear that I have absolutely no delusions about the path I choose being an easy one. I'm going this route purely because the technology that I want to focus on (WebGL) doesn't have that wealth of existing code, tools, and community. There are some good frameworks out there (three.js, J3D) but nothing that's really purpose-built for a game. I really want to make something that's not just a generic "framework" or "engine" but actually a real, playable game that can be studied, built on, played with, and improved over time. So let's see just how far down that particular rabbit-hole we can go, shall we?
Starting with a blank page in a text editor is always the hardest part of any project, because there's a lot of boilerplate code that needs to be put in place before we can start putting things on screen. So that's what today's post is aimed at: giving us that starting point.
(Coincidentally, the code from today's post also serves as something of a replacement to my previous "WebGL Sandbox")
First things first, we need a simple index page with a canvas that we can latch a WebGL context onto. It's also certainly helpful while developing to have a FPS counter, so I'll add one of those. Also, to take advantage of a newer bit of HTML5 goodness, we'll throw on a "fullscreen" button, because we all like to play our games fullscreen, right?
love despise. To this end, I'll be using RequireJS. I won't say that the syntax is my favorite, but it does a good job at what it does so we'll run with it.
Next, we need a place to handle our rendering logic. To this end we'll build out a simple GameRenderer class that gives us a place to manage our render resources and state. Moving forward this will be distinct from the core game logic like player input, physics, collision detection, etc. We only want this class to handle the actual drawing of a frame. To demonstrate that things work and get something on the screen it's got the logic for a simple cube rendering in it.
(Side note: I gave the cube a crate texture, which means that my game has crates in it months before actual gameplay! I think I may have just received the worst StC score ever!)
We're also going to be spending quite a lot of time in the first few posts of this series working out various different formats for our 3D models and environments. As such, we'll want a simple way to control our view of said environment which will come in the form of our Camera Classes. There are two of these:
- ModelCamera - Orbits around a given center point at a fixed distance. Useful for viewing individual models (hence the name). This is the camera type we'll use the most initially.
- FlyingCamera - Using a floating WASD + MouseLook movement scheme to allows us to navigate larger scenes. Basically the same as what you see in my Quake 2 demo.
Both camera types include all the required event hooks internally for their movement, and only require that camera.update() be called at each frame to make sure the motion is properly timed. Note that these classes will almost certainly outlive their usefulness once we get into the meat of the game, but you've gotta start somewhere, right?
Finally, we need some sort of entry point into our code (a "main" function, if you will) that will tie the varying pieces together for us. This comes in the form of our index.js. It is run once the page is loaded and contains the logic to initialize the WebGL context (and show an error to the user if that fails), handle the aforementioned fullscreen button and the associated resizing, and starts up the game loop, which currently just calls renderer.drawFrame() and updates the FPS counter. (Using RequestAnimationFrame, of course!)
Of course, we have a few utility functions hiding away in the background to help out with some of the more common and boring bits, and as always we're using glMatrix for our mathematical needs, but that's pretty much it! The result:
A spinning crate! Impressive, no?
Okay, it's not much, but it gives us a place to start. And now that we've got some of the boilerplate out of the way, we can start working on the interesting bits.
Up next: Creating a model format! (I swear the next part will be far more interesting!)