Collecting wild snails

I got quite a bit done on the snails yesterday, mostly focusing on creating a snail manager class, displaying snails using Canvas, and saving snails you choose to keep to the database. It’s all implemented really dodgily right now, but it’s mostly functional.

The wild snail collection flow now kind of looks like this (obviously it still needs a lot of work):

Log in

You log in to the site with your chosen username and password (assuming you’ve already registered and verified your account). A Stable Overview page is shown, displaying your chosen stable name and eventually other details (like your jars, news, etc).

Stable page

On login, we check if the user has ever logged in before and show some helpful text to point them in the right direction:

	<?PHP if ($fgmembersite->FirstLogin()) { ?>
		Looks like you're new here! You should go and <a href="../world/collect.php">find your first snail</a>.

	<?PHP } ?>


Search for a snail

You can choose where you want to search for your first snail. It doesn’t make any difference right now, but eventually certain kinds of snails will be prone to hang out at certain locations.

		<li><a href="?run=rock">Under a rock in your garden</a></li>
		<li><a href="?run=bushes">Around the bushes near your house</a></li>
		<li><a href="?run=tree">Under the old oaktree</a></li>


Found a snail

A random snail is then generated in snailmanager.php:

	function SearchRock() {

        $snail = $this->GenerateRandomSnail();
        $snail = $this->GenerateGeneString($snail);
        return $snail;

    function SearchBushes() {

        $snail = $this->GenerateRandomSnail();
        $snail = $this->GenerateGeneString($snail);
        return $snail;

    function SearchTree() {
        print "searching tree";
        $snail = $this->GenerateRandomSnail();
        $snail = $this->GenerateGeneString($snail);
        return $snail;


    function GenerateRandomSnail() {
        $minStat = 1;
        $maxStat = 5;

        $minArousalDelay = 1;
        $maxArousalDelay = 15;

        $snail['scouted'] = false;
        $snail['maxSpeed'] = $this->RandomFloat($minStat, $maxStat);
        $snail['currentSpeed'] = $snail['maxSpeed'];

        $snail['maxEndurance'] = $this->RandomFloat($minStat, $maxStat);
        $snail['currentEndurance'] = $snail['maxEndurance'];

        $snail['maxWeight'] = $this->RandomFloat(1, 25);
        $snail['currentWeight'] = $snail['maxWeight'];

        // APPEARANCE 
        $snail['shellColorR'] = $this->RandomColor(0,255);
        $snail['shellColorG'] = $this->RandomColor(0,255);
        $snail['shellColorB'] = $this->RandomColor(0,255);

        $snail['eyeColorR'] = $this->RandomColor(0,255);
        $snail['eyeColorG'] = $this->RandomColor(0,255);
        $snail['eyeColorB'] = $this->RandomColor(0,255);

        $snail['patternColorR'] = $this->RandomColor(0,255);
        $snail['patternColorG'] = $this->RandomColor(0,255);
        $snail['patternColorB'] = $this->RandomColor(0,255);

        $snail['patternShape'] = $this->RandomInteger(1,3);
        $snail['arousalDelay'] = $this->RandomInteger($minArousalDelay, $maxArousalDelay);

        // WEIGHT
        $weightPercentage = $this->CalcPercentage($snail['maxWeight'], 5);
        $snail['maxScale'] = $this->CalcTargetPercentageValue($weightPercentage, 1);
        if ($snail['maxScale'] > 1) {
            $snail['maxScale'] = 1;
        $snail['currentScale'] = $snail['maxScale'];

        // This is for appearances only, do not store in db
        $snail['maxSize']['x'] = $this->CalcTargetPercentageValue($weightPercentage, 150);
        $snail['maxSize']['y'] = $this->CalcTargetPercentageValue($weightPercentage, 150);
        // ------- 
        $snail['size']['x'] = $snail['maxSize']['x'];
        $snail['size']['y'] = $snail['maxSize']['y'];
        $snail['age'] = 5;
        $snail['name'] = "Unnamed";
        $snail['health'] = 100;
        $snail['arousalDelay'] = $this->RandomFloat(1,15);

        $snail['stagID'] = 0;
        $snail['doeID'] = 0;

        return $snail;


As you can see above the weight of the snail is not limited to the 1-5 starting snail stat range, since a higher weight stat doesn’t necessarily mean a better snail and wild snails can be just as heavy as captively bred ones (at least in the beginning).

We then generate a gene string for the snail based on its stats:

    function GenerateGeneString($snail) {
        $arrayOfColors = [
            "r" => $snail['shellColorR'], 
            "g" => $snail['shellColorG'], 
            "b" => $snail['shellColorB']
        $snail['shellColorGeneAllele1'] = strtoupper($this->FindDominantColor($arrayOfColors));
        $snail['shellColorGeneAllele2'] = $this->FindDominantColor($arrayOfColors);

        $arrayOfColors = [
            "r" => $snail['eyeColorR'], 
            "g" => $snail['eyeColorG'], 
            "b" => $snail['eyeColorB']
        $snail['eyeColorGeneAllele1'] = strtoupper($this->FindDominantColor($arrayOfColors));
        $snail['eyeColorGeneAllele2'] = $this->FindDominantColor($arrayOfColors);

        $arrayOfColors = [
            "r" => $snail['patternColorR'], 
            "g" => $snail['patternColorG'], 
            "b" => $snail['patternColorB']
        $snail['patternColorGeneAllele1'] = strtoupper($this->FindDominantColor($arrayOfColors));
        $snail['patternColorGeneAllele2'] = $this->FindDominantColor($arrayOfColors);

        switch ($snail['patternShape']) {
            case 1:
                $snail['patternShapeGeneAllele1'] = 'A';
                $snail['patternShapeGeneAllele2'] = 'b';
            case 2:
                $snail['patternShapeGeneAllele1'] = 'B';
                $snail['patternShapeGeneAllele2'] = 'b';
            case 3:
                $snail['patternShapeGeneAllele1'] = 'C';
                $snail['patternShapeGeneAllele2'] = 'c';


        return $snail; 


Displaying the snail

Once the random snail is generated, we draw it on HTML5 canvas on the collection page:

	<?PHP if ($newSnail != null) { ?>

	<h2>You found one!</h2>

	<!-- Create a canvas to draw the snail -->

		$snail = $newSnail;

	<!-- We are going to convert the PHP vars we got about the snail to a JS array, to draw it on canvas -->
	<script type="text/javascript">
	    snailVars = {};
	    <?php foreach($newSnail as $item => $value) { ?>
	    	snailVars.<?= $item ?> = "<?= $value ?>";
	    <?php }; ?>
	<script src="../js/displaysnail.js"></script>


Then we draw the actual snail in displaysnail.js and make it crawl back and forth (using the generated speed stat).

function move(delta) {
	if (!flip) {
		pos.x -= visualSpeed * delta;
	else {
		pos.x += visualSpeed * delta;

	if (pos.x + snailTemplateWidth >= c.width) {
		flip = false;
		snailTemplatePath = snailTemplatePathLeft;

	else if (pos.x <= 0) {
		flip = true;
		snailTemplatePath = snailTemplatePathRight;

function draw(delta) {
    ctx.lineWidth = 5;
	var img = new Image();
    img.src = snailTemplatePath;
    img.onload = function(){
    	ctx.clearRect(0, 0, c.width, c.height);
    	var yPos = 0;
    	var xPos = pos.x + 0;
  		ctx.drawImage(img,pos.x + 0,0, 150 * snailVars.currentScale, 117 * snailVars.currentScale); 


As you can see in the screenshot above, you do not see the snail’s exact stats, but a rough estimate of what range the stat would be in. You can get a rough idea of the snail’s speed by seeing how quickly it crawls back and forth along the canvas. To get the exact stats you would need to take your snail to a “scout”, who can evaluate the snail and show you the exact numbers.

Save a snail

If you’re happy with the snail you found, you can create a name for it and specify which of your jars you want it to be placed it to save it to the database (the jars have yet to be implemented).


Up next I’m going to work on the jars and the snail profile pages.

(In other news, I make a Spotify playlist for each hobby project I work on. It helps to get me into the “mood” of the game. Here’s one for Game of Snails!)

© - 2021 · Liza Shulyayeva ·