0

I cannot figure out why my collision function is working for one element and not for another.It's madness ,please help.It detects the food collision but it doesn't detect when the head of the snake hits it's other elements.

window.onload= function ()
{
    var canvas=document.getElementById("canvas");
    var context=canvas.getContext("2d");

    var canvasWidth=window.innerWidth-20;
    var canvasHeight=window.innerHeight-20;
    canvas.width=canvasWidth;
    canvas.height=canvasHeight;


    var up=false;
    var down=false;
    var left=false;
    var right=true;

       var snake={
        x:20,
        y:0,
        w:10,
        h:10
    };
    var snakeBody=[];
    for (i = 0; i < 20; i++) {
        snakeBody.push({
        x:snake.x ,
        y:snake.y ,
        w:snake.w,
        h:snake.h
    });
    snake.x +=20;
    }

    var food={
        x:Math.floor(Math.random() * (canvasWidth-50)),
        y:Math.floor(Math.random() * (canvasHeight-50)),
        w:10,
        h:10
    };

    function moveUp()
    {

            snakeBody[0].y -=3;

    }
    function moveDown()
    {

            snakeBody[0].y +=3;

    }
    function moveLeft()
    {

            snakeBody[0].x -=3;

    }
    function moveRight()
    {

            snakeBody[0].x +=3;


    }
    function draw()
    {
        context.clearRect(0,0,canvasWidth,canvasHeight);
        context.fillStyle="black";

        context.beginPath();

       for (var i = snakeBody.length - 1; i > 0 ; i--) {
           context.rect(snakeBody[i].x,snakeBody[i].y,snakeBody[i].w,snakeBody[i].h);
           snakeBody[i].x = snakeBody[i-1].x;
           snakeBody[i].y = snakeBody[i-1].y;
        }
        context.rect(snakeBody[0].x,snakeBody[0].y,snakeBody[0].w,snakeBody[0].h);
        context.rect(food.x,food.y,food.w,food.h);

        context.stroke();
        context.fill();


        for (var i = 1; i < snakeBody.length; i++) {
            if (intersects(food.x,food.y,food.w,food.h,snakeBody[i].x,snakeBody[i].y,snakeBody[i].w,snakeBody[i].h)) {
                generateFood();
                growSnake();
            }
            var head=snakeBody[0];
            if (intersects(head.x,head.y,head.w,head.h,
            snakeBody[i].x,snakeBody[i].y,snakeBody[i].w,snakeBody[i].h)) {
                alert('game over');
            }
        }

        directions();
        collision();
        update();


    }
    function growSnake()
    {
        for (i = 0; i < 5; i++) {
        snakeBody.push({
        x:snake.x ,
        y:snake.y ,
        w:snake.w,
        h:snake.h
    });
    snake.x +=20;
    }
    }
    function generateFood()
    {
        food.x=Math.floor(Math.random() * (canvasWidth-50));
        food.y=Math.floor(Math.random() * (canvasHeight-50));
    }
    function intersects(x1, y1, w1, h1, x2, y2, w2, h2) {
    w2 += x2;
    w1 += x1;
    if (x2 > w1 || x1 > w2) return false;
    h2 += y2;
    h1 += y1;
    if (y2 > h1 || y1 > h2) return false;
  return true;
}
    function directions()
    {
        document.onkeydown = function(e)
        {
           var event = window.event ? window.event : e;
             var keycode = event.keyCode;
            if (keycode===37 && right===false) {
                left=true;
                right=false;
                up=false;
                down=false;
            }
            if (keycode===38 && down===false) {
                up=true;
                down=false;
                left=false;
                right=false;
            }
            if (keycode===39 && left===false) {
                right=true;
                left=false;
                up=false;
                down=false;
            }
            if (keycode===40 && up===false) {
                down=true;
                up=false;
                left=false;
                right=false;
            }
        };
    }
    function update()
    {
        if (up) {moveUp();}
        if (down) {moveDown();}
        if (left) {moveLeft();}
        if (right) {moveRight();}
    }
    function gameOver()
    {
        alert('game over!');
    }
     function collision()
     {


         if (snakeBody[0].x >canvasWidth) {
            snakeBody[0].x  = 0;
        }
        if (snakeBody[0].x < 0) {
            snakeBody[0].x=canvasWidth;
        }
        if (snakeBody[0].y>canvasHeight) {
            snakeBody[0].y=0;
        }
        if (snakeBody[0].y <0) {
            snakeBody[0].y=canvasHeight;
        }

     }
        setInterval(draw,20);
};

