Sol Trader is a science fiction game with a procedurally generated society and history you can befriend, understand and manipulate.

"If you don’t want to play Sol Trader... I’m afraid we can’t be friends anymore. That’s just the way it is."
Rock Paper Shotgun

"Incredibly in-depth."
Indie Gamers UK



Gossip as a game mechanic

Posted Thu 03 September 2015 05:21

I’m now in the final stages of getting a playable demo out to beta testers (if you’d like to join the waiting list, you can sign up on the forums). I’m busy cramming in the final few things to make the demo as complete and as fun as possible.

I’ve done all my development on OSX for the last few months, so last week I put together a Windows version: thankfully it only took about four hours, due to both using SDL2 and to splitting the game code from the platform layer. I’ve also just implemented the code that allows players to talk about another person in the game, and I want to briefly discuss how it works.

The power of gossip

I wrote in June about how Sol Trader uses information as a form of currency in order to help the player advance. The power of gossip to spread rumour and information is known to us all, and it seemed to me the best way to allow players to gain information about others.

Screenshot showing gossip about another

When chatting to Amos, he started talking about Orville Averill. We can now press for more information, or try and find out where he is.

As players chat to various characters, other people will come up in conversation. We can either choose to change the subject, or press them for information about that person. The AI tracks when each character was last seen by that person as well, so asking the right questions can help players track down difficult to find characters to complete certain missions.

Each conversation has a certain amount of patience attached to it - that’s what the little blue circles are in the screenshot. Asking questions ‘spends’ patience, which means that after a while we won’t get anything else out of a character and will need to come back later. The better we know someone, the more questions we can ask, and the better information we’ll get.

How to gain information effectively

In playtesting this has thrown up some suprising effects. For example, often the best people to get information from are those in prison: they have plenty of time on their hands and often know a lot of different types of characters:

Screenshot showing chatting to prisoner

Prisoners are often the best source of information about people, and they have plenty of time on their hands to chat.

People in prison usually don’t know where characters are though. For that we’re best off talking to bar staff, as they might have seen characters come in to socialise. Making friends with hotel receptionists will give us good information about people who travel a lot, and spaceport staff will often have seen characters passing through.

Barring any last minute issues, the demo should be out on the 22nd on the same day as the new Kickstarter launches, so you will soon be able to try it for yourself!

Click here to comment



How to add live code reload to your game

Posted Wed 19 August 2015 08:55

Adding live code reloading is one of the best things I did when working on my current game, Sol Trader.

Live code reload reduces our debug loop down to milliseconds. Now when I recompile the game, it notices I’ve done so and loads new code whilst the game is still running. Here’s a demo:

gif demo

Thanks to Casey Muratori (again) and his excellent Handmade Hero series for teaching me the basics, and to this github project for demonstrating how to do it in OSX, my development platform of choice.

There are a few architecture changes that we’ll need in order to put this feature in our code. Here’s how I did it.

Splitting our game code from our platform

Sol Trader now has a clearly defined platform layer, separate from the game. The game code itself knows nothing about the platform at all and it passed in everything it needs in order to calculate what’s next. Here’s the method that we call to run a game loop:

bool gameUpdateAndRender(Memory* memory, v2i screenDim, Input* input);

The update and render call takes some Memory, the screen dimensions and the input that we received this frame from the player. It is the job of this method to render the next frame to the screen, in under 16ms.

Memory is just a big chunk of raw memory allocated by the platform layer at the start of the game. The gameUpdateAndRender function is free to do what it likes with this space. It’s important to note that it’s persistent across live reloads which means that all state should be saved here. The game is not allowed to allocate any memory itself, it has to use the memory given to it.

gameUpdateAndRender actually is implemented as a call into a shared library (a DLL on windows, or a dylib on Linux/OSX) using a #define trick I learnt from Handmade Hero:

// Platform.h
#define GAME_UPDATE_AND_RENDER(name) bool name(Memory* memory, v2i screenDim, Input* input)
typedef GAME_UPDATE_AND_RENDER(GameUpdateAndRender);

// Game.cpp
extern "C" GAME_UPDATE_AND_RENDER(GAME_updateAndRender) {
  // game code here
}

(We need the extern "C" here to stop the compiler from mangling the name, so we can find it in the shared library.)

Running the game code

This is a cut down OSX version of the platform layer I’m using. Similar code exists for other platforms:

// Platform.cpp
void OSX_loadGameCode(GameCode* game, char const* path) {
  if ((game->code = dlopen(path, RTLD_LAZY | RTLD_GLOBAL))) {
    game->updateAndRender = (sol::GameUpdateAndRender*)dlsym(game->code, "gameUpdateAndRender");
    game->lastWriteTime = OSX_lastWriteTime(gameCodePath);
  }
}

void main() {
  Memory memory;
  allocateMemory(&memory);

  initOpenGL();
  v2i screenDim = createGameWindow();

  GameCode game;
  char const* gameCodePath = "soltrader.dylib";
  OSX_loadGameCode(game, gameCodePath);

  // Main loop
  while (!quit) {
    Input newInput;
    getInput(&newInput);

    // Check if the game has been recompiled
    time_t newWriteTime = OSX_lastWriteTime(gameCodePath);
    if (newWriteTime != game->lastWriteTime) {
      OSX_unloadGameCode(&game);
      OSX_loadGameCode(&game, gameCodePath);
    }

    if (game.updateAndRender) {
      game.updateAndRender(&memory, screenDim, &newInput);
    }
  }
}

At the heart of it, it’s a standard game loop. We first allocate enough memory using one big alloc call at the beginning. This is all platform specific code, so it’s ok to use OSX, Linux or Windows specific calls here. We figure out our screen dimensions from the platform, create a window, and initialise OpenGL or whatever graphics library we’re using.

Then we load the code using dlopen and if that succeeds, we find the gameUpdateAndRender function and save the location. In the main loop, assuming that all worked, we call the saved function with the info it needs to render the frame.

