07.Jun.2011 Multiplayer server with node.js

I have been interested in Node.js for a while, and wanting to try it out for a real project. Preferably using WebSockets on the client/browser side.

Recently I have begun to implement a multiplayer server for Orbium. The initial goal is to make it possible for 2 players to play cooperatively over the Internet. To accomplish this I had to start with the basics…

Multiplayer game servers
An excellent text to read about multiplayer FPS games and how they work is Unreal Networking Architecture by Tim Sweeney of Epic Games. The article is over 10 years old but still relevant, still describes the basics about how multiplayer FPS games work. I encourage you to read it if you are interested in this and are a beginner in this (like I am). It opened my eyes a bit about concepts that before I read it seemed magical to me.

The article talk a lot about relevant set in FPS games (the things each player can see). For a game as simple as Orbium, the relevant set is always all actors in the simulation, so that part is not so relevant for this discussion (but very interesting).

Also there are a lot about scripting that is also not applicable to a game as simple as this.

What is relevant in a Orbium multiplayer server is how to run the game simulation on the server, inform clients of the correct game state, all the while the game simulation is run on the clients aswell to get an acceptable experience for the players. Orbs cant jump around due to network lag for example, the animation must still be as smooth in the same way as in a singleplayer game.

So basically both the server and all clients run the same game simulation and server is always authorative about the game state. All random events (like deciding what the color of the next orb is) must happen on the server and be distributed to the clients. The clients must report player actions like launching an orb for example, and that action must cause the orb to be launched in the server simulation aswell as being distributed to all other clients.

A bit about WebSockets
WebSockets is starting to become viable as Chrome, Safari (Including Mobile Safari and UIWebView on iOS) supports it out of the box now. I felt that for my first project I wanted to learn how WebSockets really work instead of using Socket.IO library. Although I must say Socket.IO looks awesome, both shielding you from difficult WebSocket handshake details and providing fallbacks for browsers without WebSocket support. So please use it if you dont have the same goal as I have starting out (learning).

Using WebSockets client side (in the browser) is very easy, look at this code for a quick start: client.js

Node.js
Node makes it easy to write socket servers in JavaScript without the need to worry about a lot of C low level operating system stuff or threads. It is the ideal server side companion to websocket support in the browser. If you hava a basic understanding of how events and callback functions work in JS it is easy to get up and running.

The development experience is very nice with it, there are no “compilation steps” and “redeploys”. In a lot of ways it mirrors the ease of use you get in the browser, but on the server side. Instead of hitting F5 to see the changes, you do a ctrl-c and rerun “node server.js”. It is very fast.

Like on the client its probably best to use Socket.IO in node aswell, to be shielded from WebSocket protocol details. WebSockets are not raw sockets (for good reasons) so there are some things you have to do like, doing the initial handshake and pad the data you are sending with a pre and postfix.

Details for doing it from scratch can be seen in server.js. The WebSocket protocol is not 100% final so there might be changes in details about how this work so it might break in the future. Another argument for using Socket.IO and let them worry about it (If you are not a masochist like I am :-) ).

Using the same code on the client and server
To be able to run the game simulation on the server and the client, the only practical way to do it is to share code beween server and client. In the Unreal case above this is done with C/C++, that can be made to run both on a server and in the game client (with some care ofcourse). In this case, for Orbium we use JavaScript on both client and server so code sharing can be done in the same way.

When doing this you need to architect the code (or refactor it) so it can run on the server in node, that means no window object, no DOM tree, no canvas element. There is also the issue with the module system in node, that is not really compatible with how things are normally done in the browser.

I solved this by just doing a “require(./tile.js)” for example so all code is just put in the “orbium” object that is attached to the global object, esentially in the same way as it works in the browser. I doubt that this is a “best practice”, but it works and I dont really se any major downsides with it.

Deploying this to actual players/customers
At this stage I am not sure how to actually deploy this in the real world. It works to play over the internet now, for example one player on iPhone and another using Chrome on a laptop. To test it out, for the time being, you have to clone the repo from github and change the hardcoded ip address to match your server.

There is a lot of work remaining in how to match up players, user interface for that, etc etc. There is also the question about hosting. If you are reading this and have some experience with node.js hosting providers I would be glad to get any tips in that area.