It's a lot of code, so here's a fiddle http://jsfiddle.net/5nLQG/

Focus would seem to be function intersects:

 function intersects(x1, y1, w1, h1, x2, y2, w2, h2) {
    w2 += x2;
    w1 += x1;
    if (x2 > w1 || x1 > w2) return false;
    h2 += y2;
    h1 += y1;
    if (y2 > h1 || y1 > h2) return false;
  return true;
}
3
  • Snake snake snake snake snake snake snake -Vi Hart Commented Jan 3, 2014 at 22:24
  • I presume intersects does collision testing. Why are you incrementing values there also? Commented Jan 3, 2014 at 22:40
  • What browser are you using? If it's chromes\ there's a chance you just clicked hide alerts. Change alert("gameover") to console.log("gameover") and check dev console. Commented Jan 3, 2014 at 22:44

1 Answer 1

1

Yep. Check it out. Game over is being hit. Repeatedly. Because your blocks are all scrunched up it's difficult to do collision detection in the first place. In fact only checking after the 20th cube was I able to have a functional game. Check it out

        if (i - 20 > 0&& intersects(snakeBody[0].x,snakeBody[0].y,snakeBody[0].w,snakeBody[0].h,
        snakeBody[i].x,snakeBody[i].y,snakeBody[i].w,snakeBody[i].h)) {
             clearInterval(pulse);
        }

Where I declare pulse the timeInterval ID http://jsfiddle.net/fC25X/

I would work on spacing your cubes and you should be golden

What to do?

I think there's a great joy in figuring out these simple games for yourself. For instance minesweeper if not done properly can give massive stackoverflows. I've written a snake game before and I will quickly explain how I managed cubes following each other. Your way seems like it could work with a bit of playing around, so only read further if you don't care about figuring out the process yourself. My way is probably not best either.

Actually pretty terrible

I remember my particular implementation of snake I kept a separate array called 'turningPoints' and on keypress it looked something like this:

    document.onkeydown = function(e)
    {
       var event = window.event ? window.event : e;
       var keycode = event.keyCode;
       if (keycode===37 && right===false) {
            left=true;
            right=false;
            up=false;
            down=false;
            turningPoints.push(snake[0].x,snake[0].y,[1,0]); // [1,0] matrix for right
       }
    }

Then when iterating over each cube (this is where it gets messier) I moved each cube in the direction it was going, and then checked to see if it had reached a turningPoint (with some margin of error), if it had then it would change direction:

   if(snake[i].x == turningPoint[j].x && snake[i].y == turningPoint[j].y)
         snake[i].direction = turningPoint[j].direction;

I made sure to clean up turningPoints (after all the cubes have followed the instruction there's no need to keep the point), and the whole thing worked OK

BUT

I got bored, and played around with your way a bit more and came up with this http://jsfiddle.net/LAMZt/ It's quiet a bit different, but it's more or less the same. Noticed another issue was that you snake's head was the left most piece going right, so naturally, it collided with the other pieces. So I fixed it by rendering additional pieces as the snake moved. The rest was just house keeping so I could save it as a gist (referenced this question of course).

Sign up to request clarification or add additional context in comments.

6 Comments

20th rich? Could you explain for those of us unfamiliar?
Terrible typo. Meant to write "cube", but guess they are squares anyway
There are a number of ways. The main reason they scrunch up is because instead of moving each piece 3px per iteration, you shift each piece into the next piece's position. Let each x be a square and each o be a pixel xoooooxoooooxooooox then goes to xoooooxoooooxooox then xoooooxoooxooox finally xoooxoooxooox at which point the squares are overlapping.
What is xoooooxoooooxooooox this suppose to mean?Can't you tell me with words how to fix it?I don't understand this.
Watch the whole process very slowly and hopefully it will make more sense jsfiddle.net/5hD39
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.