Building the shared library

Here’s how the build.sh script looks:

// Build the shared library
$CC $CFLAGS -dynamiclib ../src/Unity.cpp -o ../libsol.dylib $LIBS

// Build the executable
$CC $CFLAGS -o ../$EXE ../src/platforms/sdl2/Application.cpp $LIBS

We build the shared library containing only the game code, not the platform code. We then use the platform code to load and run the shared game library.

Summary: everyone should have live code reload

This is an amazing way to develop games. For too long in the past I have sat watching a long compile, then ploughed through the game from the main menu, to find the bug I’m trying to fix, only to find that I’ve made a stupid error and have to start again. We need to find fun as fast as possible - anything we can do to reduce the debug loop is a good thing.

Live code reload also does away with much of the need to use a scripting language (fast feedback). I don’t have any designers who don’t write C (it’s just me!) so I haven’t implemented one for this game. I also don’t need any GUI configuration files for layout, it’s all just implemented in C with live code reload for positioning tweaks.

Trust me: once you’ve tried it, you’ll never go back.

Click here to comment



Why I wrote Sol Trader's GUI code from scratch

Posted Sat 01 August 2015 22:25
The new rewritten GUI in action.

A decision to rework a major piece of infrastructure late on in a game’s development is pretty significant. It’s especially so if we’re replacing it with our own code written from scratch.

Yet about a month back, after plenty of profiling, I took the decision to remove the GUI library I was using from Sol Trader’s codebase and replaced it with my own.

The library I was using, libRocket, has many useful features and it got me a long way during the game’s prototyping stage. It is however written in C++ and extensively uses a large class inheritance tree with lots of virtual methods. I’ve written before about how this can potentially be a speed problem, and it turns out through profiling that this was indeed the case for my game. Because parts of the game are very GUI heavy, these performance problems surfaced quite quickly after building the final interface structure for city mode.

So, on 1st July, I set out to write a minimal GUI as quickly as possible, whilst at the same time reskinning the prototype GUI I had with the new look and feel. It took about 60 hours to both write the GUI infrastructure and reskin the interface. In that time I also implemented live code editing, revamped the asset system and vastly improved the efficiency of the renderer.

Here are a few reasons I went with the “from scratch” route rather than using different library:

Compilation speed is faster

I’ve been heavily influenced by Casey Muratori’s no-libraries approach to writing video games. Avoiding libraries really does shorten the debug loop. By pulling out the last major library and its dependencies, I doubled the build speed of the game.

The new Sol Trader coder is leaner and meaner that it has ever been: all 12,000 lines of code now compiles in under a second and updates the running game live.

I can write the minimum code I need

The current GUI that my game needs is around 1,000 lines of C code. I don’t need anything fancy and it doesn’t need to be made general purpose: it only has to work for what I need. By cutting out extraneous code I can keep complexity and code size right down to the minimum.

I gain architectural homogeneity

This is a fancy way of saying “the game code fits together well.” Now I’m writing my own GUI code I can create exactly the interfaces that the rest of the game wants to use. I can also build it with my own game’s constraints in mind: because of the way space travel looks on screen, a good frame rate is essential.

Summary: Is the “Not Invented Here” principle overrated?

In hindsight, I definitely made the right decision. Build speed is so important because the shorter our debug loop the faster we can iterate towards fun. Writing my own tiny GUI library within my game has meant that now there are no external barriers to a smooth frame rate.

I can now understand why there aren’t that many well established game GUI libraries out there. It’s relatively easy to write just enough GUI for what we need, and relatively difficult to write enough GUI so that everyone can use it.

I think “Not Invented Here” is overrated. As developers we’re often tempted to reinvent the wheel, and often that’s unnecessary. However, as long as we understand the concepts, sometimes it’s ok to rewrite the code without resolving the problem. Perhaps we need to focus more on not reinventing concepts and less on not rewriting code.

Click here to comment



Sol Trader will be at EGX in September!

Posted Wed 22 July 2015 07:00

EGX logo

Now that it’s almost reached the playable demo stage, I’ve been wanting an opportunity to show Sol Trader off in person. So we will be taking the game to EGX 2015 with our own booth!

My friend Richard Patching and I will be in the Rezzed area of the show - there will be plenty of opportunity to ask us questions and see the game in action. We’re also hoping that the man responsible for the amazing artwork, Aamar Rana, will also be there for a day.

If you’re from the press or a publisher and want to make an appointment for a demo or interview at the show, I’ll be available Thursday to Saturday morning. Send me an email to book a time.

Latest development plan

After finishing the new GUI and the city mode interface last week, the next major thing to do is to revamp the space mode again. We now have a continuous space model: it’s now possible to fly from one end of the Solar System to another, but it’ll just take a (very) long time…

This week, I’ve been adding jump gates back in to allow faster travel to and landing on the different planets, and I’m in the middle of adding particles back in. After that we’ll put back the AI ships, weapons and trading systems. Finally I’ll be balancing the interaction between characters, and adding simple missions.

By the time EGX comes around, we should have a playable demo and a new Kickstarter campaign running to to raise funds for a marketing push. Spending correctly on marketing is essential for any indie game, especially if not from an already known publisher. I’d like to raise enough money to budget for that, and to give everyone an opportunity to buy the game at an early bird price.

The final release will be early next year, once I’ve added the final features. It’s all coming together and it’s very exciting! Follow us on social media or join our mailing list on the website to keep up to date.

Click here to comment



3 new screenshots of Sol Trader's new interface

Posted Sat 18 July 2015 12:55

I’ve just released three new screenshots showing off the new GUI and space mode. Enjoy!

Looks like our in-game wife might have… other interests:

Flattery will get you… Protective Shoes?

Taking the Protective Shoes out for a spin.

Click here to comment



Trailer: How it will feel to move around Sol Trader's cities

Posted Fri 17 July 2015 16:16

