Cowboy Programming Game Development and General Hacking by the Old West

February 14, 2007

Comments vs. Self Documenting Code

Filed under: Cowboy Programming,Game Development — Mick West @ 10:20 am

I was reading a thread over on GameDev about the use of comments. There were a variety of opinions, ranging from the extremes of “comment every line of code” to “code should be self documenting and have no comments”.

Personally I use quite a few comments in my code. Game code tends to involve the interaction of a large number of complex systems. Self documenting code is really only a reality if you are insanely familiar with the context of that code. That’s plausible for a period of time, on smaller projects. But for large game projects, especially console games, that often use code that has evolved over several years, and interface with several third-party middleware libraries, it’s really not practical.

What do real code gurus say about commenting code? Steve McConnell has a whole chapter on “Self Documenting Code” in Code Complete 2, which covers the cases for and against comments, concluding (page 817:

The question of whether to comment is a legitimate one. Done poorly, commenting is a waste of time and sometimes harmful. Done well, commenting is worthwhile

In The Pragmatic Programmer Hunt and Thomas say (page 249)

In general, comments should discuss why something is done, its purpose and its goal. The code already shows how it is done, so commenting on this is redundant.

In The C++ Programming language, 2nd ed., Bjarne Stroustrup (the creator of C++) says (page 139)

A well-chosen and well-written set of comments is an essential part of a good program. Writing good comments can be as difficult as writing the program itself

Jef Raskin, Creator of the Apple Mac project, says (here)

Do not believe any programmer, manager, or salesperson who claims that code can be self-documenting or automatically documented. It ain’t so. Good documentation includes background and decision information that cannot be derived from the code.

The question of “Comments vs. Self Documenting Code” is a false dichotomy. You want both. If your code is really so messed up that it needs lots of comments, then it’s smelly code, and may be ripe for refactoring. Obviously it’s a good thing to have meaningful identifiers in code, and to avoid stating the obvious in comments. But if you can clarify something with a comment, then you should.

Unfortunately dogma is something you find often in programmers, even in good programmers. “Goto considered harmful”, “premature optimization is evil”, “comments indicate sloppy code”, “pointers are evil”, “singletons are evil”, “multiple check-outs are evil”.

All these things: goto, early optimization, comments, pointers, etc., are useful tools. They can also be dangerous tools. They can be over-used, and mis-used by bad programmers. Hence simple minded programmers (and managers) rail against them, and impressionable programmers regurgitate the dogma without really understanding the reasons behind it.

Read Code Complete 2, it’s all you need to know (which is quite a lot).

January 30, 2007

Stylus Control

Filed under: Game Development,Inner Product — Mick West @ 8:31 am

This article originally appeared in Game Developer Magazine, November 2006.

STYLUS CONTROL FOR GAMES

Until recently the majority of games have been controlled with either a handheld “sticks and buttons” controller (on consoles), or a combination of keyboard and mouse (on the PC). Two factors are changing this. Firstly, the casual game market’s emphasis on simple and accessible gameplay has resulted in a large number of games that are mouse-only, and that only use single clicks of one mouse button. Secondly, the release of the Nintendo DS has hugely increased the potential audience for games that are controlled by a touch screen and a stylus. The two factors converge in Nintendo’s branded “Touch Generation” games, which are essentially casual games for the DS that are played with a stylus. An additional factor is the increase in the installed base of tablet PCs and the related emerging market of ultra-mobile PCs (like the Microsoft “Origami” spec) that use touch screens with a stylus or a finger as their primary input device.

This article discusses a few of the programming and control design issues involved with implementing stylus control (and the related single-button mouse control) in a game.

DEFINE YOUR ROLE

What should the role of programmer be in implementing stylus player control? Are you implementing the player control, or implementing tools that allow someone else to implement it? Programmers have always been a key part of implementing player control, and it is one of the few remaining areas where the programmer is directly involved in the most critical aspect of gameplay – the interface between the player and the game.

Yet, like most aspects of game development, even player control is shifting to a more data-driven approach, where a game designer is able to define the player control with some script language or table of data. Problems arise with this approach when the capabilities supplied by the programmer do not adequately match the needs of the designer. This is especially problematic when the programmer is tasked with implementing a specific set of input functionality, and then handing it over to the designer before moving on to other tasks.

The implementation of player control is an organic, exploratory task, especially when dealing with a controller (such as a stylus) that is new to the team. It is inevitable that unforeseen inadequacies will be found in any control scheme technical design, and that subtle control bugs will crop up throughout the course of the project. Hence it is highly recommended that a significant portion of the programmer’s time is allocated to make refinements and fixes. This is especially true if the programmer is working on the actual player control, and not just the underlying code. In that situation, the programmer needs to be free to make very rapid changes to the player control when the need arises.

The role of the programmer is unique in this area, since the effective implementation of intuitive player control requires an understanding of what is going on at a per-frame level. This is not something the designer is typically experienced with, and hence they will heavily rely on the programmer to explain what is going on when “this just does not feel right” . Again, the programmer is not simply implementing a control specification; they are an integral part of organically developing a seamless user experience.

MOUSE vs. STYLUS

At first glance it may seem that a stylus is just a mouse that draws on the screen, and indeed with a tablet PC, you can use the stylus pretty much as you would use a mouse. Since you might be asked to develop a game that works well with a mouse and stylus (or convert from one system to another), you need to think about what the differences are.

Other than other obvious physical distinctions, the fundamental logical difference is that with a stylus there is no need for a permanent cursor. A mouse is always moving a cursor object around the screen, but the stylus is its own cursor. The leads to the next major difference: you don’t always know where the stylus is. With a mouse, if you move it from one position to another, say to click on one icon, then another, the code can detect the movement of the mouse between these two icons, and use that information as hints to the player control. With a stylus on platforms such as the Nintendo DS, it is invisible when lifted off the screen, and essentially vanishes from one point to appear on another. On platforms like the tablet PCs, the stylus can be detected moving in the air an inch or so above the surface, but can still move out of range, and re-appear somewhere else.

DEBUG BEFORE CODING

The single most important tool in implementing player control is the ability to visualize exactly what is going on. The very first thing you should implement is the displaying of the device input data in an easily understandable form. This need not be complex. In the figures accompanying this article I just use alternating red and black diamond shapes at every recorded stylus position, with a line drawn between them.

Ball mouse input
Wireless laser mouse input
Figure 1 – A similar circular motion give different data with different hardware (here a cheap wired ball mouse and an expensive wireless laser mouse), which needs to be handled to avoid input ambiguity.
 

This visualization will give you a good initial idea of the type of input you will be handling, and can highlight unexpected issues with either the hardware, or with the driver layer you are using to read the stylus or the mouse. For example, figure 1 shows approximately the same stroke performed by two different mice; each read the same way by simply handling the WM_MOUSEMOVE messages. In figure 1a you notice the points are fairly evenly spread, and the curve is reasonably smooth, but there are a few small kinks here and there. Compare with figure 1b, there are two differences, firstly the line itself is smoother, with fewer kinks, secondly, and more importantly, there are four samples “missing” from the data.

The smoothness of the line can be attributed to the second mouse being an expensive wireless laser optical mouse, whereas the first mouse was the cheap ball-based one that came with the computer. The gaps in the line could be anything, maybe a driver bug, or a problem in some higher layer, but the important thing here is this simple visualization reveals these problems before you start coding.

DEVELOP A LANGUAGE

For efficient communication between programmer and designer, you need to agree on a common language. The fundamental, low-level, building blocks of player controls are the device “events” you are probably already familiar with. Specifically: the movement events and the contact or button events. But at a higher level, stylus control consists of a series of “strokes” .

A “stroke” is the path defined by the collection of points that the stylus moves through between a down event and an up event. A stroke can be as short as a single tap on the screen (equivalent to a mouse click), or can be a long stroke covering the entire screen that indicates something like the path a weapon should take, or a set of objects to be selected.

Other high level control events are game specific. A “throw stroke” might indicate throwing something in a particular direction. Words such as “tap” , “drag” , “gesture” , “path” , etc, have different meanings depending on the game type, and it is important to establish exactly what you mean when discussing player control.

DIFFERENT STROKES

In my article “Pushing Buttons” (Game Developer, May 2005), I discussed the problem of “sloppy thumb” , where different users hold the controller in different ways, which leads to different patterns of input that the programmer needs to deal with. Similar factors apply to stylus control and simple mouse control.

With a stylus, people can hold it at different angles, which effects the amount the stylus can slip when making contact with the screen. The force applied when tapping can also affect the shape of the resultant stroke. A light handed person may give a nice smooth line, whereas a more heavy-handed person, or someone with poor motor control, may start off the stroke inadvertently in the wrong direction as the style makes contact.

Ball mouse input

Figure 2 – Different players with different ways of holding the stylus can give different input with the same intent. We want all three players here to have the same responsive experience.
 

In figure 2, we see three different people attempt the same simple left-right stroke. In Figure 2a, the player gives us a nice clean stroke, holding the stylus firmly yet precisely, and moving his hand smoothly and cleanly. In figure 2b, the player has hit the screen hard with the stylus, but is holding it loosely, causing it to slip upwards slightly at the start of the stroke. In 2c, the start of the stroke is again indeterminate, as here the player has tapped the stylus down hard, and paused for a fraction of a second before starting the stroke. At the end of the stroke the player has slowed their movement and the angle of the stroke tends upwards. This ending is more typical of a left handed player who holds their stylus with a firm overhand grip, as they would a pen.

What is the programmer to make of these strokes? It depends on what’s going on in the game, but a common control element is “throwing” something, or shooting a missile in a particular direction. We need to translate the stroke into a direction vector. Two obvious approaches are to either use the vector from the first point in the stroke to the last, or to use the vector formed as the average from all the individual components of the stroke.

But as we can see from the strokes, the results of these calculations would result in a direction vector that is not in line with the intent of our sloppy players. Our precise player in 1c would be fine, but in both 2b and 2c, the resultant vector would tend upwards.

A possible solution here is to simply chop off the start and the end of the stroke by a certain amount, ignoring, say, the first and last 10% or maybe 0.05 seconds of a stroke. But a more sophisticated solution would be to try to identify the “straight” portion of the stroke, which we can easily recognize ourselves, but is a little more complex to program.

Whether you actually want to do this depends on the type of game, and the intended audience. Some games such as golf, bowling or curling might depend on the nuance of a stroke for fine control of ball spin, and so the degree of slack you want to give the player would be less. But in ball tossing games such as Magnetica or Luxor, all you want is a direction vector.

ACCELERATION INFORMATION

The raw vectors that form a stroke tell you where on the surface the player moved his stylus, and how fast. But by looking at the acceleration information in the stroke data, the programmer can gather information that indicates what the user was doing before and after the actual stroke.

Ball mouse input
Figure 3a – The acceleration at the start and deceleration of this stroke show that the player is deliberately moving the stylus from one point to another, indicating a “drag” action.
 

Consider the two strokes in figure 3. They both cover about the same distance in the same direction. But in 3a, there is significant acceleration at the start of the stroke, and deceleration at the end. This indicates the player deliberately made the stroke from one point to another, and the stylus was not really moving before and after the stroke. In 3b, the stroke is the same speed throughout, indicating the player was moving the stylus bother before and after the stroke at the same speed. This is like the player moving the stylus through the air, dipping it down to briefly touch the surface and continue.

Wireless laser mouse input
Figure 3b – The velocity is consistent across the stroke, indicating the stylus was moving before and after the stroke, hence a “spin” or “toss” action
 

These two movements are very different, yet the interpretation of the strokes may or may not be different, depending on the type of game.

SUMMARY

Game control using strokes from a stylus or a mouse is increasingly common. The programmer’s technical knowledge makes him an integral part of the design process and the organic implementation of that player control. Visualization is vital. Players have different input styles and mental expectations of stroke control, and by accommodating as many styles as possible without compromising coherent controls, you will expand the potential market and the conversion rate for your game.

January 18, 2007

The Seven Stages of the Programmer

Filed under: Game Development — Mick West @ 11:05 am

Before Programming – Ignorant

Before he takes the first step, the programmer does not know that programming exists. He is aware of computers, but has never considered how they actually work. He feels the process of making a video game is somewhat akin to making a film, or perhaps writing a book. If someone were to ask him how that actually works, his brain would immediately shut down, as if you asked him why string theory requires ten dimensions.

Stage 1 – Awestruck

The programmer become aware that programmers exist. He is not entirely sure what they do, but he know it involves typing things in, and possibly moving a mouse. Somehow there are “programs”, or perhaps “code”, he is not sure. Regardless, for our stage 1 programmer, people who actually do these things seem like gods, omniscient in their mastery of impenetrable yet valuable and (finally) socially acceptable skills. While the nascent programmer feels some longing to achieve this mastery, it is as if he were longing to bend forks with the power of his mind – he’s seen it done, yet secretly believes it to be magic, inaccessible to mortals.

Stage 2 – Fumbling

The programmer writes his first program. In the olden days this would have been of the 10 print “hello”, 20 goto 10 variety, but in more modern times the possible starting points are varied. Perhaps Unreal Script, perhaps Dark Basic, perhaps JavaScript, perhaps even some master may initiate them directly into the dark arts of C++. How many roads may a programmer take? 101010.

Stage 3 – Discovery

A whole new world has opened up. Syntax becomes an enchanted garden, each new keyword hold mystery and delight. Wave of pleasure accompany the discovery of new powers like arrays, and subroutines. A whole new reality seems close at hand. The programmer seeks out others of his kind on the internet, discoveries are shared and wonders are related.

Stage 4 – Delusional

Intoxicated by his new power, suddenly the world is an oyster belonging our programmer. With the gradual appreciation of the power of programming, and the realization that code underpins everything, our programmer will feel limitless in power. All tasks see manageable and anything can be programed, for our programmer is now armed with the hammer of limited coding skills, and all problems look like the nail of N-Queens.

Stage 5 – Methodological

After perhaps years of delusion, some tragedy will befall our programmer. Perhaps he will get a job, and the skills he thought wondrous will prove to be of little worth. Or perhaps some personal project, such as a game engine, will be transformed by much sweat into a blob of worthless code, undeniably incorrect despite his seemingly god-like powers. Faced with this reality, one of three things happens: the programmer may give up in despair, they may lapse back into delusion, or finally they will discover “methodology”, and avidly begin to read books on this, and begin to “program” in UML. This stage is perilous, as the methodological world is similar to the mythological world, replete with Sirens, succubi, heroes and monsters.

Stage 6 – Pragmatic

More pain shall be endured. For, as the programmer will discover, there is no silver bullet. It’s complicated, and he’s beginning to realize this. An awareness emerges that the important things are getting the job done on time to a sufficient level of quality. He can now estimate projects reasonably well, not because of any methodology, but because he’s generally done something similar before. He’s got a lot of tools in his belt, and is suspicious of anything new. He may become curmudgeonly and bitter.

Stage 7 – Transcendent

The programmer finally becomes self aware. He now grasps how complicated it is, and recognizes the dimensions of the problem space. He realizes the bounds of his knowledge and experience. He is also fully aware of what efforts would be required to extend those bounds. He’s still suspicious of the new, but can now accommodate those new things into his arsenal. The programmer is at peace with himself, embracing the chaos of development as something as elemental and unchangeable as the weather. Canute cannot stop the tides, and not even the transcendent programmer can ship without bugs.

While all programmers may pass through the seven stages, not all will make it to transcendence. Many will become stuck at a lower stage, and either abandon their quest, or settle wherever they find themselves, churning away at what they know.

Not all programmers take the same path, and not all aspects of the programmer will proceed at the same rate, or even direction. With this unfortunate vagueness comes the observation that you can only recognize a stage when you are two stages above that stage. Thus, the transcendent programmer will never truly know he is transcendent (although he will suspect it) and must always be in doubt as to the pragmatism of his solutions, and the pragmatic programmer will be forever conflicted regarding his usage of methodology.

January 12, 2007

Programming Bio

Filed under: Game Development — Mick West @ 11:22 am

I first started programming games in 1979, aged 12, when my Grandfather bought me a Casio FX-180p, a programmable calculator that had just 38 steps, and a display of just the usual ten digits. Nevertheless I managed to whittle away a few games from that meager space, including a gambling game where you had to guess if a random number you had was bigger or lower then the computer’s random number, and you could bet an amount of money. I had the game code memorized since every change to it meant re-entering the entire program (not much of a chore with only 38 button presses). I have since forgotten it.

My first real computer was the Sinclair ZX81, with 1K of memory, and a 3.2Mhz 8-bit processor (coincidently, that’s exactly 1/1000th the clock frequency of my current computer, and 1/2000000th the memory). I swiftly upgraded to 16K, and wrote some simple games.

But my programming really took off with the Sinclair Spectrum. 48K of memory, high resolution color graphics. Luxury. I wrote games, I hacked the hardware. Still all just at a hobbyist level, although I dreamed of working in the games industry.

Then I went to UMIST (Manchester, England) to “study” computation. During my last year here I got an Atari ST, an immensely powerful machine with 512K of RAM, a 16-bit processor at 8Mhz and a floppy drive. Truly this was the pinnacle of computing! I messed around with this computer to the exclusion of all else, including attending classes.

Upon leaving university with a degree, I got a job as a game programmer at Binary Design in Manchester, earning the vast salary of £6500 (about $10,000), which actually seemed like a lot back then. The first game I worked on (with two other programmers) was “Steve Davis World Snooker”, a 2D snooker game that was incredibly simplistic. The most valuable lesson I learned during development was that people perceive human attributes in random behavior. This happened after a producer told me that the positional play (where the white ball ends up after a shot) was “too good” in beginner mode. In fact the computer only concerned itself with potting balls, and never even calculated where the white ball would go after, making the “positional play” essentially random.

The next game at Binary was “Rotox”, a rather odd game based on the premise that a 2D rotating playfield was fun. I had way too much creative control on this game, which meant it was late and rather strange. Shortly before it was finished I arrived at work to find all our Atari ST computers had been replaced by Vic 20s. Shortly after this we found the company had declared bankruptcy.

I then went to work at Tiertex for less than a year, churning out an arcade conversion “UN Squadron”. The art process for this game consisted of using a video frame grabber to take pictures of the screen, and then an artist would trace the images to create game art. Tiertex was actually fun, since round the corner was a pub that gave free pizza with a purchase of two pints or more, so come noon we would head round there and begin the relaxed afternoon.

I left Tiertex in the company of an artist to go work at Ocean, where I did three games: Darkman, Parasol Stars and Lethal Weapon. Of these Parasol Stars was by far the best, probably because I was not involved in the game design. I have since learned a lot from my mistakes.

After finishing a conversion of Lethal Weapon to the Sega Genesis (which I think was never released) I got a job in the US, at Malibu Interactive, formerly Acme Interactive. There I co-programmed a Battletech game on the Genesis. Malibu was then in something of a development limbo, and lots of people left to start their own companies. I was approached by Joel Jewett to start a company, the first game was going to be “Skeleton Warriors”, apparently going to be something better than Power Rangers. Eventually I agree, and tell Joel we would need an artist, so we team up with Chris Ward.

The rest is history, or at least Wikipedia:

http://en.wikipedia.org/wiki/Neversoft

Cowboy Scrabble Programming

Filed under: Cowboy Programming — Mick West @ 10:39 am

(This is just a programming anecdote.   If you want to know how to program something that plays scrabble, then look here: http://www.gtoal.com/wordgames/scrabble.html)

A couple of years ago I was trapped in Truckee, California, snowed in somewhere up a mountain in a little cottage, with no electricity. It was the holidays, and I was visiting with the in-laws, and we’d just had a rather unsatisfying game of Scrabble. Unsatisfying because we had no dictionary, and so no way to validate challenges, which makes the game even less visceral than normal.

So my laptop still had a few hours of juice left, so I resolved to write a quick scrabble word checker. As it happened I already had the list of valid scrabble words(ospd.txt), which can be downloaded from http://web.mit.edu/rwbarton/Public/ospd.txt

At first I though a quick batch file would do the trick, but after a few minutes poking I got annoyed, and decided to simply brute force it, and write it in plain old C++, just to pass the time. Half an hour later I came up with this monster (stripped slightly):

		w = (char*)argv[1];

		char * p = new char[10000000];		// 10MB
		FILE * x = fopen ("C:\\ospd.txt","rb");
		for (int i=0;i<10000000;i++)
			p[i] = 0;
		fread (p,1,10000000,x);

		int len= 0;
		while (w[len])
		{
			if (w[len] >= 'A' && w[len] <= 'Z')
				w[len] -= ('A'-'a');
			len++;
		}

		char *s = &p[0];		// w = search pointer to start of word

		int valid = 0;
		while (*s != 0)
		{
			int letter = 0;
			while (letter < len)
			{
				if (s[letter] != w[letter])
					break;
				letter++;
			}
			if (letter == len && (s[letter]==0x0a || s[letter] == 0x00))
			{
				printf ("%s is GOOD\n",w);
				valid = 1;
			}
			while (*s != 0 && *s != 0x0a)
				s++;
			if (*s == 0x0a)
				s++;
		}
		if (valid == 0)
			printf("%s is BAD\n",w);

Now there’s some hackery, quite embarrassing really. It’s a good example of Cowboy Programming because:
– It’s long and messy code
– It’s using an ad hoc solution to something that has been solved many times before

But the key thing is that it works. It’s a perfect solution to the given problem in the sense that it solves the problem perfectly. But it’s nothing beyond that.

Of course, you can do the same thing in one line of Ruby:

puts IO.readlines("ospd.txt").include?(ARGV[0]+"\n")

But I did not have Ruby (or Perl) installed, and since I’m no Ruby expert, and had no Internet access, that one line of Ruby could have taken me longer to write than the 50 lines of C++.

However, had I persevered a little, I could have figured out the batch file:

@echo off
for /F %%f in (ospd.txt) DO if "%%f"=="%1" @echo %%f IS GOOD!

In hindsight, what should I have done, wanting to be a “good” cowboy programmer? Well, my goal was to solve the problem as quickly as possible, and I knew the code was never going to be looked at or used again. I knew that very simple solutions existed, but I did not know how to get to them. I knew I could get to those simple solutions eventually, but I did not know how long it would take. On the other hand, I knew if I programmed in C++, the code would be long and messy, but I knew exactly how I would write it, and I knew roughly how long it would take, about 20 minutes.

So, the choice was a short and elegant solution in between two minutes and two days (if I had to wait until we escaped the snow), or a long and messy solution in twenty minutes. Take the money, or open the box? I experimented briefly, and then chose the known quantity. The messy code was written. Done.

« Newer PostsOlder Posts »

Powered by WordPress