Friday, April 5, 2013

Turtlefy!

Remember The Turtle Language (I mean, Logo) from last post? I was so disappointed that this online version of Logo (you know, by Google, with Blockly, etc.) didn't have an actual turtle... well, but why complain, when you can change it yourself?

That online version of Logo is client-based Javascript, which means that we can change it as we wish! Of course, sometimes people can make our lifes difficult with obfuscation and such, but for this one it was pretty straightforward. The function that draws the "turtle" is Turtle.display, in Turtle.js, so I just had to change that code with a circly turtle drawing code.

Yayyy, now with a turtle!

So, you can grab the bookmarklet below and run it in Blockly's Logo.

Bookmarklet: Turtlefy!

Or, alternatively, just run the code below in your javascript console:


Turtle.display = function() {
  Turtle.ctxDisplay.globalCompositeOperation = 'copy';
  Turtle.ctxDisplay.drawImage(Turtle.ctxScratch.canvas, 0, 0);
  Turtle.ctxDisplay.globalCompositeOperation = 'source-over';

  if (Turtle.visible) {
    /* Draw the turtle body. */
    var radians = 2 * Math.PI * Turtle.heading / 360;
    var radius = Turtle.ctxScratch.lineWidth / 2 + 10;

    /* Translation/rotation of the turtle, so it can point to the right way */
    Turtle.ctxDisplay.translate(Turtle.x, Turtle.y);
    Turtle.ctxDisplay.rotate(radians);
    /* Turtle body */
    Turtle.ctxDisplay.beginPath();
    Turtle.ctxDisplay.arc(0, 0, radius, 0, 2 * Math.PI, false);
    Turtle.ctxDisplay.lineWidth = 3;
    Turtle.ctxDisplay.fillStyle = '#009900';
    Turtle.ctxDisplay.strokeStyle = '#0eee09';
    Turtle.ctxDisplay.fill();
    /*head*/
    Turtle.ctxDisplay.beginPath();
    Turtle.ctxDisplay.arc(0, - radius, radius/2, 0, 2 * Math.PI, false);
    Turtle.ctxDisplay.fill();
    var pawRadius = radius/3;
    /*left front paw*/
    Turtle.ctxDisplay.beginPath();
    Turtle.ctxDisplay.arc(1-radius, 7 - radius, pawRadius, 0, 2 * Math.PI, false);
    Turtle.ctxDisplay.fill();
    /*left back paw 2*/
    Turtle.ctxDisplay.beginPath();
    Turtle.ctxDisplay.arc(3-radius, radius -3, pawRadius, 0, 2 * Math.PI, false);
    Turtle.ctxDisplay.fill();
    /*right front paw*/
    Turtle.ctxDisplay.beginPath();
    Turtle.ctxDisplay.arc(radius-1, 7 - radius, pawRadius, 0, 2 * Math.PI, false);
    Turtle.ctxDisplay.fill();
    /*right back paw 2*/
    Turtle.ctxDisplay.beginPath();
    Turtle.ctxDisplay.arc(radius-3, radius -3, pawRadius, 0, 2 * Math.PI, false);
    Turtle.ctxDisplay.fill();
    /*undo the rotation/translation to not mess with the drawing*/
    Turtle.ctxDisplay.rotate(-radians);
    Turtle.ctxDisplay.translate(-Turtle.x, -Turtle.y); 
  }
};

The original code calculated the right position for the head - instead, this one just use canvas rotation. I have to say, though, that it gets dismembered with big fat turtles.