Over the last three weeks, I completely removed all traces of our old GUI code and wrote a fresh GUI from scratch. I also entirely reskinned the GUI to the final look and feel of the game.

It’s been a huge amount of hard work, but I’m very proud of the result. I’ll talk more about the reasons for replacing the GUI soon, but in the meantime, here’s a gameplay trailer showing a short section of the new GUI in action!

In between travelling through space you’ll be spending some time hanging out in cities, hiring ships, taking loans and interacting with the citizens who live there. The trailer shows you playing a character called Harry with a wife and family, who heads to the bank to take a loan. What do you think?


Click here to comment



How Sol Trader uses information as currency

Posted Wed 24 June 2015 06:29

Screenshot showing you gaining information

There are two currencies in Sol Trader: Credits, which are used to purchase ships and goods, and Information, in the form of knowledge about events. Read on about I’m using information to enhance the gameplay.

Gaining information

When you start the game, you know about all the event that have happened to you, and many things that have happened to your close family and friends. The rest of the world, however, is a mystery.

As you chat to other characters in the game, they tell you about events in their past. You can continue the conversation by talking about something else that happened to you, exchanging one piece of knowledge for another. As long as you have similar information to share, they’ll keep about themselves and other people they know. If they tell you about an interaction they had with someone else, you get to learn about that relationship.

Some events are more private than others, and you’ll only get information about them if the character really trusts you, or they’ve had too much to drink…

Using information

This information can be “spent” in various ways:

  • A mission you’ve undertaken will often ask you to discover a particular piece of information in return for a reward.
  • You exchange information about sensitive events with other characters when chatting, in exchange for knowledge about more sensitive events.
  • Event knowledge could be sold to an in-game journalist for credits. This assumes the character is high status enough, or the event is notorious enough. This will really annoy the character that you’re exposing, though, so watch out! Any action in the game you take which has the effect of harming another character will generate a ‘backstab’ event, which can rebound back on you if you’re not careful.

Events have other effects, too. Beware of telling others about your sensitive events! If everyone gets to know about them, your ability to take work with organisations will become limited.

Most of this is already in the game. I hope to release a video or two in the coming weeks showing the gameplay in more detail.

Click here to comment



The difference review and planning makes to indie development

Posted Wed 17 June 2015 07:53

List your accomplishments. Make a realistic plan. Get enough sleep.

I’m currently in a pretty good groove working on Sol Trader’s development. Due to other work commitments I can only manage 2-3 days a week on it at the moment, but my productivity is pretty much at an all time high.

One of the things that’s helped me is reading a great article on how to motivate ourselves as indie game developers. One of the most helpful tips was to keep a list of all our accomplishments week by week, and to plan the week ahead. It sounds simple, but it’s already made a big difference to my work. Here’s how I do it.

List accomplishments from last week

On Monday morning I record a list of what I’ve done using Notes on my Mac. I trawl through todo list items, Github commits and my marketing plan. Here’s Sol Trader’s from last week:

## Time last week

1 full day plus 4 evenings

## Last week - code:

* Switched the renderer coordinate system around
* Added planet rendering
* Refactored rendering out of platform into game code
* Added normal maps and sun angle
* Show the correct planet on the background
* Fill essential vacancies
* Started work on entity sheet pane - loads of refactoring on it
* Refactored all relationships to separate component
* Custom rendering of ship images on GUI
* Auto-reload shaders on Cmd-R
* Tweaked the bloom code loads
* Introduced higher resolution planets
* Moved premultiply of alpha out to script on game start
* Fixed last seen location for friends
* Started ship hiring components

## Last week - marketing:

* Live stream
* Montage: focus
* Weekly promotional thread on /r/indiegaming
* Blog post on bloom
* Facebook ad on new main menu screenshot

This was enormously motivating for me: despite only giving half a week to the game I got a huge amount of development done! It’s worth really celebrating this achievement.

Plan the upcoming week

I then work out how much time I have to work on the game next week. Then I make a realistic list on the goals I want to achieve in the week, with loose estimates, based on the amount of time I have. Here my list for this week - as I have about 3.5 days, I’ve given myself 2.5 days of goals for the week, plus a stretch goal.

## Time this week

3 days plus 1 evening

## Next week goals

[X] finish relational currency work: 0.5d
[ ] Banks and borrowing money: first pass - 1d
[ ] Ability to hire ships: first pass - 0.5d
[X] Marketing: livestream - 0.25d
[X] Marketing: Montage: quote on motivation
[X] Marketing: Weekly promotional thread on /r/indiegaming
[ ] Marketing: Blog post: how I plan my week - 0.25d
[ ] Marketing: Friday Newsletter with a roundup of latest work - 0.25d

## Stretch goal:

Launching a ship - basics of space back in - 1d

It’s very important to pace ourselves here. We should not plan more work that we can realistically do. If we easily achieved last week’s goals, then we should plan a little more: if we didn’t achieve them, then we should ask ourselves why and do a thorough review. Also, we need to make sure we get enough sleep. I definitely need 7-8 hours a day - otherwise when I work on my game I end up subtracting value rather than adding it, and short-changing my family and other commitments.

This week, I’m already ahead of myself. I’ve almost finished adding in banks and borrowing money (the final thing I need to add is handling a loan default, which I’ll do this morning) and I should get ship hiring in today as well. The quote on motivation was popular on Facebook, which is encouraging, and the live stream went well. That leaves most of a day to get the newsletter and the ship launching code back in, which is my stretch goal.

Summary

Sometimes indie development can feel rather like moving the game from 46.001% to 46.002% completed each day. Without a clear measurement of progress, it can be a real struggle. I’ve found this process of review and planning enormously helpful. What methods do you use in order to stay motivated?

Click here to comment



How to quickly add bloom to your game engine

Posted Wed 10 June 2015 17:30

I rewrote Sol Trader’s bloom code last week. I originally added bloom over three years ago, and now I’m refreshing of the internals of the game, it was time to take a fresh look at it.

bloom before and after

