bridge ideas

Gas, my current game project, has reached a turning point at last. I know this not because I’ve written a whole bunch of new code—actually, commits have fallen off a little lately—but because I’ve started removing the code that implements the bridge ideas.

I think most developers have this concept, even if they call it something else. For me, a bridge idea is only obvious in retrospect, a feature that I spend considerable time implementing but have to throw away in the end. A bridge idea moves the project along, and though it no longer suits the project, the project could never have been completed without it.

I just wish I had a better analogy than a bridge for this kind of idea. Yes, they both get you somewhere, but you usually don’t throw a real bridge away once you’ve crossed it. (Unless I’m missing a trick here. Disposable bridges? Get my people on the phone.)

some things never change

Today:

You’re writing a game with a story? Bleh. Why not write a novel instead?

A thousand years ago:

You’re writing a story in prose? Bleh. Why not write an epic poem instead?

Ten thousand years ago:

You’re writing a story? Bleh. Why not paint on the cave wall instead?

A hundred thousand years ago:

Bleh bleh bleh bleh? Bleh. Bleh bleh bleh bleh bleh bleh instead?

drawing rooms and gas giants

I’m deep in the game script at the moment. Oddly enough, what I’d planned as a science fiction story about a clash of cultures on a distant gas giant world is turning into a 19th century drawing room comedy. It’s still set on a distant gas giant world, though. I hope that doesn’t confuse anyone.

On the technical side, one new approach I’m trying out is paying off. In the games I made previously, most objects were “smart”—that is, they contained all the game logic that concerned them. The player object knew about damage tables. A state machine for determining when an antagonist would break off an attack would be found in the object that maintained the antagonist, and so on. Each object maintained its own state and its own business logic.

This seemed logical to me until a couple months ago, when I was going over the source code for Easy Does It and realized that the game logic—code that describes how the game actually works—is all over the codebase. Hard to understand, hard to debug.

For the new game, I dipped into design patterns and came up with a model-view-controller like pattern to use. All drawable objects are dumb, knowing only how to create and draw themselves, rather like views. The game logic is maintained in one source file, broken up into several different modules. These are the controllers. And the tables that drive the game—the models—are maintained in another source file.

It feels right, and I’m finding it very easy to develop and make changes. I’m never wondering where a given feature or mod should go anymore. Every code function has a definitive place where it belongs.

Back to the drawing room. More tea, vicar?

when time isn’t a constant

I noticed a problem last night with Gas (working title for my current development effort). NPCs were jittering as they moved. I hadn’t noticed it much before, but I couldn’t unsee it now. I debugged my way down the chain.

Behavioral state machine, check. Physics, check. Drawing, check. I couldn’t find the reason. I set up a simple test, enlisting an NPC to run away from the camera at top speed, and I followed it, moving at what I thought would be the same speed.

It wasn’t, though. Acting on a hunch, I monitored the velocities of the NPC model and the camera, and found that the difference between them was fluctuating from frame to frame, sometimes as much as 10%. I checked the directional vectors—same. Speed? Same. What’s left?

Well, distance equals velocity times time. I checked the time intervals I was using to update the camera and NPC positions. They were varying by 5-50 milliseconds. Couldn’t be, I thought. I use a single time base calculated by my SOAR library on every animation frame. It had to be consistent!

Unless of course, the camera and the NPC were updating in two different frames. I couldn’t see how it was possible, but was all I had to go on. I started tagging frames to see which phase each update was happening in.

The camera and the NPC were indeed updating in two different frames. Since the time interval between animation frames can vary wildly, especially under heavy loads, a model updating its position in a frame before or after the camera updates its position will be drawn out-of-phase, so to speak, with the camera. This becomes significant at higher speeds, manifesting as jittery movements.

So, why were they updating in different frames? Three factors.

In the main application loop, updating and drawing are performed in two different methods. This way, if the player pauses the game (freezing all updates) then resizes the window, I can still redraw the scene with the new aspect ratio. This is usually fine, but it helped create the issue in this case.

