Sign in to follow this  
  • entries
  • comments
  • views


Sign in to follow this  


Well, the site should be much snappier now. I've changed the way the ads at the top of pages are loaded from "document.write" javascripts into full IFRAMEs; that way they get loaded asynchronously, instead of pausing the page while they make requests to the banner system. It really is the ad system that's slowing it all down; we need to look into moving it onto separate servers, or finding alternative software. Sadly the AdComplete tech support guy seemed rather eager to blame all our problems on our own software, but judging by the speed at which pages are rendering, that seems like a fairly poor assumption.

So, there's this idea I've had in my head for the past several days. It's not going away so I should write it down.

Games are referred to by some places that want to pretend they're more than what they are (e.g. universities) as "Real-time interactive simulations." The name is actually pretty accurate:

  • We've got a simulation, a collection of game objects in a game world that change state according to a set of rules. Can't pass through walls, take damage when shot, etc.
  • We've got a clock. A load of rules in the simulation are about what to do in response to the clock "ticking."
  • We've got one or more players. They have a "portal" into the world that gives them a view on the simulation and allows them some interaction, some limited ways to affect the state of the simulation. Or, swapping the active/passive roles, the player has ways of triggering events that the simulation can respond to ("gun fired," "step taken," etc).

So here's the crux of the idea: The way we write code for games, the procedural style, where we loop over bits of data and process things individually - it's not actually a very good way of doing it. Processing game objects one at a time is not the right way to think about things, really, because we're performing exactly the same operations on most game objects.

Another thing to consider is that programming isn't really "telling the computer what to do." If we were doing that, we'd be writing in assembly. What we're really doing is expressing the behaviour of our program in a form that our tools (compilers) can understand. As long as we've got the tools we can write them however we like.

So I'm wondering about experimenting with a more natural approach to writing, at least, the core simulation: SQL, or at least something like it. Instead of building up behaviours within self-contained objects, we encode them as set-based selections and updates. Newtonian motion across all objects in your game is just "UPDATE entities SET position = position + (velocity * Tick.slice)".

Sets, of course, are not sufficient to capture it all - so we add events as well. The most obvious event is the "Tick" event, which gets fired every frame; there's also things like the "Collided" event, the "BulletFired" event - whatever you like. Events are user-definable, as the events that make sense for your simulation are up to your simulation. They do also have data fields (which can themselves be sets), but are read-only once created.

There needs to be a way to raise events, natch. I'm considering a "FOR EACH ROW IN" syntax, which raises an event for each record in a set. So collision detection is "FOR EACH ROW IN entities a, entities b WHERE != AND MeshesIntersect(a.collisionMesh, b.collisionMesh) RAISE CollidedEvent(," for simple mesh-mesh collision. Obviously, there's more to it than that - we'd want to use separate queries for performing coarse testing (e.g. AABB) before doing mesh/mesh intersection, MeshesIntersect wouldn't be implemented in SQL, etc... there are some nice things that could be done with, for example, Octree-based indexes for positional columns.

The real benefits of this approach, though, become clear when you start having lots of cores available. Dependencies between statements are very obvious; a statement may only refer to data in the tables it is working with and data in the event that caused it to be executed. No other state may be used, and only tables referenced in the statements may be written to. Functions may not have side-effects. So, you've got these neatly-segregated little chunks of processing with clearly defined dependencies, input and output datasets, and a predisposition towards SIMD. Hello, stream-based processors and PS3...

It also produces interesting changes to the development methodology. As well as the demonstrated statements for describing runtime behaviour, what about CREATE/ALTER statements for loadtime? Suddenly an entire element of the game design can be packed up as a set of load-time and run-time behaviours. Want to add an economy to your game? Write a load-time statement to add a 'value' column to all items, populating them with a default value calculated from their weight and damage (plus a few hand-tuned values), and a statement to add a 'gold' column to the players table; and run-time statements to handle the 'PurchaseItem' event, etc. The ramifications for modding are quite impressive; if you've installed mods to add a bunch of new weapons to the game, and then you install a mod to rebalance the money values of all the weapons, the latter mod can update the custom weapons without even knowing that they're present if it uses a formula to calculate the new value.

Of course this only really works for the simulation part of the game. The 'portal' that players use can touch on it - "SELECT FROM entities WHERE InViewFrustum(position)" - and of course everything that the player does to the game world is expressed to the simulation as an event - but most of the code there still needs to be procedural. Still, it's a start.

SQL would of course be too slow at runtime to execute directly, so these behaviours could be fed to a tool that generates a more optimal result - calculates the best layout for data structures, etcetera.
Sign in to follow this  


Recommended Comments

At first glance it looks very nice to have such a structure, but (with my admittedly limited experience) I'm doubtful if such a generic setup will give you the performance you need and won't make some things harder. In a game with a straightforward ruleset, I can definitely see the benefits of such a neat structure for multicore systems and asynchronous requests.

On the other hand, I was just reading up on collission detection and physics simulation, which requires some stepping back and forth through update time to resolve interpenetration and has some more data dependencies. This may be harder to implement, the overhead of the generic storage structure may take its toll and the cost of the actual checks/actions may be hidden too well by this setup.

Kylotan commented on something similar and I'm afraid he's right:

- data backed by SQL databases: these give you automatic persistence, standardised querying facilities, easy ability to locate your data on a different computer to the program doing the querying, etc. All good. Now try to write a common interface for such SQL-enabled objects, get it to work across inheritance, and guarantee that the code stays in sync with the SQL statements required to create the database. I never knew adding two integers to a C++ class could take 3 weeks before, but now I do.


All these facilities do Great Things. There's no denying it. But you pay a price. And I fear that all we're doing is shuffling the burden around rather than eliminating it.

Even when you're not referring to actual databases, but a similar structure, I think his last statement holds.

Share this comment

Link to comment
Ah, but I'm not actually talking about using an actual database at the backend - merely an SQL-like syntax for describing behaviour. Don't forget that "SQL" is a language and an "SQL database" is merely a database that supports that language.

So there is not necessarily anything like inheritance to have to "support." I'm not talking about an SQL interface to C++ objects. I'm talking about replacing C++ code with this Game-SQL stuff. (In any case, subtyping is easy to implement).

C++ expresses things on the machine's terms. I want to take a step higher up and express things in terms that are even closer to the original design.

Share this comment

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now