Last active
January 27, 2016 14:20
-
-
Save Joncom/e97f2f23e443015aecf2 to your computer and use it in GitHub Desktop.
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
// The purpose of this program is to "pre-render" pixel | |
// perfect circles, so that they can be drawn from an image | |
// instead of using something like an arc function. The | |
// output image is a tilesheet that can be used in 2D pixel | |
// art style games. | |
// Originally I ran into an issue with common algorthithms | |
// (such as the midpoint circle algorithm) only supporting | |
// an increase in diameter of 2 pixels at a time. I wanted | |
// to capture single pixel size increases (thus doubling | |
// the number of frames and improving animation smoothness). | |
// This program does support that goal. | |
// This program was made from a mixture of these sources: | |
// https://en.wikipedia.org/wiki/Midpoint_circle_algorithm | |
// https://github.com/donatj/Circle-Generator | |
"use strict"; | |
var maxDiameter = 64; | |
var firstFrameEmpty = true; | |
var frameCount = maxDiameter + (firstFrameEmpty ? 1 : 0); | |
var canvas = document.createElement('canvas'); | |
canvas.width = maxDiameter * frameCount; | |
canvas.height = maxDiameter; | |
var context = canvas.getContext('2d'); | |
var imageData = context.getImageData(0, 0, canvas.width, canvas.height); | |
var pixelData = imageData.data; | |
var makePixelIndexer = function(width){ | |
return function(i,j){ | |
var index = j*(width*4) + i*4; | |
//index points to the R chanel of pixel | |
//at column i and row j calculated from top left | |
return index; | |
}; | |
} | |
var pixelIndexer = makePixelIndexer(canvas.width); | |
var drawPixel = function(x,y){ | |
var idx = pixelIndexer(x,y); | |
pixelData[idx] = 255; //red | |
pixelData[idx+1] = 0; //green | |
pixelData[idx+2] = 255;//blue | |
pixelData[idx+3] = 255;//alpha | |
}; | |
var distance = function( x, y ) { | |
return Math.sqrt((Math.pow(y, 2)) + Math.pow(x, 2)); | |
}; | |
var filled = function( x, y, radius ) { | |
return distance(x, y) <= radius; | |
}; | |
for(var i=0; i<frameCount; i++) { | |
var diameter = i + (!firstFrameEmpty ? 1 : 0);; | |
var radius = parseFloat(diameter) / 2; | |
var maxblocks_x, maxblocks_y; | |
if( (radius * 2) % 2 == 0 ) { | |
maxblocks_x = Math.ceil(radius - 0.5) * 2 + 1; | |
maxblocks_y = Math.ceil(radius - 0.5) * 2 + 1; | |
} else { | |
maxblocks_x = Math.ceil(radius) * 2; | |
maxblocks_y = Math.ceil(radius) * 2; | |
} | |
for( var y = -maxblocks_y / 2 + 1; y <= maxblocks_y / 2 - 1; y++ ) { | |
for( var x = -maxblocks_x / 2 + 1; x <= maxblocks_x / 2 - 1; x++ ) { | |
var xfilled = filled(x, y, radius); | |
if(xfilled) { | |
var nudge = (radius * 2) % 2 == 0 ? 0.5 : 0; | |
drawPixel( | |
x + maxDiameter/2 - nudge + (i * maxDiameter), | |
y + maxDiameter/2 - nudge | |
); | |
} | |
} | |
} | |
} | |
context.putImageData(imageData,0,0); | |
console.log(canvas.toDataURL()); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment