|January 7th, 2012|
A fair amount of folks have taken the last few posts (on making games more cheaply and on rigid programming philosophies) to a bit of an extreme further than I intended. So in the spirit of contradicting myself, here are some good reasons to write new code.
When you have something new to learn.
Writing your own version of a known solution is a fantastic learning tool. Trying to learn how to write jazz progressions? Grab a jazz song, change the key, and start modestly tweaking the chords (an 11th into an augmented, or whatever). Then build your own melody on top of it. Trying to learn how to draw? Start copying people who know how. Trying to figure out how a given game genre works? Try cloning or reverse-engineering a game in that genre. It’s a classic method of learning and there is no shame in it. If you have any creative spark, you’ll quickly move past this sort of journeyman work and start adding your own elements to it. (This is one of my caveats to Dan Cook’s post on game cloning).
I really enjoyed the process of learning every aspect of client-writing when working on Metaplace (I wrote a client — the first one, actually! — and maintained it for a year or so before we switched to the “real” clients). I did things I had never done before. It was a great learning experience. I may never do those things again, but that’s fine.
When you want to invent.
A lot of the things I want to do involve having stuff baked into the engine at a deep level. And that means that retrofitting them into an engine can be hard. If you are really working on something new, then sure, you are going to have to write code.
It can be hard to tell when the things you are trying to work towards is a superficial bell-and-whistle or is really integral to the product. In the case of the procedural terrain in Star Wars Galaxies, there was a fair amount of inventing there. But there was also a lot of research into past work on terrain generation, Perlin noise applications, and so on. In the end, it touched many elements of the game: it allowed very large planets without comparably huge data files; it drastically cut the development time for the title; it allowed the terrain to be dynamically modified algorithmically, which enabled free-form structure placement for houses and mob spawns;it even allowed a neat way of adjusting graphics detail level to accommodate a wider range of target client machines.
Now, there were plenty of problems that it caused too! But my point is that there simply wasn’t a solution available that happened to do all that, so inventing what ended up being a large and complex system was the choice.
When the available solutions are too big.
Sometimes, there’s stuff like a giant physics system or a huge STL library or whatever that you could just use. But it is a Swiss army knife that bloats your codebase, makes your executable too large to fit on a mobile device, or adds in extra complications you just don’t need. It’s one thing if your game needs gravity; it’s another if having gravity means that every rock in the world is going to collide against the ground every frame, which may result in your whole game running too slow.
When you see the real problem.
Sometimes you have a customer, and sometimes the customer is yourself. Either way, the following applies: you need to find out what the customer actually needs, rather than what they are asking for. They (yourself included!) usually don’t know. They will ask for something that is too big or too small.
Finding the sweet spot there takes practice. I look for the elegant solution that can grow with the customer to some degree, but also outright blocks them from getting into trouble. (I am just as prone to get myself into trouble as any customer would be). Customers, yourself included, often ask for a solution to a use-case by describing the solution they want, rather than the use-case.
I don’t have any very specific advice to give on this other than
- Try to think about the problem abstractly. They might be asking to cache an image, but really, if they need to cache an image, they probably need to cache several different kinds of things. They might ask for a tool that lets them specify points on a curve for AI motion, but really, they’re asking for better ways to control AIs, and think that the path tool is the best solution. They don’t know what you can actually provide, so they ask for something they already know about that meets immediate needs, and stop there.
- Minimize. By this I mean, pursue something elegant. Few moving parts will often give more expressive capability than a complex system. I started thinking this way when I became fascinated with the principles behind artificial life. If you go back and read the Ultima Online articles on the AI systems there (1, 2, 3), you’ll notice that the system is deliberately limited to very few variables. In fact, I recall going to Scott Phillips and asking if it was OK to burn one more byte on a variable for aversions… A great example can also be found in this phenomenal article on the AI in the original Pac-Man. Notice how four ghosts have radically different behaviors, they interlock, and yet they can all be described with remarkably little code. (Going back to classic arcade games is always a great lesson in systemic design).
The bottom line though, is that the sweet spot is going to pleasantly surprise the user, whether that is you yourself or someone else, precisely because it solves the real problem that the user imperfectly understood.
When it’s the puzzle for the player to solve.
Games are usually for fun. Fun is about learning. Learning requires there being new puzzles to solve. New puzzles do not come out of a code library.
A perfect example would be when you go to create the AI for your opponents, whatever the game may be. There are AI libraries out there, certainly. But an AI library would not have given that Pac-Man code. Saying “embrace code reuse” doesn’t mean “never write code.” And especially for something like AI, where it effectively is the black box aspect of the game that the player is trying to figure out (and therefore from which they derive their learning and hence fun).
So, why would you want to not write new code for AI, particularly if a) you haven’t done it before b) you want it to do something that you can’t find an off-the-shelf solution for c) you have some inventing to do? It’s going to be where your game lives or dies, and if you reuse someone else’s wholesale, they will have played your game before, and you are no longer making a system-driven game but a content-driven one.
That said… you’ll probably need A*, and attempting to reinvent it from scratch is an unnecessary delay.