Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

Following an assignment and just getting started with libGDX by building a small Snake clone I've run into an issue that I'll probably be ashamed for in a little while.

I currently have a snake's head (a simple rectangle at this stage) moving around the game's canvas. The most straight-forward way of building the rest of the snake was to have the head own a Java Collections LinkedList of SnakeElements which would in-/decrease in size according to what the player does.

Having this list of SnakeElements follow the head however has proven to not be trivial.

The current function doing this is as follows and is called every time the head updates its position:

private void moveTail (float x, float y, int direction) {
    float tmpx, tmpy;
    int tmpdirection;
    int offset_x, offset_y;

    for (SnakeSegment snse : tail) {
        offset_x = 0;
        offset_y = 0;

        tmpx = snse.getX();
        tmpy = snse.getY();
        tmpdirection = snse.getDirection();

        switch(direction) {
            case 0:
                offset_x = 0;
                offset_y = -(2 + snse.width);
                break;
            case 1:
                offset_x = -(2 + snse.width);
                offset_y = 0;
                break;
            case 2:
                offset_x = 0;
                offset_y = (2 + snse.width);
                break;
            case 3:
                offset_x = (2 + snse.width);
                offset_y = 0;
                break;
            default:
                System.out.println("wrong direction");
        }

        snse.setX(x + offset_x);
        snse.setY(y + offset_y);
        snse.setDirection(direction);

        x = tmpx;
        y = tmpy;
        direction = tmpdirection;
    }
}

which unfortunately results in this behavior:

gif

Any tips on how to make a correctly working snake tail would be much appreciated :)

share|improve this question

2 Answers 2

up vote 15 down vote accepted

Think of the problem like this:
How does a snake move in the original game?
The snake moves towards its current direction. The behavior looks like the head appears out of nothing, and the last tail part disappears.

You can have a list of snakeparts. What you want to do is remove the last item in the list which represents the last tail part.
Then you want to create a new headpart where it should be positioned and put it in the first position of the list.
This means the remainder of the snake is not moved since you only alter first and last position.
This creates a snakelike behavior.

share|improve this answer
    
Whoa, thanks! This makes a lot of sense and should've been the idea from the get go, looks like I'll have some fun refactoring :) I'm just sorry my sad amount of karma is preventing me from upvoting you. I promise I'll be back in the future! –  Kilian Koeltzsch May 3 at 23:36
1  
An alternative way to think about it is that each snake element follows only the element directly in front of it, rather than following the head. This will be useful if, later, the snakes are textured or anything like that. –  Nathan Reed May 4 at 2:48
1  
Here's the current version by the way, thanks again :) i.imgur.com/IaT5PNH.gif –  Kilian Koeltzsch May 4 at 14:55

The way I see it is as a "Caterpillar" like system, where each part of the snake follow the part ahead of it.

In another words, each part of the snake would be an Object with Position (x, y), a reference to the part ahead of it that it would use to move around and a function to process the position of the part ahead of it and move accordingly. The main snake (the Head) should have references for every part of the snake, and would call the function responsible to make the part follow its predecessor, being the Head the predecessor of the first part.
Hope it helps!

share|improve this answer
    
This was the idea, but handling corners turned out to be quite complex. And what would happen if a player would turn a sharp 180 degree corner? We weren't sure how to handle this correctly, and using the method as described by Pontus Magnusson solves all these problems nicely. –  Kilian Koeltzsch May 4 at 14:58
    
I see. The only time I implemented a caterpillar system I had a grid with cells at the size of the parts, so each part was always inside one specific cell, this way, the problem didn't occur. Sorry for my bad english. –  NotAnActualLince May 5 at 0:40
    
Ah yes, that makes sense and should also work, but we ditched the idea of having a grid for a reason I can't currently remember ;) Thanks though :) –  Kilian Koeltzsch May 5 at 6:55

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.