Posted

I’m developing an indie game called Substream

I’ve now been a games programmer on three commercial games. Like those games, Substream is a project that is going to take a lot of time to build. But Substream contains several experiments. A lot of the programming is standard: I still need to code up boring things like collision detection, depth sorting and render state management. A lot of the gameplay is familiar too: you shoot things, score points, unlock levels. But the new stuff is what’s important to me and hopefully to players as well.

Music Synchronization

“Music games” seem quite popular. I think Rez and Audiosurf have done the best job of this so far. These games get really strong positive reactions; it seems like the goal of making a player feel connected to the music has been already been done. This is very interesting to me because I think these games are only scratching the surface of what’s possible.

I didn’t get around to playing Rez until it had been out for a few years. Several of my friends described it enthusiastically – “it’s hypnotizing, it’s like you’re actually in the music”. I was very keen to try it. When I eventually got to play it I could see what they meant, but I was really surprised that Rez’s visuals are only really connected to the music in two ways: (1) vibrate certain objects to the beat, (2) hold certain actions from occuring until the next beat.

Audiosurf’s method is to analyse any piece of music from your hard drive. It calculates two things: (1) how intense the music is and (2) where the beats are. Audiosurf really makes the most of these two types of data. Getting any more information than this is extremely difficult and PhD thesis are still being written on the subject, so this wasn’t a route I decided to take.

My primary experiment with Substream is to connect with more aspects of the music, and to see how players repsond to that. This is my approach…

Audio Marker

This is essentially a music sequencer program. But this tool isn’t used to make any music, it’s actually used to mark when events and animations will happen in the game world relative to an existing piece of music. My approach in Substream is human design and this is a tool I’ve created to help me.

This design process is something like choreography. I’m deciding exactly what will happen when, and it means I can pick up on anything in the music I want to…

Moods: how does the music make you feel and how does that change?
Music: what does the music remind me of?
Intensity.
Patterns: is the melody moving up, down, in circles? Game animations can repsond to that.
Instruments: multiple game animations will be related to different instruments in the mix.
Rhythm: including different actions for snares, cymbals, bass etc.

As long as I can hear and can code it, I can implement all the animations I want to fit the music. This process takes time, so Substream will be a short game with with an intense high quality experience. Hopefully there’ll be enough going on that you’d want to go back and play it again.

Dynamic Terrain

This really goes hand-in-hand with the above. I started to learn shader programming recently and it got me interested in some possibilties. Vertex shaders are used to alter the shape of an object on a graphics card’s processor rather than on a PC’s main processor. In the past they have been used for rag doll physics, skeletal animation and other simple animations, but computers are powerful enough now to have every triangle in the game’s environment affected simultaneously. Substream’s environment isn’t a model that was created in a 3D package in the traditional way, but it’s generated while you’re flying along and can animate into a different shape, form, colour, or style at any time.

A Repeating Universe

Some time ago, I happened to be playing Starfox SNES and the original Mario Bros at around the same time. In Starfox you are boxed in by an annoying invisible wall to either side of your ship which you couldn’t fly past. Mario Bros solves this problem by allowing you to go off one side of the screen and come back on the other. Substream puts these together.

Substream’s universe is actually just a narrow channel, but it’s repeated in space. What you end up with is something quite interesting, where enemies appear in multiple positions ahead of you simulatenously, and your ship appears to be one in a chain of infinite ships.

I’m really happy with the terrain animations and music syncing. I also know the repeating space is a workable feature and that the game is definitely playable. It’s a unique set up and by experimenting with enemy and weapon designs I hope I can squeeze some cool gameplay features out of this.

It’s my aim to have several levels in the game on launch, each with a carefully selected piece of music which brings out different emotions, rhythms and gameplay styles. Each piece of music is between six and eleven minutes long so if you factor in a few deaths it may take a couple of hours for one play through. But there’s going to be a lot packed into those two hours.

If you find this game interesting please don’t forget to subscribe to Substream with one of the options at the bottom right of the website.

 
 

Posted

Update: In C++ 11 and later, the need for this macro is obsolete due to the introduction of the scoped enum. But I leave this article up on the off-chance someone desires this in an older version of C++.

Here’s a macro I wrote for C++ which I’ve found extremely useful. It creates structures which act just like an enum, but where the value names are inside the scope of the enum.

To avoid values in different enums having the same name, a traditional C++ coding style is to write something like this:

enum Answer
{
  Answer_Right,
  Answer_Wrong,
  Answer_Pending,
};

A naming convention like this is necessary to distinguish from a Direction_Right or a function called Pending(). I wanted something more like C# so I’d be able to use Answer::Right.

#define strenum( name ) \
struct name { enum name##_e; inline operator name##_e&() \
{ return name##_d; } inline operator const name##_e&() const \
{ return name##_d; } name() {} name( const name##_e& i ) : \
name##_d(i) {} name( const int& i ) : \
name##_d(name##_e(i)) {} \
private: name##_e name##_d; }; enum name::name##_e

That’s very ugly code, but to work with it I just put it in a header file and forget what it looks like. Declaration and usage is similar to an enum.

strenum( Material )
{
  Wood = 17,
  Metal,
  Tin = Material::Metal,
};
Material a = Material::Wood;
Material b( a );

The main practical advantage of this is that I can now forget the names of all my enum values and use Intellisense.

Feel free to copy and paset the above into any C++ program you want.