PHOBOSLAB

Blog Home

X-Type – Making Of

For this year's Google IO, Google asked me to do a Chrome experiment for Mobile for them. They initially wanted me to vamp up Biolab Disaster – it's still a good game, but because of it's retro style it wouldn't be that impressive. Modern mobile browsers can do a lot more.

I suggested I would try to take another game of mine – X-Type – and make it work on mobile browsers. The game was made with my JavaScript Game Engine, so it mostly "just worked" on mobile browsers already. Yet, I still had a lot of work to do.

Have a look at X-Type over at chromeexperiments.com.

X-TYPE running on various mobile devices

Screen Size

One of the most difficult things for HTML5 games is dealing with the vast amount of different screen sizes and aspect ratios out there. I experimented a lot with different solutions and ended with a fairly simple one: the internal width the game's viewport is always 480px. These 480px get scaled to whatever is available on the device. The height of the viewport is variable, so that it fills the screen with the same scaling factor as the width.

// The internal width for our canvas is fixed at 480px.
// The internal height is set so that it fills the screen when scaled
canvas.width = 480;
canvas.height = window.innerHeight * (canvas.width / window.innerWidth);

// Scale the canvas via CSS to fill the screen 
canvas.style.width = window.innerWidth + 'px';
canvas.style.height = window.innerHeight + 'px';

In older browsers (Mobile and Desktop), scaling the <canvas> element was a horrible idea – it decreased performance to a tenth of what it would be unscaled. I'm happy to report that this is no longer true; Mobile Safari on iOS5 and the Chrome Beta on Android work just fine with scaled canvas. It still makes the game unplayable in Android's "Browser", though.

I also took care to only display the game in portrait mode and show a "Please Rotate the Device" message otherwise. Mobile Safari and Chrome both support the orientationchange event, which makes this easy. However, we can not rely on window.orientation, which reports the rotation in degrees (0, 90, 180 or 270), because some devices report 0° for portrait mode, while others report 0° for landscape. How convenient!

The solution is to just check if the window height is bigger than the width – if so, we're obviously in portrait mode! But as this would be too easy, Chrome's Browser offers another challenge for us: it only updates the window dimensions after it has fired the orientationchange event. So we listen for orientationchange and resize events. Sigh.