17.Sep.2010 Retina display and web development

A couple of days ago I got a new toy, an iPod touch 4th gen, that has the new high resoultion 960×640 display. I have been having higher resolutions in mind since I started development of Orbium, the source art is high res and I scale it down for different devices.

So this should be straightforward right? Not quite. For the Retina display Apple has choosen, for backwards compability with the older iPhones 480×320 display, to make “1px” in CSS to be 2 real hardware pixels. That means that every site developed for the older models look exactly the same on the new iDevices with retina display. It is ofcourse good for backwards compability, but we want to use the new high res display to its full potential.

Fortunately, you can detect this from JavaScript in the window.devicePixelRatio variable. In the case of the new Retina display equipped iDevices this is set to 2. I am unaware of any other device that currently implement this, but thanks to the dynamic powers of JavaScript we can detect if this property exists, and use a default value of 1 if it doesnt. So we define the following utility function:

function getDevicePixelRatio() {
	if (window.devicePixelRatio == undefined) {
		return 1;
	}

	return window.devicePixelRatio;
}

By using this utility function, we can decide how to do our layouts, what image sizes to use, and what dimensions objects in the page should have. Now everything is high res on the iPhone4 etc and all is good. Only one problem left to solve: only 1/4 of our page is visible on the screen! Why? The device has twice the pixel density than the older iDevices, and hence four times as many pixels.

What to do? I can think of several solutions, but I only ended up trying one, since it worked soo good: manipulating the scale property of the viewport meta tag. Instead of declaring the viewport tag in HTML we leave its contents empty like so:

 <meta id="vp" name="viewport" content=""/>

Note that I have also given it an id “vp”. Then somewere in the initilalization code for the page we do this:

var vp = document.getElementById("vp");
var vp_width = "width=device-width, ";

var vp_user_scalable = "user-scalable=no, ";

var scale = "1.0";
if (getDevicePixelRatio() == 2) {
	scale = "0.5";
}

var vp_initial_scale = "initial-scale="+scale+", ";
var vp_minimum_scale = "minimum-scale="+scale+", ";
var vp_maximum_scale = "maximum-scale="+scale;

vp.attributes.content.value = vp_width+vp_user_scalable+
	vp_initial_scale+vp_minimum_scale+vp_maximum_scale;

So what happens here? we build up the viewport tag dynamically and set the scale property to 0.5 if we have a pixel density of 2. This “zooms out” the page so we see the whole page. Initially I was worried that this would kill performance, in about the same way that happens if you use the scle property on the canvas tag. But if it is set to exactly 0.5 it is not a problem, as it will give a pixel perfect result. I tried to set it to for example 0.51 to see what happens, and the result was jerky animation and a very hot device.

The result is awesome, performance is great, and the higher dpi graphics really makes a difference. The graphics on my older iPod looks blurry and smudgy now.

These changes will be present in the next version, 1.3, that I am currently developing.

13.Jul.2010 Fingers and mouse pointers

I see a lot of new stuff that is built on the web that shows off touch capabilities in Mobile Safari. And while that is great most of them is simply broken or send you away if you want to have a peek using your desktop browser (or other mobile browser).

Supporting touch doesnt mean exluding the good old mouse/keyboard users, you can have both! You can even support multitouch, for devices that have it, as long as your application doesnt rely on it.

See this excellent demo for a demonstration.

For developers there are basically three classes of devices:
Mouse/keyboard desktop PC.
Device with touch screen, lacking “Touch API”.
Device with touch screen and “Touch API”.

To make matters worse some desktop browsers, like Chrome, report it has touch API even when its running on a regular dektop PC that ofcourse doesnt have a touch screen. So what I do currently for Orbium to decide if we are running on a touch screen is a pretty big assumption and a hack.

I use the available screen size, if its less than or equal to 1024×768 (the iPad resolution) I assume mobile device with thouch screen. Of course this is not future proof in the least, and I will only get away with this for maybe a year more. So if you have some method of finding out if the user uses a touch screen I would love to hear about it.

Orbium has two control modes “click mode”, and “swipe mode”. Click mode is just click to launch orb, works with mouse control. Swipe mode is touch gestures to launch the orbs. This is needed bacouse of the smaller screen size realtive to your finger. swipe gestures effecively increases the resolution involved, and without it Orbium would not work on mobile devices.

