Saturday, 25 October 2014

Jonathan Blow on Programming Practices

Since the game programming is a hobby of mine – something I do in my spare time – I tend to have a lot more time to think about what I do than to actually do it. I have filled many pages of notebooks and have made many documents with notes ranging from design material, to specific solutions, and everything in between.

So it’s with that in mind that the following video from the Braid developer Jonathan Blow intrigued me, for it advocates effectively the opposite approach to what I've been taking.



One immediate thing that occurs to me is that I’m no Jonathan Blow. Just being able to sit down and write without inhibitions, I'm fairly certain, would get me a mess that doesn't really do much of anything.

The second thing that occurs to me is that it's taken me a year to get half an engine. So the approach I'm taking now is realistically-speaking unsustainable – at least for the goal I'm trying to work towards.

My hope by this stage of my career is that I've absorbed enough of the good design patterns such that the hard work is done for me. What I seemed to have absorbed, however, is knowledge of the existence of patterns minus the knowledge of their application on low-level functions. Since I've had no professional game development experience, this should come as no surprise – why would I have needed to understand patterns outside of their application in Java EE?

Same goes for my stagnated C++ skills, whereby I'm digging through Scott Meyer’s Effective C++ in the hope I can mitigate a lot of the 'gotchas' on areas where Java manages it for you (such as dealing with pointers). My intuitive grasp of class design and function design is rooted in a Java mindset, and C++ is just far enough away from it that my coding style has to be more deliberate. The lack of private functions, especially, is testing my coding sensibilities.

Blow's list of do’s and don'ts seems on the face of it a good one, and especially pertinent if I replace his use of optimisation with "open design" to reflect the kind of design considerations I'm currently working with. I've spent so much time trying to get things just right – of trying to come up with a perfect class order that will enable extensible code. It’s great when it works, but the cost in time and effort has been considerable for that. As Blow pointed out, this kind of approach won’t pay off in the long term.

The other stand-out idea in his talk was the idea of writing specific code over general code. I know I'm especially guilty of doing this. Some of the time there is good reason to write general code, and to my mind it’s especially important to get it right in the core. But it’s something to reflect on that there is good that is fit for purposes without being so flexible it fits every purpose I desire. My Input class comes to mind, and part of that was I think a rationalisation of adding an abstraction atop of SDL's abstraction of the interface. I got what I wanted, but it’s easy to forget the cost of that.

One final lesson that was worth highlighting was the idea of writing code in a single block. This goes dead against the coding principles outline in Robert C. Martin’s Clean Code. In one sense, I can understand this in C++ because of how annoying it is to write function headers for private functions. But Blow’s suggestion about encapsulation is a point well made.

Friday, 24 October 2014

Prototype-Driven Design

This is designed to be a normative approach based off the three [1, 2, 3] development approaches I wrote about earlier. Namely, how to take the use cases of a simple game to develop and refactor an extensible and versatile underlying code. This is a note to myself for next time.

Bootstrapping the framework
A game is a loop, and the loop has an exit condition. Hitting the exit condition exits the game. To be interesting, while the game is looping, the game has to do stuff. All that should be met with “duh”. What this means is that we have to organise an order of things to do in the loop. You need to create a window, load images, display, capture input, change game code, etc. Organising this basic pattern needs to come first..

The first thing is to get the libraries loading successfully. This may take more time than the task sounds like it would, and doing something slightly unusual (for example, choosing to develop on Windows using MinGW) might not have a single point of clear instructions. Don’t fret if this takes longer, it’s important to get this right.

There are a number of discrete systems that in concert make up a game. Many of these are “core”, and will be used every time in very nearly the same way. As such, each of these systems can be given a basic function (such as render updating the screen each frame), and each function placed as part of a list of functions that are always called. In mine, I called this the Engine façade, where the update() loop took care of everything the engine needed to do with a single call from the game loop.

At this stage, it’s okay to use scenario-based development. “A screen should appear on start-up”, “a button press should quit the game”, etc. Indeed, there’s little more one can do at this stage. The important point is not to overdo this, however, because you a) cannot account for every scenario, and b) what you think will be right scenarios may not be the case. Overdo it at this stage, and prepare to refactor.

