Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript

How can I add a body part to my snake?

// Creates the canvas for our game.
var canvas = Raphael(10, 2, 400, 400),
// Creates the background for our canvas.
backgroundRect = canvas.rect(0,0,400,400);


// Generates and returns a random number between 0 and 400.
function getRandNum () {
    var rand = Math.round(Math.random()*400);
    // This while loop ensures that our snakeGoal never exceeds the coordinates x = 390 or y = 390. If it did, it's parts would be cut from the canvas.
    while (rand > 395) {
        rand = Math.round(Math.random()*400);
    }
    // This while loop ensures that our rand variabe will always be divisible by 10, which is used to make sure our snakeGoal and snakePart elements are always rendered in coordinates divisible by 10.
    while (rand % 10 !== 0) {
        var randString = rand.toString(),
            // This variable stores the whole length of our randString variable.
            randStringLength = randString.length,
            // This variable stores the last number of our rand as a string character.
            subtractionChar = randString.charAt(randStringLength - 1),
            // This variable stores the last number of our rand as a integer.
            subtractionInt = parseInt(subtractionChar),
            // Finally, this line subtracts the last number of our rand from itself and then sets it equal to itself, ensuring that rand is always divisible by 10.
            rand = rand - subtractionInt;
    }
    return rand;
}

// We set this variable globally so all of our functions have it in their scope.
var start_interval;

// This function builds the goal of our snake.
function buildElement (element) {
    switch (element) {
        // Creates the goal for our snake at a random point on our canvas.
        case "snakeGoal":
            snakeGoal = canvas.rect(getRandNum(),getRandNum(),10,10);
            snakeGoal.attr("fill", "red");
            snakeGoal.attr("stroke-width", ".25");
            snakeGoal.toBack();
            backgroundRect.toBack();
        break;

                // Creates the head of our 'snake'.
        case "snakePart":
            snakePart = canvas.rect(10,390,10,10);
            snakePart.attr("fill", "blue");
            snakePart.attr("stroke-width", "0");
            snakePart.hide();
        break;

    }
};

function moveDirection (direction) {
    // This function allows makes our svg graphic move according to the arrow key clicked.
    movePeice = function(direction){

        var old_X = snakePart.attr("x"),
            old_Y = snakePart.attr("y"),
            new_X,
            new_Y;

        // This if-else statement makes our snakePart to where it can not go outside of the canvas or else the game will be lost.
        if (old_X >= 0 && old_X <= 390 && old_Y >= 0 && old_Y <= 390) {
            var snakePartXCoordinate = snakePart.attr("x"),
                snakePartYCoordinate = snakePart.attr("y"),
                snakeGoalXCoordinate = snakeGoal.attr("x"),
                snakeGoalYCoordinate = snakeGoal.attr("y");

            snakePart.show();

            // This switch statement makes our snakePart move according to the value of the direction parameter.
            switch (direction) {

                case "right":
                    new_X = old_X + 10;
                    snakePart.attr("x", new_X);
                break;

                case "left":
                    new_X = old_X - 10;
                    snakePart.attr("x", new_X);
                break;

                case "up":
                    new_Y = old_Y - 10;
                    snakePart.attr("y", new_Y);
                break;

                case "down":
                    new_Y = old_Y + 10;
                    snakePart.attr("y", new_Y);
                break;

                default:
                    alert("ERROR:: PROHIBITED MOVEMENT!");
                break;
            }

            // This if statement runs if the coordinates for both our snakeGoal and snakePart are equal. It removes our snakeGoal from the canvas and rerenders it somewhere else on the canvas.
            if (snakePartXCoordinate === snakeGoalXCoordinate && snakePartYCoordinate === snakeGoalYCoordinate) {
                snakeGoal.remove();
                buildElement("snakeGoal");
            }

        } 
        // This else statement runs if our snakePart leaves the canvas, removing our elements from the screen and displaying the 'lost' message.
        else {
            snakeGoal.remove();
            snakePart.remove();
            backgroundRect.hide();
            $('#lost').show();
        }
    }

    // This if-else statement tells our peice that if it's direction does not equal "stop", then move our peice according to the direction specified.
    if (direction !== "stop") {
        // The clearInterval(start_interval) is here to eliminate any previous interval that was running.
        clearInterval(start_interval);
        start_interval = setInterval(function(){movePeice(direction)}, 100);
    } else {
        clearInterval(start_interval);
    }
};

// This function calls our moveDirection() whenever the arrows are pressed. It will also restart or stop the game if you press 'r' or 'space' respectively.
$(document).keydown(
    function(a){
        if (a.which === 32) {
            moveDirection("stop");
        } else if (a.which === 37) {
            moveDirection("left");
            return false;
        } else if (a.which === 38) {
            moveDirection("up");
            return false;
        } else if (a.which === 39) {
            moveDirection("right");
            return false;
        } else if (a.which === 40) {
            moveDirection("down");
            return false;
        } else if (a.which === 82) {
            moveDirection('stop');
            snakeGoal.remove();
            snakePart.remove();
            buildElement("snakePart");
            buildElement("snakeGoal");
            backgroundRect.show();
            $("#lost").hide();
            return false;
        }
        a.preventDefault();
    }
);

buildElement("snakePart");
buildElement("snakeGoal");

backgroundRect.attr("fill", "#CDCDCD");
backgroundRect.attr("stroke-width", "0");
backgroundRect.toBack();

$("#lost").hide();

Okay, so I am fairly new to programming and I have been creating a JavaScript based snake game. Using Raphael JavaScript Library (raphaeljs.com), i have created the canvas and the 'items' to be used in the game. I have given these items their basic behavior, but I am stuck at the part where the snake should add another body part that follows it's tail after it grabs one of the 'goal' pieces. If someone could help me out and explain to me a possible way of doing this, that would be excellent. Also, feel free to constructively criticize the semantics of my code. Like I have said, I'm new and still learning. Any helpful advice is appreciated. Thanks!:)