Germination X: Player characters

Posted May 15, 2012 by Dave Griffiths

After another code sprint on Germination X, I've added player characters (avatars) to the game. Based on the falmouth focus group feedback this seemed one of the major things missing that players felt would improve the game.

The character design came from the Mandrake plant, which has been cropping up in groworld projects for some time - as a magical plant known to resemble human forms as it grows.

This change also allowed a much needed clean up and decluttering of the user interface for the game - as navigation now happens by moving your mandrake around by clicking on things. Your location is persistent, so when you log in you go back to the same place. All existing players in the game have been given mandrakes scattered around the world.

As the mandrakes represented a new type of entity in the world, able to move around, and linked to players - this was quite a lot of work, particularly in terms of updating the existing database. I had a lot of trouble doing this manually with MongoDB'ssave command in the script interface. This seemed to be creating duplicate records (and creating very hard to track down bugs) that took a long time to find. The better approach seems to be to upgrade the database automatically in the game code, by checking a stored version number - and mapping over entries like this:

;; map over each player in the db (db-map!(fn[player](println"upgrading"(:name player)"to include tile and avatar");; get a random tile in the world(let[tile (first(db-get-random-one:tiles{}))](db-update!;; update it, adding an avatar:tiles tile (merge tile {:entities(cons(make-avatar(:id player)(:name player)(make-vec2;; random position(rand-int5);; in the tile(rand-int5))(:layer player);; show the player's score on the avatar(count(:flowered-plants player)))(:entities tile))}));; add the tile location to the player;; so we can find the avatar again(merge player {:tile(:pos tile)}))):players)

This also means that the latest code will work with snapshots I've taken of the game world regardless of how old they are. This turns out to be really important - I can try some changes and rewind the whole world back to the same starting point, as well as testing code locally on a copy of the current public world version.