Map rendering with OSM and HTML5 canvas

This week I’m trying to get as much code done on the borrowed scenery game as possible – today, fixing the map rendering.

I decided to load map tiles from OpenStreetMaps directly rather than using OpenLayers. This is done quite simply, accessing the millions of pre-rendered png files with URLs in this form:

a.tile.openstreetmaps.org/z/x/y.png

Where x and y are the tile coordinates and z is the zoom level. The question is, given a GPS coordinate – how do you find the right tiles? Luckily the OSM site is very helpful. This is what I’m using, where lat and lon are specified in degrees:

function latlon_to_tile(lat,lon,zoom) {
    with(Math){
        var m=pow(2,zoom);
        var lat_rad=lat*PI/180;
        return [floor((lon+180)/360*m),
                floor((1-Math.log(tan(lat_rad) + 
                       1/cos(lat_rad))/PI)/2*m)];
    }
}

I’m then doing quite a bit of work chopping the images up to create a 4×4 grid of game tiles for each map tile on the fly before the perspective transform. This brought up an issue with processing images loaded from domains other than the current server – try and do anything with the data you’ve loaded other than display it and this happens:

Unable to get image data from canvas because the canvas has been tainted by cross-origin data.

The answer is quite simple, as presumably it’s quite rare for this to actually cause vulnerabilities (perhaps if executing image data in some way?) you can simple add this property to the image:

image.crossOrigin = "anonymous";

And everything works as normal, cross origin data can be treated as if you’ve loaded it locally. I’ve also spent quite a bit of time fiddling around with the scaling to make the street names visible. There will probably be some more image processing to come. I also found another MMO game that used OSM data: Monopoly City Streets.

Clay mushrooms

More work on the Borrowed Scenery project and a first screenshot, experimenting with different visual styles. I’m trying modelling clay to get a 3D look on the fungi and using Theun Karelse’s mockup characters for player avatars. The floor is being built out of map tiles of Ghent pulled from OpenStreetMap, using the OpenLayers API which has been pretty fast to get running.

A lot is changing with code too, the client graphics are now entirely HTML5 canvas, the server is running a modified version of the Germination X game, switched to using websockets and upgraded versions of all the clojure libs.

Borrowed Scenery 1.0 – joining imaginary and physical spaces

FoAM is building a story for Electrified III: The Responsive City in Ghent in September. It’s called Borrowed Scenery 1.0 and follows on from our previous Borrowed Scenery 0.1 in the same city in 2009. The story will be built out of parts arising and inspired from the groworld project – human plant interfaces, but with a focus on physical narratives and alternate realities based in the city.

One of my tasks is to take two of our existing projects, Germination X and Boskoi and bring them together – absorbing the physical space of a city into an online game, as well as using a mobile foraging application as a way to propagate pieces of the overall story. This is a good chance to prototype some ideas for combining imaginary online spaces with physical spaces, online players from all over the world and people foraging in the streets of Ghent.

I’m starting with the game, and a working sketch using Maja’s visual references for inspiration – some of the ideas here include:

  1. Representing plants found by Boskoi foragers as characters – the bubble plants with feet are the plants from our world in the game’s reality.
  2. Using the map of the city as terrain – which becomes deformed by the activity of players.
  3. Mixing different styles, organic and digital elements – but focusing on sculptural and 3D objects (rather than Germination X’s mainly 2D look).
  4. Use of many more minor and major characters (e.g. the chicken in the lower left).
  5. Use of Lingua Ignota – the “unknown language” of Saint Hildegard of Bingen, who’s viriditas or ‘greenness’ is an important element of this story (the pope is also making her the 35th “Doctor of the Church” on the 7th October, while the festival is happening).

Further ingredients will include the music of Stevie Wishart, plenty of patabotany and a good dose of tarot.

Websockets vs HTTP

A bit of R&D this morning into websockets. Previous games like Naked on Pluto and Germination X have made use of standard HTTP protocol for their client server communication. This is easy to set up (as a newbie web programmer) and fine for prototyping and proof of concept – but has some serious problems with regard to scale.

The first problem is that the direction is one way, clients always have to call the server in order to get data. This has serious impact on how realtime applications work – as they need poll – “has anything changed yet”… “has anything changed yet”…

More seriously, the server has no real notion of who the client is and what they have received already, so all the data needs to be sent for each poll. This results in duplicate data being sent, and is a waste of bandwidth.

Underlying the HTTP protocol are sockets for sending the data – each request is treated as a distinct event so a socket is created and destroyed to return the response. A better way is to hook into this lower level and use sockets directly – each client then has a unique connection on the server, and data can be sent in both directions. Also the server is told when the socket is disconnected so things can be cleaned up.

On the client side, websockets are a standard part of HTML5 so they are fairly simple to use from Javascript:

socket = new WebSocket('ws://localhost:8001/websocket');
socket.onopen= function() {
    socket.send('hello from client');
};
socket.onmessage= function(s) {
    alert('server says: '+s.data);
};

On the server I’m using Clojure, and after a bit of fiddling around with my own socket server implementation, I found Webbit which takes all the hassle away:

(defn -main []
  (println "starting up")
  (doto (WebServers/createWebServer 8001)
    (.add "/websocket"
          (proxy [WebSocketHandler] []
            (onOpen [c] (println "opened" c))
            (onClose [c] (println "closed" c))
            (onMessage [c j]
                (println "message recieved: " c j)
                (.send c "hello from server"))))

    (.add (StaticFileHandler. "."))
    (.start)))

This approach takes us from perhaps 100’s of simultaneous connections for an online game into more like 10,000 theoretically – so much more into the big league, but also more importantly persistent connections like this allow for some interesting game mechanics.

Cyclic score sketching for livecoding

Live coding in cyclic time, while making the process of sketching, painting and general mark making as much part of the musical performance as the coding is. This is a prototype for “The Hair of the Horse”, a performance with Alex McLean and Hester Reeve as part of Live Notation at the Arnofini on Friday 27th July. It’s incomplete without Alex’s code over projected and I’m also expecting the performance will consist of a much larger and messier score!

GX: Player statistics-o-rama

Some stats on Germination X player activity since November:

Total num players: 310
Time spent playing total: 181.80 hours
Average player return duration: 9 days
Players who returned for periods longer than 30 days: 21 players
Average num sessions per player: 2.47 sessions
Average num fruit/seed picked per player: 12.53 fruit
Average num plants planted per player: 12.31 plants
Average session length per player: 16.09 minutes
Median session length: 3.82 minutes
Average plantings per session for all players: 8.73 plants

These sorts of player behaviour stats can be an important part of developing online games, as they provide a way to get feedback on changes you make to the game. In that vein – here are some statistics before and after a couple of big changes to attempt to see how they changed the experience, based on the average number of plants planted per session by all players:

Tutorial feature:
Average plants per session – before: 6.47 after: 12.23

Player avatar feature:
Average plants per session – before: 8.23 after: 11.20

I think it’s possible to take these kinds of stats too seriously (especially in small sample sizes as here) but in combination with focus study feedback you can start to build up a useful picture that can be used to influence decisions.