Touch API is needed for swipe gestures? No! Its very possible to emulate this using mousedown, mousemove, mouseup, as long as any kind of multiutouch is not needed. This is how it works when Orbium runs on the Palm Pre or the Nokia N900 for example, that doesnt yet have the touch API.

So promise me for your next mobile project dont leave everything besides iPhone out, it could lead to a similar thing that we had with IE in the past, and the would ofcourse be bad.

15.Jun.2010 The resolution thing

Supporting multiple devices is a lot more than being resolution independent. But we need to start somewere, and in following blog posts I will go deeper inte capability detection and supporting different control methods.

There are basically 5 resolutions that you need to support today for a web game (lets assume landscape mode for handsets):
480×320, iPhone 3
800×480, Most Androids, Nokias and what have u’s.
960×640, iPhone 4
1024×768, iPad
> 1024×768, desktop PCs

The first try I did on this, I had graphics in a high resolution, and just used the scaling that you can do on the canvas tag. It looked alright, but it totally kills performance. On my desktop I had CPU usage that reminded me of *that evil plugin that everyone hates*. On my N900 I had something like 3 fps and and a very hot handset. I dont think its really viable to implement something that animates with the scale property today.

So I switched strategies, to something I found works great and ended up using. I use an ImageMagick script to automatically create several copies of the graphics in different resolutions, each graphic optimised just right for the current device. I use capability detection in JavaScript to determine what graphics set to use. Its one of the first things that gets done in the init() function, check it out in the source.

I read up some on the web how to optimally scale down graphics, using cubic method and sharpen, I will post about it.

I think the results turned out great.

Comments Off

08.Jun.2010 Taking it further

So I had my Nokia N900. The browser on it is just fantastic, I use it all the time. A problem though is you cant disable pan/scroll/zoom on a page, a crucial feature for most touch screen web apps.

So it was basically while trying to solve that I found PhoneGap, and a fork of it that works with Maemo, the OS of the N900. After I manage to package my then unfinished game with it and installed on my phone I saw for the first time that this game could work great on a smartphone. Around this time I decided to get an iPod Touch and get the game into the iTunes App Store.

So I got my first idevice, and set up the dev environment for it, an adventure in itself. The great thing about PhoneGap though is you only need to use the native SDKs for all the different handsets you want to support when you are packaging the app. Development and testing can be done in the devices web browser, and ofcourse in your desktop browser. Its a really great experience to develop for the web if you compare it to a lot of other stuff. For example reload page to try out changes, firebug, no compilation steps, etc.

In the following blog posts I will go more into detail about doing web development for touchscreen handheld devices, and at the same time support traditional mouse/keyboard desktops.

06.Jun.2010 How it started

Back in the 90′s I was a fan of the Amiga game Logical. A couple of years ago I tried it again in an emulator and noticed it was still fun.

Now largely forgotten, even many Amiga fans dont remember or even played this game, it had pretty uniqe, and very addictive gameplay. It was made by Rainbow Arts (now defunct), a german game development shop. Not a lot of info on this game is available on the web, but there is these entries at Lemon Amiga and HOL.

About the same time I was getting into JavaScript development, learning the language properly, reading Douglas Crockfords, JavaScript: The World’s Most Misunderstood Programming Language. I was certainly one of the guilty ones, having used it some in web development, but never understood there was a proper object oriented language in there.

So I started out with some experiments with animating divs. I “discovered” it was definetly feasible to implement fast moving sprite based games on a web page, while keeping CPU utillization in check. JavaScript garabage collection interrupting the timers were problems at this time though, even in A-grade browsers. I remember animations were not exactly smooth.

At this time I wasnt very interested in mobile phones, the iPhone had just been introduced, but wasnt on my radar yet. I was loosely aiming for a web game played on a computer in the browser. I had a very early test version, using some ripped gfx, then I kind of lost interest.

Some years later, the beginning of 2010, I had gotten into mobile phones with touch screens. I had my Nokia N900 in my pocket, and this project entered my mind again. Wouldnt Logical work really good on a small device with a touch screen?

Comments Off