The resolution variable
8-bit, pixel graphics, whatever you choose to call it, this style has a special place in my heart. I tend to default to this style of graphics when given the choice. What is interesting about pixel art is that you always start small and scale up, as opposed to creating HD assets and then scaling down when necessary. If you have ever worked with pixel art, you have probably noticed that you can only ever enlarge your illustrations by a factor of one (100%, 200%, ect) otherwise you get dropped pixels and things start to look broken (as demonstrated below).
I kept this in mind when programming and did all the coordinate math using the dimensions from the original, low resolution sprite sheet. For every coordinate check, I multiplied the dimensions by a "resolution" variable, where resolution was the number that the sprite sheet was multiplied by when enlarged.
The huge advantage to this is that it's no problem to scale the graphics up for different resolutions. In fact, I actually do a screen resolution check at the initialization of the game that loads in the appropriate sprite sheet and sets the resolution variable. This way I don't have to worry about creating an HD version, as the game responds to screen resolution appropriately!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
if((navigator.userAgent.match(/iPad/i)) || window.innerWidth >= 640){ | |
resolution = 4; | |
diglettSprite.src = "img/spritesx4.png"; | |
document.getElementsByTagName('html')[0].className += " hd"; | |
hd = true; | |
}else{ | |
resolution = 3; | |
diglettSprite.src = "img/spritesx3.png"; | |
} |
Rounding coordinates
Another important aspect of the resolution variable is rounding coordinates. Even though everything is being rendered as pixel art, each pixel is still actually a 3x3 (or 4x4 on higher resolution screens) square. Without taking this into consideration, the pixel graphics would be layered on top of each other at fractions of the upscaled pixels, which looks and feels wrong
To combat this, I simply made sure to round the coordinates down to the previous "whole pixel" based on the resolution. Here's an example of setting the X value for each Diglett:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Diglett.prototype.setX = function(){ | |
this.x = randomXToY(0, parseInt(canvas.getAttribute('width')) - this.width); | |
if(this.x % resolution > 0){ | |
this.x -= this.x % resolution; | |
} | |
} |
And then everything layers naturally:
Touch events
It is actually very easy to handle touch events and have them fall back to mouse events where touch is not available! Especially for this game, where the interaction was simply "on touch" or "on click." To do this, you bind your event listeners to a variable event, which is set at initialization based on whether or not touch is available. Like so!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var _has_touch = ('ontouchstart' in window); | |
//determine which event we're listening for based on touch availability | |
var touchEvent = (_has_touch) ? "touchstart" : "mousedown"; | |
//bind our event listener to our event variable | |
document.getElementById('gameWrapper').addEventListener(touchEvent,function(e){ | |
var touchPosX = (e.type == "mousedown") ? e.layerX : e.touches[0].pageX; | |
var touchPosY = (e.type == "mousedown") ? e.layerY : e.touches[0].pageY; | |
//We have extracted the coordinates from the input event! Deal with them here. | |
} |
Coming soon in part 2:
- The game object
- Webapps
- CSS3 vs Canvas (i used both!)