Last active
December 29, 2020 14:32
-
-
Save blixt/371fb0668178c06fbb9a to your computer and use it in GitHub Desktop.
Procedural avatars using procedural.
This file contains hidden or 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 avatar = procedural('avatar') | |
.takes('username') | |
// Size, in blocks. | |
.takes('size', function validate(avatar, blocks) { | |
return typeof blocks == 'number' && blocks > 0; | |
}) | |
// The pixel size of a single (square) block. | |
.takes('blockSize', function validate(avatar, px) { | |
return typeof px == 'number' && px > 0; | |
}) | |
// Calculate the colors that make up the avatar. | |
.provides('hueAngle', function (avatar) { | |
// Use a named number generator to get our own set of random values. | |
return avatar.getRandGen('color').nextInt(360); | |
}) | |
.provides('background', function (avatar) { | |
return 'hsl(' + avatar.hueAngle + ', 100%, 50%)'; | |
}) | |
.provides('foreground', function (avatar) { | |
var hueAngle = (avatar.hueAngle + 180) % 360; | |
return 'hsl(' + hueAngle + ', 100%, 50%)'; | |
}) | |
// 75% of avatars have a mirrored effect, others don't. | |
.provides('isMirrored', function (avatar) { | |
return avatar.getRandGen('mirror').nextFloat() > .25; | |
}) | |
// A particular avatar has a unique set of blocks. | |
.generates('block') | |
// The validator will run independently for both parameters. | |
.takes('x', 'y', function validate(block, xy) { | |
// We can refer to the parent instance (the avatar). | |
return typeof xy == 'number' && xy >= 0 && xy < block.avatar.size; | |
}) | |
// The color of this block. | |
.provides('color', function (block) { | |
// No need for a named RNG because we only use it here within "block". | |
if (block.getRandGen().nextFloat() > .5) { | |
return block.avatar.foreground; | |
} else { | |
return block.avatar.background; | |
} | |
}) | |
// Go back to defining the parent (avatar). | |
.done() | |
// Renders to a canvas and returns a URL for <img>. | |
.provides('url', function (avatar) { | |
var canvas = document.createElement('canvas'), | |
context = canvas.getContext('2d'); | |
canvas.width = avatar.size * avatar.blockSize; | |
canvas.height = avatar.size * avatar.blockSize; | |
context.fillStyle = avatar.background; | |
context.fillRect(0, 0, avatar.size, avatar.size); | |
var finalX = avatar.isMirrored ? Math.floor(avatar.size / 2) : avatar.size, | |
blockSize = avatar.blockSize; | |
for (var y = 0; y < avatar.size; y++) { | |
for (var x = 0; x < finalX; x++) { | |
var realX = x * blockSize, realY = y * blockSize; | |
var block = avatar.block(x, y); | |
context.fillStyle = block.color; | |
context.fillRect(realX, realY, blockSize, blockSize); | |
if (avatar.isMirrored) { | |
var mirroredX = avatar.size * blockSize - realX - blockSize; | |
context.fillRect(mirroredX, realY, blockSize, blockSize); | |
} | |
} | |
} | |
return canvas.toDataURL(); | |
}); | |
var img = document.createElement('img'); | |
img.src = avatar('bob', 16, 4).url; | |
document.body.appendChild(img); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment