Asynchronous game in real time

We made a game, a mobile racing game for Red Bull. Sort of in the trails of Chrome Racer, but even more fun we think. We used some cool stuff that we’ve written about here before – html5 audio, multiplayer gaming with websockets and node.js, but also stuff that was new to us, the vector scripting library paper.js, canvas animation and angular.js.

The first mindboggle was the question of where the race actually is taking place. The game is multiplayer and also a competition, so we needed to make sure the race synced well across multiple devices, but also that the game was correct in deciding who’s winning and what time you get. We started out with presuming that the game had to take place in real time on the server, and the server could push your car or hold it back when you got out of sync with the server, or crash it when you took a curve too fast, but in bad conditions with network latency the racing got twitchy. So the gaming experience hurt – no good.

racing-twitchy
Blue car is weirding out.

It was best to leave your car be. If your opponents get jittery on bad reception it’s ok, as long as your own car moves smoothly. So if the client is controlling the race, how do we know it’s not spoofing a killer race time? The conclusion was that the race must take place both in your browser and on the server, and the server rules when it comes to the actual result.

If the server doesn’t interfere with your driving it doesn’t have to work in real time either. There’s no clock running on the server so to speak. The server sets a start time, you tell the server when you’re throttling and when you’re not (or actually when you did throttle, due to latency we work with past tense data – the player throttled 0.2 seconds ago), and the server calculates the race, and where it thinks you should have crashed. Does nothing with this data, just quietly executes the race in an asynchronous manner. Since it just waits for events to come in it doesn’t really know or care where you are at this exact moment, not even at the finish line. Your race time is calculated when the server simulates your final run towards goal and sees that this gal was over the finish line at 16.34.

The server basically take your actions and recreates your race on the server piece by piece, while simultaneously sending out the same data to your opponents, and finally sets your race time with no consideration of the time you said you finished at. Latency matters at race start, if you’re on a bad connection you get a late start, but at the end and during the race it doesn’t matter at all. Your opponents will just look like drunk chinchillas on the race track.

Play the game on your phone: www.redbullracechallenge.se

More node.js game action

This small game idea felt like fun – there is a man walking at the bottom of your browser window. Adjust the size of the browser window to make the man walk into the green area, i.e. live on.

manmanbg

Try the game here: http://nodelab.earthpeople.se:1112

The man walks faster and faster and more green doors appear. To this you could add extra lives and power packs to catch along the ride. Also control the game in other ways by tampering with your browser, like jump if you scroll down rubber band style.

Anyway, someone said “what about multi-player?” So time for more node.js. When the man exits he simply walks over at the next persons screen, and walks from screen to screen. We made this a player vs. player game, but it could also be a collab. Keep the man alive for as long as possible, and keep track on how far he’s been walking and what part of the world he is in right now.

What we are doing is simply saving the player ids in an array, and walking through the array round robin style.

node.js server code example:


io.sockets.on('connection', function(socket) {
   clients[socket.id] = socket;
   ids.push(socket.id);
   socket.on('manLeaving',function(data){
      nextUser();
   });

   socket.on('join',function(data){
      io.sockets.emit('newUser', {});
      if (ids.length == 1){
         clients[ids[0]].emit('manComes', {});
      }
   });

   socket.on('failed', function(){
      remove(socket.id);
      nextUser();
   });

   socket.on('disconnect', function() {
      remove(socket.id);
   });

   function remove(user){
      delete clients[user];
      var i = ids.indexOf(user);
      if (i > -1) {
         ids.splice(i, 1);
      }
   }

   function nextUser(){
      if (userInTurn = ids.shift()){
         clients[userInTurn].emit('manComes', {});
         ids.push(userInTurn);
      }
   }
});

Quiz buttons in node.js

For our recent fall party we made a music quiz, and if you’re quizzin you gotta have some buttonpressin. We looked for quiz buttons at teknikmagasinet, surprisingly we didn’t find anything. So www what do you have to offer? Nothing? Well ok, let’s build some buttons in node.js. Real time web!

5 teams, connected to the same wifi, visit the laptop where node.js is running. They choose a team color (from #A0A to #EE0), and that team color is then removed from the other players screens to choose.

socket.on('claim_team',function(data){
   io.sockets.emit("remove_team",data);
});
If one team push their button no one else can push theirs until the quiz show host resets. On the laptop we see the scores and who pushed first.

Super simple code. The client tells the server that i pushed:

socketio.emit('ipushed', { team : myteam});

And on the server side, change a state and tell the scoreboard to dim the losers:

socket.on('ipushed',function(data){
   if (state == 'open'){
      state = 'locked';
      io.sockets.emit("they_pushed",data);
   }
});

buttons
Blue is winning!

The music questions were pretty nice ones too. Pop songs reworked in different ways – DJ Premierified, Brian Enofied, Bad youtube cover-ified, Dubified etc. This Enofied one was a hit.

Web audio music game

After we did the rhythm experiment at Music Hackday we fooled around a bit more with the web audio synthesizer. It’s pretty amazing that they got a built in synth in Chrome, and if you got some knowledge of synthesizers the different audio experiments out there (googles own minimoog for example) actually seems pretty straight forward, when you look at the api.

You basically just create an oscillator instance:
oscillator = context.createOscillator()
Give it some properties:
oscillator.frequency.value = 440
Create a filter:
filter = context.createBiquadFilter()
Choose filter type:
filter.type = 'LOWPASS'
etc.

It then works a lot like a modular synthesizer, where you connect all these boxes into each other to tamper with the audio signal before it hits the speaker. Like:
oscillator.connect(filter)
filter.connect(gain)

neworder

This is a simple game built with this chrome audio api. All sound is generated on the fly, and it only works in Chrome. You hear a melody, which then get split up into pieces – represented by boxes. You can click on a box to hear the part, and you should then move the boxes in the correct order of the original melody. It gets really hard pretty quickly, maybe some musical einstein could go up to 20 points or something.

Try it here: http://earthpeople.se/game_neworder