Sol Trader's new main menu, before and after bloom was reapplied

The last time that I added bloom to the engine, I had complex and clever code all over the place in order to make bloom optional. This time I’ve simplified it by turning bloom on for everyone. It makes the game look so much better, and these days the chances are small that people cannot run with it turned on.

This is how I did it, along with some example screenshots and some OpenGL sample code.

Step 1: render the source images

First, we render the original image to a temporary buffer. At the same time, we render any glowing parts of the image to a glow buffer.

bloom step 1

Left is the original texture. Right is the glow buffer

This is how we set up OpenGL to draw into two buffers:

cpGenFramebuffers(1, &fb);
cpBindFramebuffer(CP_FRAMEBUFFER, fb);
GLenum fboBuffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
glDrawBuffers(2, fboBuffers);
cpFramebufferTexture2D(CP_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mainBuffer, 0);
cpFramebufferTexture2D(CP_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, glowBuffer, 0);

(The ‘cp’ prefixes are my backwards compatible wrappers for OpenGL functions - see the section below on backwards compatibility.

Once we’ve set this up, we refer to gl_FragData[0] and gl_FragData[1] in our fragment shaders. In this snippet from the GUI shader, I’m adding 9% of the GUI’s colour in to the glow buffer to give it a tiny bit of glow:

gl_FragData[0] = colour;
gl_FragData[1] = vec4(colour.rgb * 0.09, col.a);

Step 2: Copy the glow buffer to several smaller buffers

bloom step 2

All we’re doing here is drawing the glow buffer to several other textures:

// Select the VBs for the vertices and the UVs
glBindBuffer(GL_ARRAY_BUFFER, fullscreenVertsVB);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, bottomLeftUvsVB);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);

glUseProgram(copyProgram);
glUniformMatrix4fv(matrix, 1, false, identityMatrix);
glActiveTexture(GL_TEXTURE0);
glUniform1i(texture, 0);
// Draw from the glow buffer
glBindTexture(GL_TEXTURE_2D, glowBuffer);

// Draw to the half texture
glViewport(0, 0, width / 2, height / 2);
cpFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, halfBuffer, 0);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

// Draw to the quarter texture (repeat for even smaller buffers)
glViewport(0, 0, width / 4, height / 4);
cpFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, quarterBuffer, 0);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

Step 3: Blur the glow buffer and smaller buffers

bloom step 3

This is the clever bit. We use an optimised Gaussian filter process on each of the glow textures. To make it fast, we blur in two passes: horizontally to a temporary buffer, and then vertically back to the previous buffer. We also take advantage of linear texture filtering to sample between the pixels to get both colour values.

This speeds up the process massively for the GPU - it brings the number of texture lookups down from 25 to just six. See Philip Rideout’s excellent article for further explanation.

The OpenGL code is similar to the previous step:

glUseProgram(blurProgram);
glUniformMatrix4fv(matrix, 1, false, identityMatrix);
glActiveTexture(GL_TEXTURE0);
glUniform1i(texture, 0);

// Vertices and UVs are already set up from the copy step above

glViewport(0, 0, width / 2, height / 2);
glBindTexture(GL_TEXTURE_2D, halfBuffer);
glUniform2f(offset, 1.2 / width, 0);
cpFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, halfBufferBlur, 0);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

glBindTexture(GL_TEXTURE_2D, halfBufferBlur);
glUniform2f(offset, 0, 1.2 / height);
cpFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, halfBuffer, 0);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

Here’s the fragment shader that does the actual blur:

void main() {
  vec4 c = vec4(0);
  c += 5.0 * texture2D(texture, uv - offset);
  c += 6.0 * texture2D(texture, uv);
  c += 5.0 * texture2D(texture, uv + offset);
  gl_FragColor = c / 16.0;
}

Step 4: Combine these smaller buffers together into the result.

I’ve overdone the bloom effect on this scene so we can see the effect it has:

bloom step 4

The OpenGL code simply sets up a new shader and selects all of the textures. The fragment shader then combines them all together:

void main() {
  vec4 vOriginal = texture2D(uTextureOriginal, uv);
  vec4 vT1 = texture2D(uTexture1, uv);
  vec4 vT2 = texture2D(uTexture2, uv);
  vec4 vT3 = texture2D(uTexture3, uv);
  vec4 vT4 = texture2D(uTexture4, uv);
  gl_FragColor = clamp(vOriginal + vT1 + vT2 + vT3 + vT4, 0.0, 1.0);
}

Making this backwards compatible

Rendering to a texture didn’t become standard in OpenGL until version 3.0 was released in 2008. Thankfully the extension has been around since about 2005, so most if not all drivers do support it in some way. I used glew and a series of macros like this one to choose between either the extension or the standardised version:

#define cpGenFramebuffers(a, b) \
  ((GLEW_VERSION_3_0 || GLEW_ARB_framebuffer_object) ? \
   glGenFramebuffers((a), (b)) : \
   glGenFramebuffersEXT((a), (b)))

Now I can use call cpGenFramebuffers and have it call the right thing for any graphics driver.

Summary

The end result looks just great, and really makes our games come alive and look that much more professional. Thanks to the rewrite, I’m able to render much brighter bloom than with my previous code. It’s important not to overuse this effect (there’s already way too much lens flare out there) but it’s amazing just how much a even a little bit of bloom lifts a scene.

Take a couple of hours and put bloom into your game engine. You’ll be glad you did.

Click here to comment



The huge difference a good Entity System could make to your game

Posted Wed 03 June 2015 10:17

Continuing a general theme of discussing the nuts and bolts of Sol Trader’s design, this post is about the huge difference the recent decision to move to an decent Entity System with components has made to the flexibility of the underlying engine.

In case you’re not familiar with Entity Systems, I’ll summarize briefly why they’re important and how they work.

The problem

Most games have multiple things in them that work in similar but varying ways, such as players, bullets, walls, trees, weapons, and so on. The Entity abstraction is a useful one to encode this – all things in the game share basic properties (such as position), but have special behaviour in certain circumstances.

Here’s how Entity systems have often been approached in the past:

class Entity {
  int x, y;
};

class Player : public Entity {
...
};

class Monster : public Entity {
...
};

We have general shared behaviour across all entities stored in the Entity superclass, and special case behaviour in the classes underneath it.

After a while, we come up against two different entities that need to have the same behaviour. To solve this, we might attempt to insert a class in the middle of the hierarchy:

class Destroyable : public Entity {
  int health;
};

class Player : public Destroyable {
...
};

class Monster : public Destroyable {
...
};

However, this quickly becomes unworkable. Inheritance hierarchies are fairly rigid, and this increases with complexity. It’s not easy or desirable to specify in advance all of the different behaviours that our entity might want to have. If for example we wanted to share two different types of behaviour between two other entities, then we might be stuck at that point.

In theory you could use multiple inheritance, but this is a bad idea. See the deadly diamond of death if you’re not familiar with why this could be a problem. Also these designs can rely on virtual functions to override behaviour, which are fundamentally slower to execute.

A solution using components

A way around this problem is to ditch the idea of inheritance entirely (I’d done this already by switching away from C++ at the beginning of the year) and instead break up all your entity behaviour into separate components, which are then associated with each other via an ID.

Here’s a great diagram of an entity system using components from Cowboy Programming:

Entity system diagram

In order to code this in C, we just have the following code to represent an entity:

struct GameState {
  uint32 nextEntity;
};

uint32 pushEntity(GameState* state) {
  return state->nextEntity++;
};

That’s it! An entity is denoted by a simple counter, and has no data attached to it. All the data lives in the components.

Here’s a snippet of the initialisation code from Sol Trader for Human and Ship:

// Human
uint32 humanId = pushEntity(state);
pushEventful(state->history, arena, humanId);
pushHistoricalFigure(state->history, arena, humanId);
pushNameable(state, humanId)->type = NAMEABLE_HUMAN;
pushEnterer(state, humanId);

// Ship
uint32 shipId = pushEntity(state);
pushNameable(state, shipId)->type = NAMEABLE_SHIP;
pushRenderable(state, arena, shipId);
pushEnterer(state, arena, shipId);

Here I’ve listed a few of the components in Sol Trader’s current system:

  • Eventful: Attach this component to entities which can have historical events (currently humans and organisations.)
  • HistoricalFigure: Attach for an entity with a human-like history. Only used for humans.
  • Nameable: Attach to entities with names. This component has different types depending on how it is being displayed. All Nameable entities can can be renamed by the player, allowing them to customise the names of lots of different things in the system. Used for humans, organisations, ships and homes.
  • Enterer: Attached if an entity is allowed inside an entity with the Enterable component.

It’s now trivial for several entities to share the same component, which hits on one key advantage: re-usability.

If you’re interested in more, then this blog post series does a pretty good job of explaining the above in more detail.

Why this is so important

The cost of development is a huge barrier to quickly prototype new ideas for our games. Anything we can do to bring this down allows us to try more ideas and get to ‘fun’ as quickly as we can. The longer it takes to build a new type of entity, the slower the prototyping of new ideas.

It’s so much easier to prototype with entity systems: you can much more easily reuse behaviour between components. Here are some advantages I’ve discovered in just the last two weeks:

  • Added Nameable to ships meant customisation for free. It’s really important to me that the players can rename lots of different things in the game. Previously I would have had to spend ages refactoring the naming code to make it usable across entities. By spending about 45 minutes implementing Nameable for ships, I got customisation for free.

  • Adding landed ships to the GUI took less than 20 minutes. I simply reused the Enterer component for ships, and because they were also Nameable they simply popped up on the GUI in the list of people. After straightening out a few assumptions in the GUI that all Enterer entities also had HistoricalFigure, the game was back up and running.

  • Adding homes for humans took about 2 hours. I wanted to try the idea of humans all having their own homes visible on the planet GUI. Up until now, this was implemented via a simple flag. Adding new entities for homes with a few components on game start caused them to pop up in the GUI immediately. Seeing the human homes on the GUI felt great - but if it hadn’t been so easy to add, I might not have attempted it. It also allowed me to delete a stack of special-case movement code. Wonderful.

  • Components save memory. Previously to create a human in history generation meant you had to store all the data the human could possibly need, even though many humans would die before the game began. With an entity system, I could only add the component I needed for generation, and add the rest of the components to humans that survived to the game start. This also speeds the generation up: the history generator now iterates through less data allowing more efficient use of the memory cache.

I can’t imagine building another game without a decent Entity System. It’s transformed my prototyping speed and is very extensible. There are a few disadvantages, but they pale in comparison to the benefits.

How do you organise your Entities? Do you use a similar system?

Click here to comment



How tone of voice works in Sol Trader's dialogue system

Posted Wed 27 May 2015 10:45

Hot on the heels of the main dialogue system in Sol Trader, I’ve been working on adding tone of voice to the system. I think this will add a lot to the way that the dialogue system works. It will allow for some interesting and thematic interactions, like the one below:

tone of voice

Perhaps I should have chosen a better subject :) Read on for more about how it works.

How tone of voice works

Each tone of voice that can be used has two character attributes attached to it, which are opposed against the other. For example, if you attempt to flirt with someone, your “charm” (basic flirting ability) is pitched against their “wisdom” (how easily they can see through you.)

You select a tone of voice and a conversation subject. We then roll a dice for each person and add their relevant attribute. If your score is greatest, any test that is conducted on the selected conversation subject is that much easier to succeed on. For example, if you’re trying to borrow a ship, or get a bargain, attempting to impress (or flirt with) the person you are speaking to might make the chance of getting what you want that much greater.

