Recently my friend Sergei Anenko told me about the interactive he should do as a homework for The British Higher School of Art and Design:

There is a big line of people on the street to Van Gogh's exhibition and a lot of them are frozen (-20°C/-4°F outside). Let's do a fun game to warm they up!

And we made it!

It was a racing game about Van Gogh and his Ear. Two players press special pads one by one as fast as they can and their heros moves step by step to the finish. The winner gets a cookie :)

Preview

Here is how controllers looks like:

Prototype

Each pair (red and blue) has two pads which are responsible to pressure.

So how to build it? We bought an arduino and few other components:

Components

The key component is E-FSR sensor set which measures the pressure. So we build this device to read sensors:

Device

(the beautiful colored wire connected with sensors)

Next, we had to get responses from sensors.

Here is our code for #arduino:

int s1 = A0;
int s2 = A1;
int s3 = A3;
int s4 = A5;
char str[30];

void setup() {
  Serial.begin(9600);
}

void loop() {
  *str='\0';
  sprintf(str, "%d,%d,%d,%d;", analogRead(s1), analogRead(s2), analogRead(s3), analogRead(s4));
  Serial.println(str);
}

analogRead() returns a value from sensor in range from 0 to 1023.

We just get 4 signals and sends it to serial port as string like 0,0,0,30;0,0,0,0;0,0,10,15;0,.

Next we had to read signal from our data server. I implemented it with #ruby:

require "serialport" # gem "serialport"
require "json"

serial = SerialPort.open("/dev/cu.usbmodem1411")

filter = Array.new(4, 0)
while data = serial.gets(";") # ";" is the end mark of message
  raw = data.chomp
  # 10 is a minimum value for detection the pressure
  values = raw.split(",").map { |value| value.to_i >= 10 }
  next if values.size != 4 # if we get only part of message. this may happen when we run server

  # then we have to filter incoming data from noises and mystics
  # and mark pad active only for each 2 sequential signals
  message = values.each_with_index.map do |active, i|
    if active
      filter[i] = [filter[i] + 1, 3].min
    else
      filter[i] = [filter[i] - 2, 0].max
    end
    filter[i] >= 2
  end.to_json

  # send data like "[true, false, false, true]"
end

Ok. We received valid data from the sensors! Using Ruby! Awesome! It's time to send it to the front-end and implement the game's logic.

# let's translate incomed data to websocket client
require "em-websocket" # gem "em-websocket"

EM.run do
  EM::WebSocket.run(host: "0.0.0.0", port: 1666) do |ws|
    EM.defer do
      while data = serial.gets(";")
        message = (...).to_json
        begin
          ws.send message
        rescue => e
          p e.message
        end
      end
    end
  end
end

Then read data using #javascript in browser:

var game = new Game()
var ws = new WebSocket('ws://0.0.0.0:1666')
ws.onmessage = function(e) {
  var data = JSON.parse(e.data)
  game.receiveData(data)
}

That's it. Now we have pads and its signal gets translated to the browser! Fantastic!

How it was in action on the street (must see):

In action

The implemented game (keyboard controlled) is available here: http://gogogh.herokuapp.com.

And all code is open source: https://github.com/releu/gogogh