WandaWoo will show you the layers and the code of the Tiny Avatar Engine

in creature •  3 months ago  (edited)

Thank you @juliamulcahy for giving a name to one of my creatures. :)

Here's the post where I introduced you the tiny avatar engine: https://steempeak.com/creature/@insaneworks/what-am-i-supposed-to-do-with-this

Now let's brake this tiny avatar engine down. Explode it to tiny bits. Investigate how it was done. Dissect the bodies.

Woo-hoo says WandaWoo!

WandaWoo.png

The code was partially outsourced. It happened like this: thoughts in my head, me waving hands, spit splattering all over because of all the explaining, me moaning and bitching how wonderfully stupid but still awesome idea I have, me preparing my creatures in Photoshop for the avatar engine, a ready made code magically appearing in front of me, me requesting again tiny and not so tiny changes and complaining about the fact that my hands just copypasting other persons code does not work immediately as I want it to work, me banging my head to the keyboard, pouring coffee in to my eyes because I think that would make me understand all the features in php a little bit better. And voilà, the code is there and I didn't have to swear and act like a negative aged child that much. Only a little. Coding is such fun. Trying to copypaste and change things in a code that you barely understand, is way more fun. Funner.

If you do not care about the creature body parts, just skip the images and scroll down to the code. It's there, at the end of this post.

file1.jpgfile2.jpgfile3.jpg
file and a folderset-creaturecreature-02

Okay so I have creatures. Each creature has different layers in photoshop. All of the creatures have a body, eyes and pupils. Most of them have mouths. Some have bellies, some have eyebrows or eyelashes and all of them have accessories. Accessories can be anything. Markings in the body, speech bubble, a wand, a hat. Different creature layers don't mix with each others. All images are maximum 500px.

creature02body02.pngcreature02body05.pngcreature02body07.pngcreature02body08.pngcreature-02-belly-02.png
bodybodybodybodybelly
creature02mouth01.pngcreature02eyes02.pngcreature02pupils02.pngcreature02accessories02.pngcreature02accessories04.png
moutheyespupilswandspeech bubble

WandaWoo here has two different tongue colors. Red and blue. I could have made that a separate layer and place it underneath the layer called body, but in this case, I chose to do it this way. The tongue color is fixed with the body color. WandaWoo also could have had the right arm turned up in some cases, but this is what it is. Arms are fixed.

The folders number tells you how the layers are arranged. The smallest number is on the bottom and the biggest is on top. Only one png image in each folder is randomly selected by the code. That means only one belly option or only one accessory can exist at the same time in one creature.

Here's another example of a creature where the mouth is in the first folder and the body comes second.

creature-05-mouth-01.pngcreature-05-body-03.pngcreature-05-eyes-01.png
creature-05-pupils-02.pngcreature-05-eyebrows-01.pngcreature-05-accessory-02.png

Mouth, body, eyes, pupils, eyebrows and accessory. So there also can be an empty png image if I want some creatures to be simpler.

lataus.png

All there is left now is the code. The php in the index file. So here we go!

The three back-ticks before and after the code did not work, @steempeak didn't want to publish this because:

codeeeeeaaargh.jpg

So after 4 hours of "problem solving" all by myself, trying out different markdown combinations, hitting my head to the wall and keyboard and table and swearing and cursing, I had to cry out for @penderis. And in two minutes all was fixed! Thaaaaaaaank youuuuuuuu for encoding the code! Some day your kindness will return to you when you least expect it. :)

Creature and it's body parts: CC BY 4.0.
Code is of course open source, use it as you like.


<?php
/***
		**
		**	Olio - Tiny Avatar Engine
		**
		*/

//-- Parse arguments
$args = getArguments();
//-- Make file list
$files = getFileList();

//-- If 'name' and 'size' was defined as and argument in URL,
//-- enter to image rendering mode and quit (without generating
//-- any HTML code since it'll ruins the binary image data)
if ($args['name'] && $args['size'])
{
//-- Select avatar set and its overlay parts
$decision = makeDecision($args, $files);
//-- Render avatar part graphics and return image to user
renderAvatar($decision);
//-- Exit code execution
exit();
}

