At right is a scaled dragon sprite that is still relatively clear, after it's initial anti-aliasing. Also note the sharp color bars I've inserted to highlight the blur. This image is rendered at (0,0), so each pixel on the destination canvas matches a pixel on the source canvas. If our source image was stored in img and the canvas context is ctx, the code might look like this:
x = 0; y = 0; ctx.drawImage(img, x, y);
However, in converting from game world coordinates to visual coordinates, rarely are exact integers produced. So, for example, if we offset x by 0.35, the image is anti-aliased for the final rendering, giving the blurred image at right.
x = 0.35; y = 0; ctx.drawImage(img, x, y);
Addressing this is simple, since we can simply round to the closest integer coordinate and we once again see our pristine dragon.
x = 0.35; y = 0; ctx.drawImage(img, Math.round(x), Math.round(y));
This doesn't hold true when we decide to mirror the image, however. Now we have two items to consider: the original coordinates and where we're flipping the image. Generally, we want to flip the image at it's midpoint, so we could store that in halfImageWidth. Using translate and scale to set things up, we might have:
x = 0.35; y = 0; flipAxis = x + halfImageWidth; ctx.translate(flipAxis, 0); ctx.scale(-1, 1); ctx.translate(-flipAxis, 0); ctx.drawImage(img, Math.round(x), Math.round(y));
Notably, we have once again offset our image to sub-pixels as seen at right. We could round the flipAxis to the closest integer, but images can be flipped between two pixels or in the exact center of a pixel to render a pixel perfect mirror image, so we do this instead:
x = 0.35; y = 0; flipAxis = Math.round((x + halfImageWidth) * 2) / 2; ctx.translate(flipAxis, 0); ctx.scale(-1, 1); ctx.translate(-flipAxis, 0); ctx.drawImage(img, Math.round(x), Math.round(y));
Multiplying the original flip axis (x + halfImageWidth) by two, rounding that number to the closest integer and then dividing by two gives us a flip axis that's between two pixels or directly centered on a pixel. Once again, we have a sharp, pixel-perfect rendering from the source image to the visible canvas.
http://www.electr-news.blogspot.com
ReplyDeletehttp://al-mo9mem-b.blogspot.com/