Retro Style Platform Runner Game for mobile with EaselJS (Part 4) – adjusting to mobile displays

The 4th part of my series on creating an EaselJS-Game is about adjusting the game to different display-sizes, which is very important when targeting mobile devices. To visualize, what the result is going to look like – I added the following two iframes, to demonstrate how the game adjusts to a different screen-/stage-size.



Open this http://demos.indiegamr.com/jumpy/part4/index_nearestNeighbor.html in a new browser-window and see how it adjusts to your window-size as you reload the page after resizing the window.

As allways: There are many ways to do this, all will pros and cons, I’m going to explain two (fairly simple) ways to do this.

Method I – Linear Scaling: Easy&straight forward


‘Method I’ basically consists of these two steps:

  1. Calculate the minimum-scale from the width&height based on a default-width & default hight
  2. Multiply every (scale-relevant) value of the game with that scale(e.g: dimensions of objects, velocities, ect..)

Calculating the scale is just one line: Okay in my case it’s 3, because I added variables for the default-dimensions:

So now that we have our scale-value: We are going to multiply every value, relevant to the scale, with it. As this involves quite a few parts of the code, instead of posting the whole updated source-code I’m going to list a few examples, and you can download the full source as always at the end of the page.

Adjustments


However – we are not quite done by just multiplying all the values. Since we now (can) have decimal values for the width and height of all objects, we need to watch out for flaws in the collision detection: to prevent decimenal numbers from screwing with our collision detection, I added a parameter <rounded> to the utility-method ‘getBounds()’:

In case you are wondering, why I’m not using “Math.round()”: Rounding with bitwise operators is 7-9x faster than using Math.round(): jsperf round() vs. bitwise benchmark

You don’t have to fully understand bitwise operations, but as a basic fact you should know, that with any bitwise operation all decimals will be erased. However, for optimizing code it is allways helpfull to know how bitwise works!

So all values from the returned bounds-rectangle will be integer values, to prevent the method from not detecting a collision, but then moving the object for example 0.5px too far, thus creating a collision-situation.
Rounding values like the position or the velocity of an object is in 90% of the cases a good thing to do, as it is basically impossible to spot a difference between rounded- and non-rounded pixel-values while it is (on most platforms) way faster for the canvas to render on pixel instead of subpixel values. So: use integer-values or for EaselJS-Objects: myObject.snapToPixel = true; – it is faster and in most cases you won’t see the difference.

That’s it with Method I of adjusting a canvas-app to the screen-size, you might think: ‘Looks good to me, why should I use anything else?!’ – here’s the reason: The following image shows two scaled versions of Method I and Method II – and since we are building a retro-/pixel-style game, guess which method we are going to use ;-)

Method II – Nearest Neighbor Scaling: keep hard pixel-edges


As there is (currently?) no reliable way to turn off anti aliasing, (actually there ARE ways to do this, but they won’t work across all browsers), we are going to use the following algorithm to scale each of our assets after they are done loading:

So when the game gets initialized, we scale any bitmap loaded:

And then again, like with ‘Method I’ we have to adjust every scale-relevant value, like velocities, positions EXCEPT for any scaleX or scaleY values, because our nearsetNeighborScale-method did that already. Also, just to be on the save side, we also do the collision-detection adjustments here (see bounds-rounding further up in the article).

Compare both methods side by side


(both scales are limited to 0.5)


Method I
seamless scaling possible +
image gets distorted on small scale -
image gets blurry on big scale -

Method II
+ no distortion, no blurryness
- needs 0.5x values(0.5,1,1.5,2…)
- only if retro-/pixel-effect is wanted



Download the sources: here.

Agenda