var wasPortrait = -1;
var checkOrientation = function() {
    var isPortrait = (window.innerHeight > window.innerWidth);
    if( isPortrait === wasPortrait ) { return; // Nothing to do here }
    wasPortrait = isPortrait;
    
    // Do your stuff...
};
window.addEventListener( 'orientationchange', checkOrientation, false );
window.addEventListener( 'resize', checkOrientation, false );

Performance

Since iOS 5 the <canvas> element is hardware accelerated and it really shows. You can draw hundreds of sprites on the screen without any slowdowns at all. The same is true for Chrome on Android – to a certain degree.

All drawing is scheduled via requestAnimationFrame and thus bound to the display's refresh rate. This works nicely on iOS, but Chrome refuses to draw at the 60hz even for the simplest scenes. You can use setInterval to process more frames, but only a portion of them is really presented on the screen.

So while Chrome's JavaScript engine is fast enough to process and render 60 FPS, it fails to display all of the rendered frames. I have no doubt that this bug(?) will get fixed.

While the game works in a multitude of other browser's on Android, such as Firefox, Dolphin or Opera, none of them provided good performance. I suspect the <canvas> element is not hardware acclerated in any of these, but didn't investigate further.

Controls

In the desktop version of the game you move the player with the arrow keys and aim and shoot with the mouse. Of course this doesn't work on touch screens, so I opted for dual virtual analog sticks. This worked out surprisingly well – with a bit of practice, you can control your spaceship quite precisely.

I also tried to make the analog sticks appear where you touch the screen first, so that you can always change the position. This made everything quite a bit confusing; it's easier to grasp the concept when the position of the analog sticks is fixed. Providing the dynamic positioning is probably more of "pro gamer" feature that should be optional, if at all.

Sound

This is the sad part. I complained about support for the <audio> element in mobile browsers last year already – and guess what: it's still the same shit. Apple hasn't done anything at all to improve the situation; same goes for Android's Browser. The Chrome Beta on Android seems to have some support for Audio, but it's not really usable for real time games at the moment. I'll investigate this further.

As always, I have high hopes though. Never give up, never surrender!

All in all, I'm very pleased with the results. Rendering performance in modern mobile browsers is really awesome and the quirks I encountered were workaroundable.

I learned a lot with this project and will use this new gained knowledge to make mobile browser support much more easy in the next version of Impact.

Wednesday, June 27th 2012

17 Comments:

#1Andrey Okonechnikov – Wednesday, June 27th 2012, 21:22

Actually, with the Beta 2 of the upcoming iOS6 you can already use Web Audio API in Mobile Safari. Also <audio> tag get some sort of improvement. You still can't rely on syncronyzed sound, but it's already playing more than 1 sound.

#2 – Tem – Thursday, June 28th 2012, 04:17

Heavily inspired by Warning Forever and it's inspirations. Looks good, otherwise.

#3Phillip Senn – Thursday, June 28th 2012, 04:58

HTML5 has got the moves like Jagger.

#4m – Thursday, June 28th 2012, 10:07

How to replace audio elements in browser? Does Javascript solve this problem? ex. buzz.jaysalvat.com/ (Buzz is a small but powerful Javascript library that allows you to easily take advantage of the new HTML5 audio element. It degrades gracefully on non-modern browsers.)

#5Nathan – Thursday, June 28th 2012, 16:16

Thanks for the writeup. I'm impressed with your continued advocacy for Javascript, and I think the Javascript + mobile situation is slowly getting better.

#6Rob Colburn – Thursday, June 28th 2012, 16:43

Nice, inspiring too. Up till now, I'd still not seen a graphic-intensive, truly cross-platform html5 game.

It'll be interesting to see some test again now that A4.1 and iOS6 have been anounced.

#7Felipe Budinich – Saturday, June 30th 2012, 07:00

Congratulations, that looks awesome. The lack of support for the audio tag is maddening tho. I can't understand what's wrong with browser developers...

#8javisantana – Saturday, June 30th 2012, 21:22

Good article, thanks for sharing.

I'm wondering if you have used this two sticks kind of control because of the multitouch in iOS (www.phoboslab.org/crap/mt.html).

#9Ryan Poolos – Sunday, July 1st 2012, 20:30

Great game, excellent work, and really love the short concise write up breaking down each challenge and solution.

#10Valken Lee – Tuesday, July 3rd 2012, 08:16

I scored 500,000 at only stage 1.
There is a scoring trick.

Each triangle figured bullet have 20 points.
Make the target's all arm removed. and remaining body only.
The body will shot multiple triangle figured bullets to downward.
Move to ship up-left (or up-right) corner and shoot downward.
Also, mouse click and drag outside of windows will make auto-fire.

www.valken.net/510

I upload screenshot to my blog.

- Valken Lee -

#11Dominic – Tuesday, July 3rd 2012, 11:51

@Valken Lee: Thanks for mentioning! I changed it so that the bullets don't give any kill score.

#12remvst – Wednesday, July 25th 2012, 17:15

For the mobile version of Fruit Killer, I used a completely different approach to scale the canvas: I used a fixed size (480x300), and then scaled it to match the viewport dimensions, so everyone shares the same aspect ratio.
Of course I have low definition for bigger screens and sometimes the canvas does not fit the screen, but the game works about the same way everywhere.

Anyway good post ;)

#13 – Dan – Wednesday, August 1st 2012, 04:40

Hello, I have played with X-type and really enjoyed it, specially the music. I saw it was created by Andreas Loesch, but i couldn't find any download possiblitys (googled it).
So where and how i can download / buy the music?
Sorry for bad english.
Thanks!

#14 – ABC – Friday, September 7th 2012, 11:10

This is really the best Canvas game running smoothly on an iPhone I have seen. State of the art.
This is great because I can show it to my products manager and tell them "See, that run on your iPhone !"
Thanks for the hard work.

#15Aaryadev – Tuesday, November 27th 2012, 20:02

Awesome inspired by you and started leaning :)

#16 – Moses – Friday, January 4th 2013, 18:41

I have test on IOS5 to draw animation sprite in canvas.
I can got 60fps when using non retina image with 50 animation sprite.
But when i update the image to retina version, the fps will turn down to 17fps.
I also do a testing in IOS 6 they can go up to 60fps.
So That mean retina in IOS5 is not good enough?

#17 – Chidera – Wednesday, February 5th 2014, 21:22

Can I download the game

Post a Comment:

Comment: (Required)

(use <code> tags for preformatted text; URLs are recognized automatically)

Name: (Required)

URL:

Please type phoboslab into the following input field or enable Javascript. This is an anti-spam measure. Sorry for the inconvenience.