Category Archives: borrowed-scenery

Aniziz (the soil)

The borrowed scenery game has been named ‘Aniziz’ – from the 12th century Lingua Ignota used by Hildegard of Bingen. The term means “the soil” and represents the game’s role in the wider project, for nurturing plants found in the city, as well as the mapping element.

It’s working much more like a proper multiplayer game now as it has player accounts, using four types of avatar from Theun which represent patabotanical tarot versions of the hermit, hierophant, magician and high priestess. Your avatar will be picked when you register, in the form of a ‘reading’ ritual – still to be designed.

The text rendering has been greatly improved – the support provided by HTML5 canvas is quite basic, so you need to do things like word wrapping yourself. Particle systems now provide more interactivity for the fungi and the game includes a chat mode for players using the same font as on the tagged city plants and the the android app. The thinking behind this is to create a situation where interpretation is encouraged over direct text communication, inspired (as in previous multiplayer online games I’ve worked on) by Tale of Tale’s Endless Forest.

The game will be made public closer to the event, but the code and assets for all these projects are now available on FoAM’s git repository.

Borrowed Scenery – spacesuits for plants and full screen scrolling in HTML5 canvas

Lots more of Theun’s new artwork which is coming on quickly over the last few days has been added to the game, the glass bubbles (more precisely cloches) are space suits for the plants from our world to live in, in their new patabotanical environment. Information about tagged plants is printed in a Voinych Manuscript inspired font.

I’ve been doing a bit more research into HTML5 canvas, turns out the the screen size doesn’t affect rendering framerate too much, and it now adapts to the browser size. Full screen scrolling is working – centring the view on the player. It wasn’t immediately obvious how this could be done without redrawing all the sprites each frame (which is way too slow), in this respect HTML5 development is really reminding me of 16bit era – hacking things like this to work quickly. It turns out it’s possible to use drawImage using the current canvas as it’s own input – so redrawing the whole thing with an offset:

function scroll(diff_x,diff_y) {
    // calculate the source and destination offsets - whether we offset
    // the source or destination rectangle depends on which direction 
    // we are travelling in 
    var sx=0;
    var dx=diff_x;
    var width=this.ctx.canvas.width-diff_x;
    if (diff_x<0) {
        sx=-diff_x;
        dx=0;
        width=this.ctx.canvas.width+diff_x;
    }
        
    var sy=0;
    var dy=diff_y;
    var height=this.ctx.canvas.height-diff_y;
    if (diff_y<0) {
        sy=-diff_y;
        dy=0;
        height=this.ctx.canvas.height+diff_y;
    }

    // remember to convert to ints, subpixel 
    // scrolling results in crazy artifacts
    this.ctx.drawImage(this.ctx.canvas,
                       ~~(sx),~~(sy),~~(width),~~(height),
                       ~~(dx),~~(dy),~~(width),~~(height));
}

Borrowed Scenery tendrils reach out

Some serious connecting work going on with borrowed scenery for joining physical and imaginary worlds together. A new Boskoi database is up and running, giving us a place to put all kinds of story elements and plants found in the city. Boskoi uses the Ushahidi platform, which provides an API the game is now using to pull all items tagged in the map (which can come from the Android app or web app) into the game where they can interact with players or other entities.

More of Theun’s artwork has gone in, including a magician tarot avatar on the left while the three plants in the screenshot above represent those tagged on the map below. Getting everything in the right place (map lat/long coordinates vs game location coordinates and then aligning the map) took a lot of time to get right!

Algorithmic fungi patterns

Central to the borrowed scenery game is an ecosystem of fungi that players will grow to feed the plants found by foragers in the city of Ghent using Boskoi. These fungi will work differently from the plants in Germination X, partly in response to some interesting game testing feedback – the fungi will only grow to the next stage when activated by a player, but the positions of new fungi will be algorithmically decided.

This calls on a kind of cellular automata, which requires a bit of prototyping to get the right values to make the kind of patterns I want. I mocked up something in clojure (so I can plug it into the game server easily) using ascii art for previewing the patterns resulting, the four stages of fungi are:

. : spore
o : young
O : adult
* : fruiting

Each fungi cell only goes from adult to fruiting if conditions are right (counting number of neighbours as in the game of life), after which 5 spores are created around it. After fruiting or adult stage the fungi dies and gets removed. This is a screenshot showing some different colonies which emerge starting with just two fungi spores:

                     .Ooo*.                o..O   
                     o*o ..                 *.O   
                      ..*.                 o*oo.  
                       ...                 .*OOoo 
                                            ..Oo  
                  O o                       ..*.  
                  O                            o  
              O       o                           
                oO                                
            .O                                    
           O*                                     
           oO..                                   
         o  o *.OO                                
             ..O                O O               
              ** o                O               
             .*..o              OooO              
             .o.*.             .oOO*O O           
               . .              ..O*O O.          
                                O*. O*o*.         
                                Oo OoO. .     

And here is the code:

(def *spore-count* 5)
(def *neighbour-distance* 15)
(def *max-neighbour* 60)
(def *min-neighbour* 0)

(defn make-cell-world [cells]
  {:cells cells})

(defn make-cell [x y]
  {:x x :y y
   :state "."})

(defn cell-dist [cell-a cell-b]
  (let [v {:x (- (:x cell-a) (:x cell-b))
           :y (- (:y cell-a) (:y cell-b))}]
    (Math/sqrt (+ (* (:x v) (:x v))
                  (* (:y v) (:y v))))))

(defn cell-process [cell neighbours]
  (if (< 50 (rand-int 100))
    (cond
     (= (:state cell) ".") (merge cell {:state "o"})
     (= (:state cell) "o") (merge cell {:state "O"})
     (= (:state cell) "O") (if (and (< (count neighbours) *max-neighbour*)
                                    (> (count neighbours) *min-neighbour*))
                             (merge cell {:state "*"})
                             (merge cell {:state "X"}))
     (= (:state cell) "*") (merge cell {:state "X"})
     :else cell)
    cell))

(defn cell-get-neighbours [world cell]
  (filter
   (fn [other]
     (< (cell-dist other cell) *neighbour-distance*))
   (:cells world)))

(defn cells-find [world x y]
  (filter
   (fn [cell] (and (= (:x cell) x)
                   (= (:y cell) y)))
   (:cells world)))

(defn cells-make-rnd-pos-list [cell]
  (repeatedly
   *spore-count*
   (fn [] {:x (+ (:x cell) (- (rand-int 3) 1))
           :y (+ (:y cell) (- (rand-int 3) 1))})))

(defn cells-spore [world]
  (merge world {:cells
                (concat
                 (reduce
                  (fn [r cell]
                    (if (= (:state cell) "*")
                      (reduce
                        (fn [r pos]
                          (if (empty? (cells-find world (:x pos) (:y pos)))
                            (cons (make-cell (:x pos) (:y pos)) r)
                            r))
                        r
                        (cells-make-rnd-pos-list cell))
                      r))
                  ()
                  (:cells world))
                 (:cells world))}))

(defn cells-death [world]
  (merge world {:cells
                (filter
                 (fn [cell]
                   (not (= (:state cell) "X")))
                 (:cells world))}))

(defn cells-run [world]
  (cells-death
   (cells-spore
    (merge world {:cells
                  (map
                   (fn [cell]
                     (cell-process cell (cell-get-neighbours world cell)))
                   (:cells world))}))))

(defn cell-world-print [world w h]
  (dotimes [sy h]
    (dotimes [sx w]
      (let [f (cells-find world sx sy)]
        (if (> (count f) 0)
          (print (:state (first f)))
          (print " "))))
    (print "\n")))

(defn cell-world-loop [world n]
  (println "-------------------------------------------------")
  (cell-world-print world 50 20)
  (when (> n 0)
    (recur (cells-run world) (- n 1))))


(defn -main []
  (cell-world-loop
   (make-cell-world (list
                     (make-cell 25 10)
                     (make-cell 27 10)))
   1000))

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.