//-- !!! Just a regular page request !!!
//-- !!! Add your html stuff after this!!!
?><!DOCTYPE html>
<html lang="en">
<head>
<title>Olio Avatar Engine | Insaneworks</title>
</head>
<body>
<h2>Olio - Creature - Insaneworks <a href="https://creativecommons.org/licenses/by/4.0/" target="_blank">CC BY 4.0</a></h2><br>
<?php renderGallery(35, 200); ?>
<h3>Olio - Creature - Insaneworks <a href="https://creativecommons.org/licenses/by/4.0/deed.fi" target="_blank">CC BY 4.0</a></h3><br>
</body>
</html>
<?php

/*
Collect request URL arguments and environment.

<name> - any string that is used as seed of pseudo random generator
<size> - size of generated avatar image bitmap (two value '<size>x<size>'
define width and height) if not define, 32 by 32 pixel image is generated
<set> - OPTIONAL: number of predefined set used

eg: "?name=foobar&size=100" will generate 100x100 pixel size bitmap image from 'random'
set with 'random' features

*/

function getArguments()
{
$name = isset($_GET['name']) ? $_GET['name'] : '';
$size = isset($_GET['size']) ? explode('x', $_GET['size']) : array(32);
$set = isset($_GET['set']) ? $_GET['set'] : '0';

return [ 'name' => $name,
'size' => $size,
'set' => $set,
'hash' => $name
];
}

/*
Build file tree of filenames beginning from specified path
and return it to caller.

<root> <= all graphics base
+<folder_0> <= 1st avatar set
| +-<subfolder_0> <= 1st avatar bottom images
| | +-<item_0> <= image
| | +-<item_1> <= ..alternative image
| | +-<item_2> <= ....another alternative image
| | +-<item_M> <= ......yet another alternative image
| +-<subfolder_1> <= 1st avatar 1st overlay image
| | +-<item_M> <= ...images...
: :
: +-<subfolder_N> <= 1st avatar top most overlay image
+<folder_1> <= 2nd avatar set
| +-<subfolder_0> <= 2nd avatar bottom images
: :
+<folder_N> <= Nth avatar set
+-...
*/

function getFileList($path = "/set-creature")
{
//-- Build path and start scanning one single directory
$realpath = realpath(dirname(FILE) . $path);

$scandir = scandir($realpath);

$return = array();

//-- iterated all files and directories from current folder
foreach ($scandir as &$name)
{
//-- Ignore 'current' and 'parent' directories
if ($name == '..' || $name == '.')
continue;

//-- Make full filename
$file = $realpath . "/" . $name;

//-- If directory, make recursion call - otherwise insert filename to list
if (is_dir($file))
{
$return[] = [ 'name' => $name,
'child' => getFileList($path . "/" . $name)
];
}
else
$return[] = [ 'file' => $file ];
}

return $return;
}

/*
Use pseudo-random generator and name-seed for selecting
avatar set and its part items and build rendering list
with desired resolution.
*/

function makeDecision($args, $files)
{
$return = array();
$hash = $args['hash'];

//-- Select set if defined - otherwise use pseudo-random selection
if ($args['set'])
{
$olioset = $files[$args['set'] % count($files)];
}
else
{
//-- set index from 0...<number_of_folders - 1>
//-- (modulo from pseudo-random)
$count = count($files);
$index = abs(crc32($hash)) % $count;
$olioset = $files[$index];
}

//-- use selected set name as an extra salt form next pseudo-random value
$hash = $hash . $olioset['name'];
$items = array();

//-- Select one single set of parts and scan through each sub-folders
for ($part=0; $part<count($olioset['child']); $part++)
{
//-- part index from 0...<number_of_items_in_one_sub-folder - 1>
//-- (modulo from pseudo-random)
$count = count($olioset['child'][$part]['child']);
$index = abs(crc32($hash)) % $count;

//-- insert randomized info name and filename into sub-list
$items[] = [ 'name' => $olioset['child'][$part]['name'],
'file' => $olioset['child'][$part]['child'][$index]['file'],
];

//-- use selected part name as an extra salt
$hash = $hash . $olioset['child'][$part]['name'];
}

//-- get width and height values (if on one value define, use it for both)
$width = count($args['size']) > 0 ? $args['size'][0] : 32;
$height = count($args['size']) > 1 ? $args['size'][1] : $width;

//-- finally add original name and resolution into decision list
return [ 'name' => $olioset['name'],
'width' => $width,
'height'=> $height,
'child' => $items,
];
}