The prototype approach
Take a simple game like Snake. It’s a fairly simple game so it won’t take much to work out how to translate what happens on screen into code. It’s also a fairly-well defined game, so there’s not a lot of effort in setting the win / loss conditions and how that translates to a loop. It also tests out what you need in a game – to capture input, to update the game world accordingly, to trigger off sounds, play music, and to update the screen.

The general approach goes like this.
  1. Try to build the game artefact to do what you want it to do.
  2. If the engine can’t support the functionality, add the functionality.
  3. If the engine only partially supports the functionality, enhance what’s there.
  4. If the engine encourages a lot of writing the same code multiple times, refactor.

Such a system will also feed back into itself, where later development will override earlier development. The important point is not to get hung up on a decision made earlier if a better decision comes along, after a short while you should have a working game and hence a platform to immediately test out how well the system works.

Like the bootstrap framework, this might take some time to set up. There’s a lot to do going from nothing at all to even a simple working game (without taking every possible shortcut). But what it allows for is very quick refactoring and enhancement. Once you have a fully functioning product, it should be a matter of hours or even minutes to enhance it for the better.

The development phase is similar to Test-Driven Design, though in this case a piece of game functionality is the unit test. You write game code to do something, but it won’t work until you then write the engine enhancement that will make it work.

The allure of design
The prototype approach requires a continual awareness of the allure of design. When making a component, it’s easy to come up with potential uses for that component – all of which takes time to design, develop, and debug. Furthermore, enhancing the system in such a way doesn't mean the work will actually achieve anything. The prototype-driven design in this sense is a way of keeping the developer honest and focused, and not wasting time on the mere potentiality of a function.

This is not a call, however, for the abandonment of design. It’s a call to prevent overdesign, to limit areas where splurges in design can lose sight of the bigger picture. The idea of a chaotic mess of code is what you end up with even with the best of intentions, so there’s no need to add to it if it can be avoided. What I am talking about here is a different kind of chaotic mess – a bloat of code of which only some applies to the end result.

The allure of design is part of the creativity that enables development in the first place, and to some extent it’s necessary for consideration for any potential solution. Otherwise we hit the other extreme – a constant rewriting of the same basic code whenever a new requirement exists. It’s a balancing act, yes, and how the prototype-driven design approach works should be to limit the potential for overdesign.

I suppose the difference I'm trying to articulate is the difference between extensible and bulletproof.

Scope-creep is a good indication that you are moving away from the PD-D and being drawn back into the allure of design. If a problem is getting unwieldy, it’s worth reminding yourself of what the component was meant to achieve in the first place. If it wasn't something with a game-related end product, then that should be a strong indication of overdesign and grounds to stop.

A guideline
The approach sketch above isn't much of a methodology, but a guideline to stay focused. It’s a way to catch that intuitive aesthetic about how code ought to be done and give it a focal point. Furthermore, it’s a guideline that as far as I can tell applies to one person: me. Or to put it another way, this is a sketch of an approach that keeps my distracted-self focused on why I'm doing this in the first place. The desire to “get it right” is coming at the expense of “getting it done”, and this approach seems promising as a way of somewhat alleviating that.

Thursday, 23 October 2014

Toward a 2D Game Engine: Reflections

Two things that have become really obvious through this process are that a) my C++ skills are really rusty, and b) my expectations are grossly unrealistic. The idea of how long something should take should be calculated only by my present abilities, not by ideal circumstances if only I were in possession of all the relevant knowledge and an industrious disposition.

This is not the first time I've tried doing this, and even back as far as university I tried and failed to do similar. I've read a lot of books and articles trying to find the right answers (or meta-answers) to the questions I've had, but I've failed to be satisfied by what is written. Though well-meaning, the tutorials are especially bad precisely because they break basic design principles for the sake of illustrating a point. The closest to what I wanted was the book Game Architecture and Design (Dave Morris and Andrew Rollings), which had a chapter on engine design. But, again, it’s a sketch of the problem – a 9000ft overview that has to somehow be distilled into discrete complementary units.

That, to me, is where the difficulty lies. It presses the question of why I should bother to begin with. After all, there are plenty of other people much smarter and more educated than I who have put the tools out there to take care of it all for me. To name two examples, there’s RPG Maker, as well as GameMaker Studio, which have a track record. But the trade-off is whether to spend the time learning how to use those tools over designing a system I know how to use. If I were more creative, perhaps those options would be better. But since I'm not overflowing with game ideas (I have 2.5 ideas that could be prototyped at this stage), building the engine itself is what I would consider an endpoint.

What I will consider the end of phase 3 – and I'm hoping this phase will be a completion of code rather than a period of enthusiasm – will be to get a few more core engine features developed such as getting in-game text, the level/tile/camera system, and menus. This seems weeks away, where I understand weeks away in a more realistic rather than pessimistic outlook. Perhaps if I were more competent, I could say a matter of days. But it is a hobby, and a hobby has to work around the rest of life.

One concern, always, is the availability heuristic. That is memories of what I've done previously are going to be tainted by the most pressing issues that came to mind – which in my case is the failure to make headway. One hope in writing all this out is that next time I go through this; I have a record highlighting what I think worked and what didn't. Writing it out gives me a meta-plan for the future, with processes and structures of what I ought (and ought not) to do.

I think this time, though time will tell, I have reusable code. The extra time I spent trying to get the design right may have been a headache (and a significant de-motivator), but I haven’t taken the shortcuts that evidently and inevitably crept through my old code. There was nothing in the rendering class, for example, that was coupled to anything in Snake. Snake depended on the Engine objects, but the engine objects were not constrained that way. If nothing else, I can take that away as a victory of good design.

The graphics that were loaded came from an XML configuration, just as sound and music did. The Engine was flexible enough for the game objects to be used by ID, and that would apply just as well in Snake as in any other game. Even to make an animated food object in snake required little more than updating the PNG, the XML, and what type of object it was. The engine objects took care of the rest. And, at least by my reckoning, that’s the way it should be. To embellish or replace the graphics wouldn't even need a recompilation!

At the end of it all, I don’t know if I have better design principles than I did going in. I'm not even sure if what I did was right (though I'm very much of the opinion that what works is right), but from my perspective I don’t care. I'm not teaching anyone else. I'm not writing a textbook or a manual. This is to achieve what I set out to do, and I'm getting damn close to that goal!

Wednesday, 22 October 2014

Phase 3: Snake

Feeling somewhat dejected at my inability to move forward, I decided to give the Engine a test run by making a simple game: Snake. I had a bit of time off work, so I thought it could be something I’d do in a day or two and then build from there. To get it fully working ended up taking much longer, though that was partly because I spent my holidays having an actual break.



What it did teach me, however, was precisely what was easy and what was difficult to do with the Engine as it stood. One development constraint I imposed on myself, which ultimately made it take longer, was I tried to do the Snake game code as wholly separate from the rest of my engine code. So my Play Game State acted as a bridge between the Engine and a separate SnakeGame class that did the equivalent thing – complete with having to mess around with how input is processed.

One thing the process immediately confirmed for me was how inadequate the RenderObject objects were for any sort of game code. In the TextureObject, I had code for pulling out individual frames. In RenderObject, I had code for sorting out source and destination rects for rendering. Between them, both did enough for basic rendering purposes, but it was a pain to do things like change which frame of an animation block to point to. So in order to have my snake change from a head to a body part, and a body part to a tail, was to keep reference to both the snake texture and the render object for the part and do the frame shift in the code.

The reason the objects were the way they were is they served purposes for the function. I wanted an object that could encapsulate an SDL texture while also encapsulating how to break the image down into frames. I achieved what I wanted with the TextureObject, just as I achieved what I wanted with RenderObject, which was an object that could be thrown en masse at the Render class to blindly put onto the screen.

The TextureObject / RenderObject functionality was one of the concerns I had with The Grand Design approach I took earlier. Since SDL does a lot of the core functionality for me, what I'm doing is translating between those core SDL structures and my own Game structures. But because I’m working with the SDL structures as endpoints, I was never sure what value my own wrappers were adding. Furthermore, I was not sure how the wrappers would work in a game. Building Snake gave me a valuable insight into my initial design choices.

It was nice that after I had finally gotten Snake up and working was that I could refactor the code quite quickly. It took me an evening to replace RenderObject with AnimationObject as a game component, with AnimationObject doing what I had to do manually in each game object class when it came to rendering. It took me another evening to expand on AnimationObject so that animation would just work without any intervention on the class. Very quickly I had built up a Run Once and a Loop animation, both of which worked with very little tweaking. Sometimes you've got to love the power of OO!

What was a pleasant surprise was just how much of The Grand Design just worked. Aside from enhancing the RenderObject / Render classes to allow for rotation (so I could point the head in the direction of movement), almost all of the code I did for Snake was in its own set of classes. There was at least some vindication of my earlier approach.

In terms of a development strategy, I find this the most useful process so far. Mainly because now I have a target by which to aim for, and each point of refactoring is an enhancement of the Engine itself. With the AnimationObject, I was able to quickly address the inadequacies of both TextureObject and RenderObject for game code – both were far too low level for any game object to need to have to deal with, and the code general code that would have been useful to ally the two objects was being written multiple times.

I think going forward; this is the way to work. Next I want to get my Level / Camera / Tile combination finished, which I skipped over in Snake by manually generating a list of “Wall” objects that got iterated through every cycle. After that, it’s getting text writing to the screen (an easily achievable enhancement to snake – keeping track of the score and high score), and then I think it'll be enough to start working on a different game prototype to enhance the engine further.

Tuesday, 21 October 2014

Phase 2: Proof of the Pudding

After a busy phase of work (partly self-inflicted) in the first half of this year, I found myself again ready to get back to the project. I took stock of what I had done and what I still had to go. Then, like last time, I tried knocking off a TODO list.

This time, however, I tried to be a little more advanced in putting new features to the test. To have input fully working meant to be able to catch certain events in a particular way. It meant some substantial refactoring of my Engine façade at times, but I think the end result was worth it. Translating from SDL_Event to my own code may not have added much programmatically, but it was sufficient for what I wanted to do with it.

One thing I found when trying to learn how to use the SDL Input from websites, blogs, and vlogs, was that people would tightly couple the SDL_Input directly with their game. The very trap I was trying to avoid! Even the book I was using did it this way, which meant much of the implementation time was me trying to come up with the right patterns of implementation so that input would work the way I wanted it to.

What I started to do this time was analogous to test-driven development – as analogous as seeing things happen on a screen can be to explicit test cases anyway. I set myself particular outcomes I wanted to see, and used that as the driving point of design. To test my keypress feature, I wanted to be able to pause and resume music. This in turn exposed problems in my Audio class (not to mention what functions I exposed with the Engine façade), as well as problems with my Input class.

These use cases were a direct way of testing and expanding the capabilities of the engine. In the grand scheme of things, it wasn't that much different to what I was doing earlier, but it was more directed this way. For example, I wanted to know how to play around with the alpha channel, so I set the task of gradually fading in the splash screen. To get it working properly required tweaking some fundamental code in the Render class, but I was able to achieve the effect this way.

There comes a limit to this form of development, however. One of the pressing tasks for the engine, and something I’d been putting off until I had more work fleshed out, was the question of how to switch from game coordinates to screen coordinates. The basic logic behind it isn't too complicated, though getting one’s head around it in purely abstract terms was difficult for me.

What was complex about the Camera, though, is that it couldn't happen in isolation. I needed to make a concept of a level, something the Camera would translate from. To have a level meant having a system of Tiles – the fundamental units that made up the level. Tiles themselves needed to have certain properties such as knowing who its neighbours are, or whether the tiles were square or hexagonal. Again, I found myself falling into The Grand Design trap, getting very excited about accounting for the possibilities and trying to get it right the first time. Again, the enthusiasm soon waned.

I found myself a month later trying to take stock of where I was, looking back through my documentation for some hint of what to do next, but I couldn't get the motivation back. Between work and stuff going on at home, I just didn't have the inclination to put in the work to pick up where I left off.