I schedule the draw method to follow the update method. However, due to some fiddling I was doing with the SOAR library, scheduled methods are run in reverse order—the draw method is actually being executed before the update. Therefore, updates to a model aren’t drawn until the next animation frame. Now, that’s not actually a problem, as long as all the physics calculations are performed within the context of the update. You’d be fine as long as you didn’t do something stupid—like handling physics inside the draw.

Ahem. Well, I was trying to save some time. My display list handler iterates over all active drawable objects. Early on, I figured I could stuff in a quick call—if the drawable object is updatable, then update it. However, this forced the updates to the NPCs to be handled in the context of the draw, which was executed in the animation frame previous to the frame that updated the camera. Inconsistent timebases → mismatched velocities → jittery models.

I moved the NPC updates out of the display list draw and into the update handler. Result: rock-steady models. Boo-ya, I guess. It did strike me as funny that Time, the one parameter we usually assume constant, was the wildcard. Well, that and Stupid.

no wait, let me tell you a story

There’s an interesting discussion going on here regarding the author’s belief that scoring isn’t being done well in gaming right now. I didn’t get where he was coming from until I read his linked post in which he argues that “story” and “game” hurt each other and shouldn’t be combined. If you take stories out of gaming, the argument goes, you take away the “end goal” model that he believes has plagued game design for far too long, and you can focus on the “mastery” of the game mechanic.

I don’t have a useful opinion on it beyond “I disagree”, as the author implies that story games are objectively worse than non-story games. His argument rests heavily on telling people who enjoy story games that they don’t really enjoy story games. I’m sorry, what? When I step away from a game, all I care about was “did I have a good time?” If I did, then the game succeeded. End of.

presented In glorious smell-o-vision

The game I’m working on now, which I’ll refer to as Gas until I have a real title, involves locating clouds of smelly stuff and sucking them up. I mocked up a cloud of tiny black triangles to serve as a test model, and discovered they were invisible against the busy background of the game world.

You can’t see them until you’re right on top of them, which defeats the purpose of drawing them at all. How do we make it easier for the player to detect them?

My first idea I ripped from Batman: Arkham City. In some quests, Batman has the unenviable task of homing in on a signal without any directional information. The player has to look at the distance to the signal and determine if s/he is moving closer or farther away–kind of a high-tech version of Marco Polo.

Well, that’s how smell works, too. You can’t home in directly on a smell–it’s based on molecular concentration, which isn’t directional. I whipped up a readout of how close the player was to the nearest cloud of smelly stuff and slapped it on the HUD.

It worked, but it was really a pain in the ass. I had to bob this way, that way, down and up, then left a bit. It works in Arkham City because the map is effectively 2D: much, much wider than it is tall. Gas is 3D. It’s as tall as it is wide, and your target may be right over your head or just under your feet.

Or: several hundred meters under your feet. It’s a big place.

Also, you don’t have any feet.

Anyway. The Marco Polo method didn’t work for me. I needed more information. I decided to try out an idea I’d had a while back, a solution looking for a problem. I’d wanted to create a low-information version of the scene itself, like when a game uses simulated night vision. You block out aesthetics, and only show stuff that a player absolutely needs to see, or the stuff they normally can’t see.

I called it smell-o-vision. It rendered the clouds of smelly stuff as black blobs on a big square canvas off to one side of the screen. I stepped back and admired my work. It didn’t take me long to see that it looked hideous, and was completely stupid. You’ve got a GPU pipeline, why are you writing a software renderer?

I wiped it out, and made a small change to the shader instead. Now, the triangles that make up the clouds render as white, not black. You can see them for miles.

If you want players to find stuff, you can give them readouts and gauges and clog up the screen with fancy HUD gadgets. Or, you can just make it easier to see.

Is the question really that (forgive me) black and white? I’m not sure. I think it has to depend on what’s fun about the game. Gas is a flight-based game. You’re flying about in the sky, and that’s pretty fun. If you have to read a little meter and stop and turn, read it again and stop and go down, read it again, and so on, it’s not so much fun anymore.

In Batman, you do glide above the ruins of Arkham City. It should be fun, but it’s Batman, so it’s really severe and gritty and technological and loaded with guilt. As far as I can see, the only fun Batman really has is punching goons. Punching goons is the best thing in the game. Everything else is pretty much window-dressing and getting from one place to punch goons to another place to punch goons. The meter doesn’t get between you and the goon-punching, so it’s really not a problem.

Plus, Bruce Wayne’s parents were gunned down in a back alley. Dealing with a dinky little meter isn’t going to make any impression on him at all.

midweek madness

The new project-thing is starting to move again, as I suspected it would. The only thing that worries me is that I seem to have more source files than actual functionality. It isn’t clear how many source files I’m supposed to have, but maybe this is too many. Or it isn’t. No idea.

I’m sure I’ll read about it on Hacker News, which I read every day just for this kind of thing. Someone posts an article endorsing some piece of programming/life advice. It’s earnest, harmless and silly. Someone else posts a rebuttal arguing the opposite advice. It’s earnest, harmless, and silly. Someone else has a convoluted mirror-universe take on the original advice. It’s–we’ve been here before. Given my example above, we’d have:

Too Many Source Files Makes You a Bad Programmer

Not Enough Source Files? You’re a Dick

Source Files: Can You Have Too Many?

I’ve Got Your Source Files Right Here

Steve Jobs Might Have Mentioned How Many Source Files You’re Meant to Have

Evil Government Attempts to Regulate Source Files

There’s plenty of useful tech articles, so I don’t mind the fluff, which is actually endearing in its own way. It’s human, and often serves as a pleasant chaser to the straight-up tech shots.

Speaking of useful tech, there’s not much in this post, is there? Never mind. Back to work.


easy does source, and prototypes too

Little progress on my latest project. I’m running not into code issues–I wish I were as those are much easier to solve–but questions like should it really work this way and do you need combat in a game to create risk and why does internal monologue register as italics, anyway, I mean, who thought that up and so on. It’s frustrating, but it will pass.

Anyway, I put the source code to Easy Does It into github, right here. I hope it’s of use to somebody.

One big code style change I forced on myself over the last few months was using the prototypal model in deriving JS objects. For Foam, Fissure, and Pavo, I used classic inheritance and object creation: function objects and the new operator. It looked familiar enough from my days as a C++ developer, and when you’re trying to get a foot into the door, familiar is good.

However, in JS, classic inheritance feels like what it kind of is: an attempt to shoehorn a familiar pattern into a language that was built with something else in mind. Prototypal inheritance is that something else, and I have to say, I’ve come to enjoy it. I rebuilt my WebGL wrapper, Foam, into a prototypal library called Soar and I’m happy with the results. Easy Does It is all prototypal, as is the game I’m working on now. I haven’t seen a new operator in months.

For objects that I’m going to create more than one instance of–drawable objects in particular–I’ve found this pattern incredibly useful. No idea if it has a formal name, but it’s like having a static function on a C++ class.

GAME.enemy = {

	init: function() {

		// create shader object shared by all instances
		this.shader = shader.create(...);

	},

	create: function() {

		// create an instance and populate it,
		var o = Object.create(GAME.enemy);
		o.position = this.getRandomPosition();
		o.damage = this.getRandomDamage();
		return o;

	}
};

...

	// initialization code
	// creates all shared resources
	GAME.enemy.init();

...

	// create lots of objects
	for (var i = 0; i < lots; i++) {
		list[i] = GAME.enemy.create();
	}

...

	// activate the shader for this type of object
	list[i].shader.activate();
	// draw all instances of this object
	for (var i = 0; i < lots; i++) {
		list[i].draw();
	}

Changes to the base object are, of course, propogated to all instances. I find this oddly pleasing, more so than I find the idea of a fixed base “class” as in C++ and Java. I have to admit it’s taken some time to warm to it, but here I am. Good place. Good place.