/*
Render previously generated list of file top of each other from part
which is in folder of alphabetical folder first in a list.

*/

function renderAvatar($decision)
{
//-- generate transparent bitmap image for the base
$image = imagecreatetruecolor($decision['width'], $decision['height']);

imagealphablending($image, true);
imagesavealpha($image, true);

$bgcolor = imagecolorallocatealpha($image,255,255,255,127);
imagefill($image, 0, 0, $bgcolor);

$overlay = array();

//-- scan part list items through
for ($part=0; $part<count($decision['child']); $part++)
{
//-- load new image from file
$overlay = imagecreatefrompng($decision['child'][$part]['file']);

//-- scale loaded image to base size and make overlay copy
imagecopyresized($image, $overlay, 0, 0, 0, 0,
$decision['width'], $decision['height'],
imagesx($overlay), imagesy($overlay));

//-- get ridden of loaded image
imagedestroy($overlay);
}

//-- all parts glued together -> return mimetype as png-image to user
header('Content-Type: image/png');

//-- ...and send png-image data...
imagepng($image);

//-- ...and get ridden of glued image!
imagedestroy($image);
}

/*
Build a html code with specified number and size of avatar images with links.
All avatars are generated from randomly generated name every time when reloaded.
Each link open 500 by 500 pixel size image into new tab when selected.

<count> - number of desired avatars
*/

function renderGallery($count = 10, $size = 100)
{
$gallery = array();

//-- make a list of random names
for ($index=0; $index<$count; $index++)
$gallery[] = [ 'name' => substr(md5(rand() . time() . $index), 0, 10),
//'size' => 100 + (rand() % 1),
'size' => $size,
];

//-- iterate name list through and print out html code
for ($index=0; $index<count($gallery); $index++)
echo
'<a href="' . $_SERVER['REQUEST_URI'] .
'/?name=' . $gallery[$index]['name'] .
'&size=500" target="_blank">' .
'<img src="' . $_SERVER['REQUEST_URI'] .
'/?name=' . $gallery[$index]['name'] .
'&size=' . $gallery[$index]['size'] . '"></a>';
}

?>

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!
Sort Order:  

pixresteemer_incognito_angel_mini.png
Congratz, your post has been resteemed and, who knows, will maybe appear in the next edition of the #dailyspotlights (Click on my face if you want to know more about me...)
Check the rules of the Daily Spotlights if you want to nominate someone!
Pixresteemer is also listed as promoter on The Steemians Directory

cuddle_hug2.png

  ·  3 months ago (edited)

This post contained some typos in its mentions that have been corrected in less than a day. Thank you for your quick edit !

If you found this comment useful, consider upvoting it to help keep this bot running. You can see a list of all available commands by replying with !help.
·

Thank you @checky. What a rookie mistake. An a instead of an e. Hmph. :) Will fix it.

well, that is some very clean and nicely written codes.....

·

In this case, tidiness above all else. :)

I'm surprised that you didn't get side tracked here:

args=getArguments();

And actually had an argument :D

·

There's always next time.

What an interesting project you have going on! Really cool looking creatures! 😉

·

Thanks! Someday there will be more. :)

So fancy :) WandaWoo makes me think of Sister Act, good name. Lots of work that went into this your code monkey must have been working double time.
"What you doing?"

"Making creatures now bug off."

·

I asked. The whole thing, coding took about 4 to 5 hours from idea to finished version. The initial code, corrections and the repairs after my "awesome" coding and copypasting, and the comments because I demanded those.

And the creatures with photoshop... I have no clue how long I have been doing those. Perhaps 50 hours altogether. Maybe even 500 hours. From scratch to this point. A long time.

"Making creatures now bug off."

Exactly! :D

Hi @insaneworks!

Your post was upvoted by @steem-ua, new Steem dApp, using UserAuthority for algorithmic post curation!
Your UA account score is currently 3.366 which ranks you at #7627 across all Steem accounts.
Your rank has dropped 8 places in the last three days (old rank 7619).

In our last Algorithmic Curation Round, consisting of 191 contributions, your post is ranked at #78.

Evaluation of your UA score:
  • You're on the right track, try to gather more followers.
  • The readers appreciate your great work!
  • You have already shown user engagement, try to improve it further.

Feel free to join our @steem-ua Discord server