I’m often on the lookout for interesting game jam premises, for those that have the most constraints or unusual rules. Usually, that’s where I get my best personal results, from trying to achieve something according to some esoteric rules or steps to follow. It’s what, a couple days ago, brought me to LOWREZJAM from a post on the Phaser forums.
(LOWREZJAM is a currently running game jam — entries due by 19 May 2014! — around the idea of making a game within the resolution of 32 by 32 pixels. No lighting effects or down-scaling, but in the actual, 32×32 space.)
And as is probably obvious from this post title, I’ve decided to take part. However, my results so far have been… troubling.
Starting with some basic drawings I made yesterday, I mocked up what I wanted a level to look like today and wrote down some ideas of mechanics I wanted to implement. Then, playing around with some space divisions and layouts in a paint program, I settled on a top and bottom area of five pixels each (for a total of 10), leaving me 22 pixels in the middle as space for a character to move around within and possibly avoid enemies.
Trying out some different characters heights, I decided seven pixels was the smallest I as able to go and still have some definition for the character. Looking at classic Mega Man sprites for inspiration, I came up with the following concept art.
It’s obviously scaled up by several factors to make the pixel boundaries stand out.
Once I had some simple moving animations based on the sprite done, I wrote some basic JavaScript using the Phaser game engine and got ready to start prototyping. That’s, of course, where all the problems started. And where I’ve been stuck for several hours now.
See, scaling using Phaser is pretty simple. It’s the following code.
this.game.scale.maxWidth = 600;
this.game.scale.maxHeight = 600;
this.game.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;
this.game.scale.setScreenSize();
You set your maximum width and height and tell Phaser to resize the screen. No need to set specific scale factors. Phaser will base the calculations on the original canvas size, figure out the scale factor between it and the new dimensions, and adjust all objects accordingly. Simple.
There’s one problem with this: While Phaser will do all the calculations, the browser has to do all the rendering. And most browsers disagree about how image rendering should be done and which CSS properties and options should be used when doing it.
For example, in order to get general (although far from cross-browser) support, it’s the following several lines of CSS.
* { | |
image-rendering:optimizeSpeed; /* Legal fallback */ | |
image-rendering:-moz-crisp-edges; /* Firefox */ | |
image-rendering:-o-crisp-edges; /* Opera */ | |
image-rendering:-webkit-optimize-contrast; /* Chrome (and eventually Safari) */ | |
image-rendering:crisp-edges; /* CSS3 Proposed */ | |
image-rendering: optimize-contrast; /* Possible future browsers. */ | |
-ms-interpolation-mode:bicubic; /* IE8+ */ | |
} |
Of course, that will only solve part of the problem. When it works (and that ‘working’ is vendor and even operating system dependent at the moment), it will draw the scaled objects correctly. However, to get the best results, Phaser must be told to turn off its pixel smoothing.
Phaser.Canvas.setSmoothingEnabled(this.game.context, false);
this.game.stage.smoothed = false;
Now, finally, everything will be scaled and drawn correctly. Well, until the sprite moves. And only really in Firefox on Windows at the moment.
In my testing, only Firefox and Opera came the closest to rendering things the “most correct.” Scaling the seven by seven pixel image by a factor of 18.75 made it artifact pretty bad in IE and Chrome, with them both ignoring the CSS rules to draw it as they should. Firefox and Opera would draw it quite good, but would produce motion blur whenever the sprite moved vertically at all. Horizontal movement, generally, was okay. However, anything that used physics equations introduced just the tiniest bit of latency.
In Firefox, that meant aliasing on the top and bottom of the sprite. In Opera, the full body aliased when it moved, blurring quite bad. In IE and Chrome, well, the whole thing was a blur; it was hard to tell anything at all.
So, after a few hours at it on my first real day of development, I’ve hit something of a snag. Without scaling up the images in a paint program, which would break the one rule of the game jam, I’m not sure what to do next. Tomorrow, I might need to switch programming languages and try to get away from these browser image rendering issues.
Great (and quite depressing) summary. I think it gets even worse if you try to support MBP and iOS devices with Retina displays. Regarding your last paragraph: Actually, if you look at the rules, the pixels just have to conform to a 32×32 grid. Whether you blow them up using an algorithm or using an image editor shouldn’t really matter, as long as you avoid any kind of anti-aliasing. Depending on your implementation, things can become a little tricky as soon as you animate and move stuff around of course, though.