However if you fail the tone of voice test, it makes it much harder to succeed in what you’re trying to do. So you have to be careful which tones of voice you select. It pays to use tones for attributes that you are particularly strong in. It also pays to avoid tones where the person you’re talking has a high resistance, if you know them well enough to know what these are. For example, if your conversation partner has high wisdom, flirting with them is unlikely to lead to a successful outcome unless your charm is also very high.

Under the hood: how to mod it

The tone of voice data is completely customisable via a simple CSV file format. Here are some example tones:

String, you,   them,    effect success string,   effect failure string
   TONE_FLIRT, CHARM,  WISDOM, TONE_FLIRT_SUCCESS,      TONE_FLIRT_FAILURE
 TONE_IMPRESS, MIND,   CHARM,  TONE_IMPRESSIVE_SUCCESS, TONE_IMPRESSIVE_FAILURE
TONE_OBLIGING, WISDOM, MIND,   TONE_OBLIGING_SUCCESS,   TONE_OBLIGING_FAILURE

The idea is that people can mod both the different tones of voice that characters are able to use, but also the attributes that are checked when running the tests. It’s easy to add any tone you want: there’s a lively Facebook discussion on Indie Game Developers with lots of ideas for tones that could be added:

Can you think of any others we might add?

Click here to comment



How dialogue works in Sol Trader

Posted Wed 13 May 2015 15:29

I’ve recently designed a dialogue system for Sol Trader. When deciding how to support dialogue, I researched all the different ways that these systems are normally done in video games: I wanted to ensure that our system is as flexible and as immersive as possible. I’ve gone for a hybrid of all the methods I discovered and I explain how it works at the bottom of the post.

Dialogue research

new conversation preview
A basic preview of the new dialogue interface

There are a number of different methods of doing conversations in games, summarised informatively in these two excellent Gamasutra articles. I’ve summarised the most relevant ones here:

  • Non branching dialogue. Players walk up to the character and they deliver their message, which is often the same each time.

  • Branching dialogue. The classic ‘conversation tree’ approach. A preset piece of dialogue is delivered and a player has an option to choose from a range of options in reply. This then delivers another response, and the process is repeated. This is better than the non-branching approach, but can lead to linear and frustrating conversations where the player feels they’ve missed out on a vital piece of information.

  • Hub-and-Spokes dialogue. This is similar to Branching Dialogue above, but in this version the player chooses from a range of options on a ‘hub’ of the conversation. After hearing the response, the player is normally returned back to the main hub, or sent to a deeper hub with more options to choose from. Players can therefore exhaust the conversation options with a particular character, which can lead to rather unreal conversations if the character has infinite patience.

  • Parser driven dialogue. The game attempts to understand the natural language typed in by the player and responds in turn. This is relatively rare in modern games, Façade being a notable exception. The number of responses required to keep the conversation feeling natural is very time consuming to produce, and the potential for the game to misunderstand the player’s intentions is very high.

  • Time limited dialogue. In this version a player only has a certain number of interactions they can conduct during any particular time period, and much choose who they spend time with and what they choose to find out. This creates some interesting and potentially agonising choices for the player, although with a fully scripted game the player won’t get to explore all the options available.

Under the hood: Sol Trader’s conversation system

Conversations are something that Sol Trader has to get right. I decided as far as possible that the gameplay should be based around the character interactions, so the player must enjoy the process and not get frustrated with it.

I have gone for a variation on the Hub-and-Spokes method: a rules based system for choosing options, the addition of tone of voice, and two time limiting factors: patience and time of day.

Patience

When you start a conversation with a character, they have a certain amount of patience for you. This is based on their Wisdom attribute (which is generally used for emotional intelligence and maturity). It’s also modified depending on what they’re doing: if they’re languishing in prison they’ll have a lot more time for you, but if they’re on guard duty they won’t be able to stand around talking all day. If you’re a good friend they will put up with you for longer, but if they can’t stand you, you’ll get hardly any time at all.

You ‘spend’ this patience with every conversation statement you choose. Some statements require a test which will affect how much patience the statement ended up taking. Once you’re out of patience, the conversation is over. Patience regenerates slowly: you won’t be able to immediately start a new conversation with someone if you’ve just finished talking their ear off.

Tone of voice

You’ll be able to select a particular way that you say something, allowing you to flirt, to be extra obliging, try to impress the character, and so on. This will affect both the amount of patience you use up, and any tests the selected conversation statement requires.

I’ll talk more about tone of voice and how it’s implemented in a future post.

Time of day

Character go to work in the morning, and go home or out socialising in the evening. The conversation options available to you will vary depending on what they’re doing, so you’ll have a limited amount of time to interact with them.

Example: a basic greeting

Two typical conversation statements might have the following data:

Required Character Activity: At reception
Minimum Closeness: Personal friend
What to say: "Hey $firstname! Such a pleasure to see you! Anything I can do for you?"
Required Character Activity: At reception
Minimum Closeness: Unknown
What to say: "Hello. How can I help?"

Each of these two statements is checked whenever either the player needs to choose an option, or the character needs to make a response. In this case, this is the initial greeting. If you are a personal friend of the character, they’ll greet you in a warm and friendly manner. If they don’t know who you are, they’ll be much more business-like.

(You can watch me implementing this basic set of statements on this livestream archive video.)

Example: making small talk

Here are a set of conversation statements for small talk:

Required Character Activity: Socialising
What to say: Make small talk
Attribute to test against: Charm
Difficulty: Normal
Patience cost: 1
Tag on test success: SMALL_TALK_SUCCESS
Tag on test failure: SMALL_TALK_FAILURE
Required Character Activity: Socialising
Required tag: SMALL_TALK_SUCCESS
Patience modifier: -1
What to say: You have a long discussion about sports with $firstname.
Required Character Activity: At front desk
Required tag: SMALL_TALK_SUCCESS
Patience modifier: 0
What to say: You chat briefly about the traffic jam outside on the street, agreeing that the local council should ban cars from the area.
Required Character Activity: Socialising
Required tag: SMALL_TALK_FAILURE
Patience modifier: +1
What to say: You attempt to engage $firstname on a discussion about weather vanes geometry with little success.

