Modulus for Color Variation (Image Layering)

Hare

Senior Member
Have you ever used a modulus to create color variations in a breeding feature?
I came up with this method a while back and have been using it for a few years with Imagick and GD library.

Let's say we have a pet with different possible spots, stripes, nose markings, and foot markings.
With a modulus, you can have all four marking types controlled by one INT column (instead of having four different columns).

There are 5 nose patterns. The files are named: nose0.png, nose1.png, nose2.png, nose3.png, and nose4.png
There's 6 foot patterns: foot0.png, foot1.png, foot2.png, foot3.png, foot4.png, and foot5.png.
Same thing with spot and stripe patterns, which have 11 and 13 possible layer files respectively.

$markingint is the INT data column for each pet that controls their markings. We set this value, then add this code below it:
$nosepattern = $markingint % 5;
$footpattern = $markingint % 6; //uses up 2 and 3
$spotpattern = $markingint % 11;
$stripepattern = $markingint % 13;

Note that these are all prime numbers, except 6, but we sactifice 2 and 3 to have 6 foot markings.
Using all separate prime numbers allows different marking combinations to be possible.
Anyway...
The images are layered from your image folder as such (in whatever order you want):
"/foot" . $footpattern . ".png";
"/spot" . $spotpattern . ".png";

"/nose" . $nosepattern . ".png";
"/stripe" . $stripepattern . ".png";

So whatever the $markingint is, it'll apply all the different patterns. 
Let's look at two example pets.
Pet #1 has $markingint = 87;
This pet will have nose2.png, foot3.png, spot10.png, and stripe9.png.
Pet #2 has $markingint = 145;
Will have nose0.png, foot1.png, spot2.png, and stripe2.png.  
In practice, breeding these causes each marking to cycle like this: 0.png 1.png 2.png 3.png 4.png 0.png 1.png 2.png 3.png 4.png, I save the art files to have 0.png aand 4.png to look similar so it feels like you get markings that look similar to the parents when breeding. It's trickier to breed for a specific combination, though, especially if you don't understand the math behind the system.

What do you think? Do you have a better method? 
 

 
Last edited by a moderator:
Khimeros has the pinta marking, which is a series of 6 markings and you can get either a marking between the parents' marking numbers OR totally random depending on the option you select while breeding.  Not exactly the same but sort of similar idea.  I don't know the exact programming behind it though.  Another thing that I want to have implemented is similar to our dyes system, but instead of the user being allowed to choose where to put the dye, it would be a big marking sheet with say for example, lots of spots all over it and the system would move the sheet around and then mask to the base in a random spot.  This would give a different marking to every offspring that carries that pattern gene, expecially if you layered two different sheets, maybe one with patches and one with spots.

 
Khimeros has the pinta marking, which is a series of 6 markings and you can get either a marking between the parents' marking numbers OR totally random depending on the option you select while breeding.  Not exactly the same but sort of similar idea.  I don't know the exact programming behind it though.  Another thing that I want to have implemented is similar to our dyes system, but instead of the user being allowed to choose where to put the dye, it would be a big marking sheet with say for example, lots of spots all over it and the system would move the sheet around and then mask to the base in a random spot.  This would give a different marking to every offspring that carries that pattern gene, expecially if you layered two different sheets, maybe one with patches and one with spots.
Are you thinking of something like this? It randomize where the the spots go and creates a clipping mask into the top color layer to reveal another color underneathe. 
It might be cool to play around with resizing, rotating, etc. too to get all sorts of cool combos. 

View attachment 2740

Here's an imagemagick code for it:

//randomize for a 400px pet image
$x = mt_rand(0,400); 
$y = mt_rand(0,400);

$masklayer = new Imagick( $path . "/spots.png" ); //100x100px transparent png
$whitelayer->compositeImage($masklayer, Imagick::COMPOSITE_DSTOUT, $x, $y);
 

 
Last edited by a moderator:
Yes like that except a large sheet covered wtih spots or whatever design you like.  So instead of just moving the same design around on the base, you get a completely different look each time.

 
No, although players love custom stuff so if you have a system that can handle lots of custom markings that could be a thing.  I mean like if you have a pet that is 400x  400  then have a sheet that is 1200 x 600 and completely covered with random spots.  Then have a second marking that is covered with random patches or speckles or whatever.  Have the two sheets move independently and it will give a natural looking marking that's always a little bit different.

 
So it's basically an extremely simple and limited version of hashing (or is it just seeding? can you encode things, or only decode?). In simple cases like the one you described it looks like a neat solution. Although if the task is just to squeeze the genetic info into one db field, I would use either arrays, more complex hashing, NoSSL dbs, or maybe a combo of those. I'm pretty sure there are other (and neater!) solutions which I'm not aware about as a frontender. It won't be int, but image generation flexibility is far more important for a breeding game which has it as a central feature. I don't like to limit a game on the architectural level that much just for the sake of the number of db fields. Even if to start small like in the described example, you surely would love to extend the logic of image generation in future (imagine we need to store not random opacity for those markings, or already mentioned location, scale, rotation, or parameters for procedurally generated things, or something else). Hashing is a good and wide-used practice, but I definitely prefer more flexible approaches to it  :)

 
Last edited by a moderator:
No, although players love custom stuff so if you have a system that can handle lots of custom markings that could be a thing.  I mean like if you have a pet that is 400x  400  then have a sheet that is 1200 x 600 and completely covered with random spots.  Then have a second marking that is covered with random patches or speckles or whatever.  Have the two sheets move independently and it will give a natural looking marking that's always a little bit different.
Oooh, I get what you mean! That sounds better, could probably use the same code too (just change the ranges for $x and $y that determine where the sheet gets moved to). 
 

So it's basically an extremely simple and limited version of hashing (or is it just seeding? can you encode things, or only decode?). In simple cases like the one you described it looks like a neat solution. Although if the task is just to squeeze the genetic info into one db field, I would use either arrays, more complex hashing, NoSSL dbs, or maybe a combo of those. I'm pretty sure there are other (and neater!) solutions which I'm not aware about as a frontender. It won't be int, but image generation flexibility is far more important for a breeding game which has it as a central feature. I don't like to limit a game on the architectural level that much just for the sake of the number of db fields. Even if to start small like in the described example, you surely would love to extend the logic of image generation in future (imagine we need to store not random opacity for those markings, or already mentioned location, scale, rotation, or parameters for procedurally generated things, or something else). Hashing is a good and wide-used practice, but I definitely prefer more flexible approaches to it  :)
Oooh, I've never used a hashing or seeding method for this. How do you use those for genetic traits? And how would you name the image files being called up? (would they have the hash in them?) I'd like to see a snippet or example. I would love to implement bigger and better image generation methods for breeding systems. Or if you have a link to somewhere I can read about this, let me know. I'm also interested in hearing from you about which limitations would make you prefer another method. 

There's a few things I've been trying to smooth out (not sure if it's possible or not), such as finding a way to reverse the method (get the original value of the pet when your inputs are just the primes and modulus selections for each pattern). This would be useful for a generator where players get a custom pet. We have a generator on my site that uses the modulus, and you can select patterns by changing the hidden value, but I'd like to make it so there's a sliding scale or dropdown selection for each different type of markings, which all come together to generate the single value using the primes and modulus selections involved. I feel like this should be mathematically possible, but I never took high level math classes, so I'm still working my primitive brain trying to figure out a formula (if it's possible). 

And the tricky breeding thing I mentioned might be a limirtation or 'quirk,' another thing I'm not sure if there's a fix to. I'm still trying to figure something out for that on my site. 

I did find a solution to running out of smaller primes though. I just use another modulus to set it for how many files I want. For example, say you want to add a star pattern allele to a pet's genotype. You want different variations of stars, but the lowest prime you have available is 173 because the other 39 (or however many) primes before 173 are being used for other marking (or other types of variation like opacity and such). You don't want to draw 173 different star patterns, so:

$starpattern = $markingint % 173;
$starpattern2 = $starpattern % 3;


Add the layer for a file called "star" . $starpattern2 . ".png" and it'll cycle through 3 different star patterns based on the 173 remainder of the pet's marking value. If the pet has a marking value of 346, you get star0.png because 173 goes into 346 with a remainder of 0. 347 will give the pet star1.png, 348 will give star2.png, and 349 goes back to star0.png. 
I'm always testing though and will post on this thread if I find any limitations that I know of. 

Anyway, yeah. I'm interested in knowing more about hashing or other methods. 

 
Back
Top