The player has the option to choose the first statement, which is making small talk. Note that the other options aren’t available as the SMALL_TALK_SUCCESS and SMALL_TALK_FAILURE tags aren’t set. If the player selects this option, then a test on your charm is conducted: if works then the SMALL_TALK_SUCCESS tag is set.

There are two statements that become available once that tag is set, and the choice will depend on whether you are socialising or chatting at a reception desk. If you’re at reception, the cost of the discussion remains 1 for the initial small talk statement, but if you were socialising, this response will give back your patience point to reuse on another statement. People have a tendency to rattle on when at the local bar!

What do you think? Can you think of anything this system doesn’t cover?

Next time I hope to have a short video showing off the basics of the system.

Click here to comment



How face generation works in Sol Trader

Posted Wed 06 May 2015 09:52

We’re finally getting customised faces for characters in Sol Trader! Here’s a preview of some of the different faces that can be generated:

Face piece selection

There are created from individual face pieces that are overlaid together to produce the final result:

Face piece selection

Read on to find out how the code works under the hood.

Faces are completely moddable

Our face generation configuration file is found in face_pieces.csv. All the main data files in Sol Trader are now in CSV format to make modding super easy:

piece,gender,count,chance
male_base_face,MALE,1,100
male_nose,MALE,10,100
male_eyes,MALE,5,100
male_eyes_overlay_cyber_eye,MALE,1,5
male_hair,MALE,10,91
male_ear,MALE,5,100
male_mouth,MALE,1,100
male_scar,MALE,1,5
male_suit,MALE,1,100
male_t_shirt,MALE,1,0
male_beard,MALE,5,30
eyeware,MALE,2,5
female_base_face,FEMALE,1,100
...

Each piece has its own line, with the name of the piece, the gender it belongs to, the number of options for that piece, and the percentage chance the feature is present or not.

It’s pretty trivial to add your own extra options or entirely new face features! The only current restriction is that there must be less that 256 options for a face piece, and under 12 different face pieces in total, although I can increase these limits if modders need more room.

Faces are genetically inherited

Once thing that I really wanted to get right was generated characters looking similar to their parents. In the game the faces are stored for each individual as an array of numeric options, with each face only three bytes in total:

struct Face {
  uint8 pieces[12];
};

The game chooses a new character’s face in a similar way to the way it inherits other attributes from parents. When deciding on a face (when the character reaches the age of two), we go through every face piece in turn. 50% of the time the character will inherit that piece from the parent they most resemble, 25% of the time they will inherit that piece from the other parent, and 25% of the time the face piece is random, to simulate genetic mutation.

This process produces faces that resemble their parents, but aren’t exactly the same. There are currently 66,000 combinations of faces for each gender so you’re unlikely to come across two the same.

Still to do

We’ve currently only modelled Caucasian faces. We’re adding in other ethnicities soon.

Notice also that there aren’t any older faces: Sol Trader is set in the 24th century, but technology hasn’t sufficiently advanced to make 94 year old characters look like they’re in their late 20s! I like that way the Crusader Kings II does ageing with faces, where they visibly get older over time. The drawback is always artist time required to produce these, but we’re hopefully going for a simple overlay which could have the right effect.

What do you think?

Click here to comment



How I'm using Proxemics in Sol Trader's game design

Posted Tue 28 April 2015 20:01
new relationships
Your relationships, shown closest first. Your relationship with your father has cooled lately...

I’ve been trying to get to the heart of Sol Trader’s gameplay in recent months. I’ve been working on rewriting the history generation system in pure C, and concentrating on the interactions between the player and the characters in the game.

This week I completely replaced all the relationships code to make it more manageable and more fun. Read on for a comparison of the old relationship system and the new one, and why the new code is better and more fun for the player.

The old system: numerical levels

Previously a relationship between two people consisted of a status field which described the type of relationship (parent, child, sibling, spouse, etc) and a numerical value from -10 to 15 which described the strength of the relationship. Negative values meant that the characters were enemies, and high positive values signified close friendships.

Each year the history simulation would go through the list of relationships for each character, do some tests on them and work out whether the level should drop or rise. If the level went through a threshold, the relationship might change (people married, divorced, fell out etc).

This worked well enough, but it had some problems. For one thing there was no limit on the number of people a character could befriend. High charm characters had hundreds of extremely close friends, which is hardly realistic. Also, the generation was slowing significantly as a few highly networked characters shared every last detail of their lives with all their friends and relations.

The new system: Proxemics for relationships

Personal space diagram

To counter this, I’ve moved to a simpler system based on the social psychology concept of Proxemics. Proxemics is the study of personal space between people: I’ve used the idea to limit the levels of relationships that each character can have. The idea is that each person is allowed a number of relationships at each of four levels:

  • Intimate: sharing highly personal information with 1-2 very close people
  • Personal: for 4-6 good friends
  • Social: another 5-10 friends and acquaintances who share more public information and gossip
  • Public: other acquaintances, co-workers and random people the character comes across

Each year during history generation, all these relationships are tested for each character and can move up and down the list. New people can be suddenly introduced at a high level: get a new boyfriend or girlfriend and the character’s older family relationships can be pushed down to a lower level, as there’s only room for a few people that close to us. When a type of relationship breaks into a new more intimate space, certain events can be trigged (marriage, for example.)

There’s a hard limit to the number of relationships a character can have in total. This means relationships which bubble downwards can vanish over time as the character loses touch with friends and distant relatives.

The benefits of the new system

There’s both a realism and a fun boost with the new code. It’s much easier for the player to manage and keep track of the number of people a character knows, so that they can use that network to their own advantage. It’s also feels more realistic: low charm characters have many fewer relationships, and even characters with high charm don’t have an overwhelming number. It’s great fun to scroll through a character’s known relationships and see who they’ve chosen to be close to.

The history generation is also faster now, as I’m storing fewer relationships and less information for each, which means more info is being fetched each cache miss (see this article for why this matters). Overall it’s a win for realism, fun, speed and code simplicity and I’m pretty happy with it so far.

Do you think this model works well for modelling relationships? Anything I can improve?

Click here to comment



Why I ditched all the build tools in favour of a simple script

Posted Wed 22 April 2015 10:42

white elephant

Build tools are wonderful and impressive constructions. We developers invest colossal amounts of time, effort and code into their creation and maintenance.

Perhaps a lot of this work is unnecessary.

On Sol Trader, by ditching the complex dependency checking compilation system I was doing in favour of a simple homegrown script, I cut my build time from several minutes down to 5 seconds.

I’m not talking about continuous integration tools such as Jenkins, but tools such as CMake, Boost.Build and autotools. Perhaps these build tools are white elephants? They require endless maintenance and tinkering: does this outweigh their actual usefulness?

Incremental compilation: the end of the rainbow

One of the main aims of a compilation tool is to allow us to divide all the pieces of a system up into component parts to be built individually (another main aim is portability, which I’ll address below). This allows us to only build the part of the code which changed each time, and link all the compiled pieces together at the end.

However every time we build a source file, we have to grab a piece of code, grab all the dependencies of that code from disk. The disk is probably the slowest thing in our machines, and we have to grab everything from disk every time, for each source file we’re building. If we’re building a lot of files, this can get very slow.

The second problem with this is when we change an often-reused piece of code, such as a header file, we have to compile the whole lot again. In order to cut the amount of things to build down, we can set up complex dependency management systems to try to limit the amount of things built. We can also set up a precompiled header which tries to minimise disk access by building a lot of the code in advance for us, but more and more of our time is handling the side effects of pushing for an incremental build system.

Trying to get a build tool set up is like searching for a pot of gold at the end of a rainbow, which gets further away no matter how much effort we put into finding it. Even when it’s working, it’s not that fast, and it requires constant tinkering to get it right.

How I build code now: the Unity build

How about instead of building incrementally, we build everything every time? Sounds counter-intuitive, doesn’t it? It’s actually faster, easier to maintain, and doesn’t require setting up a complicated build tool.

We create one Unity.cpp file. This includes all the C files and headers that I wish to build. We build that one file each time, and then link it with the 3rd party libraries. Done. It takes about 3-4 seconds to run, or 10 seconds on the Jenkins server.

Now, when I change a header, the script just builds everything again, so it doesn’t take any long that a few seconds to see the effects of any change I want to make.

Caveats

“Strategy is about making choices, trade-offs; it’s about deliberately choosing to be different.”

– Michael Porter

There are a few caveats with Unity builds that we should be aware of:

One compilation unit means no code isolation

The static keyword will stop working as we expect: we won’t be able to constrain variables and methods to one file any longer. The power of good naming helps us out here. We also have to be disciplined about keeping our code modular and not referring to code that we shouldn’t.

We still need to discover platform-specific properties

On an open source project which must be built everywhere, we’re never going to get away with something as simple as this: we’re going to need to check to see what headers exist and which libraries are available.

However, there’s no reason we can’t set up make to do a simple unity build such as this one.

Also, many of these portability problems we patch over with our build tools stem from the fact that our code wasn’t correctly written to be portable in the first place. Also, many build systems still in wide use today have a lot of cruft left over from the 1980s - do we really still need to check for the presence of <stdlib.h>?

Additionally, in the case where we can control our build environment, it becomes even easier: we simply create a build script for each compilation platform we need to support (a build.bat for Windows, for example).

Sol Trader’s Unity build setup

This is my current build setup for Sol Trader in its entirety.

#!/usr/bin/env bash

MACOSX_DEPLOYMENT_TARGET=10.6
CC=clang++
EXE=sol
CFLAGS=" -DGLEW_STATIC -DSOL_SLOW -DCURL_STATICLIB -DNDEBUG -D_GNU_SOURCE=1 -D_THREAD_SAFE -g -O0 -I.. -I../src -I ../lib/include -I ../dist/build/include -I../dist/build/include/boost -O0 -I ../dist/build/include/freetype2 -I ../dist/build/osx/include -I ../dist/build/osx/include/SDL -Wall -Werror -Wno-unused-private-field -Wno-unused-variable -Wno-missing-braces -mmacosx-version-min=10.6 -F../dist/build/osx/frameworks"

LIBS="../dist/build/osx/lib/libSDL_mixer.a ../dist/build/osx/lib/libvorbis.a ../dist/build/osx/lib/libogg.a ../dist/build/osx/lib/libvorbisfile.a ../dist/build/osx/lib/libyaml-cpp.a ../dist/build/osx/lib/libRocketCore.a ../dist/build/osx/lib/libRocketControls.a ../dist/build/osx/lib/libRocketDebugger.a ../dist/build/osx/lib/libfreetype.a ../dist/build/osx/lib/libpng15.a ../dist/build/osx/lib/libboost_system-mt.a ../dist/build/osx/lib/libboost_filesystem-mt.a ../dist/build/osx/lib/libboost_thread-mt.a -l SDL_image -l SDLmain -l SDL -L ../dist/build/osx/lib ../lib/libcurl.a ../dist/build/osx/lib/libz.a -Wl,-framework,Cocoa -Wl,-framework,OpenGL -headerpad_max_install_names"

set -e
set -x

mkdir -p build
pushd build
$CC $CFLAGS -c ../src/Unity.cpp -o Unity.o 2>&1 | sed 's|../src|src|'
$CC $CFLAGS -o ../$EXE Unity.o ../src/main.cpp $LIBS 2>&1 | sed 's|../src|src|'
date
popd

This is working fine for me right now. It’ll need expanding on in the future, but instead of spending endless time screwing with my build system now, I’m actually adding game features instead.

Want to hear the other side of the debate? Here’s a well-argued opposing point of view: the evils of unity builds.

Click here to comment