Classic Snake Game with Snake Corners that follow Path

How do I…

I want an increasingly spawned snake body to follow the path of the head having correctly aligned Vertical & Horizontal Straight body sprites as well as correclty aligned corner pieces using L shaped sprites

What is the expected result

The body should align making a cohesive snake body with corners as appropriate

What is the actual result

The Snake head is directional and the body spawns when I collect charms as expected. But the body pieces don’t align to the path. At best corners face the wrong way or act differently depending on whether the turn is clockwise or anti clockwise and at worst, all pieces just face the same direction as each other.

Related screenshots

Snake was my first game recreation in gdevelop. This brings back memories, even tho you have a quite different approach to it :slight_smile:


I suspect you assign the BodyIndex of SnakeBody at creation (onCharmCollect) and keep it as a fixed value to know the right order of operation(?).
MyIndex on the contrary seems to be the currently picked instance.

I can’t fully grasp what is going on, but it seems to me, that there is a conflict between those two variables, wanting to do a similar thing, but ending up at different places, because MyIndex is changed dynamically, while BodyIndex is not.
I love your DebuggingText too. I guess you have one sticked to each instance of SnakeBody? You might need to refer to the index variable of that object then: Variable(SnakeBody.MyIndex). It never hurts to expand on that idea and add Variable(SnakeBody.BodyIndex) as well, to track any issues in real-time.


What I would recommend as a somewhat different concept is to put more data (you still need index reference inside the object) into a scene variable (preferably an Array of Structures / Structure of Arrays)
This can solve picking issues you might run into with snake parts, needing to know where the previous and the latter piece currently is at.

This can also work with your History-Approach, but it’s not even needed, if you can simply access [LoopIndexVar-1].

I am happy to lay out a more concrete explaination of what I mean, but it seems like you are already on a good track and just need to adjust your logic slightly.

Thanks for the advice and the quick response
2 things

  1. I’d be happy to share the full code and assets with you if that would help
    However, if there is a better way, which you perhaps mentions, I’d really like if if
  2. You could share more on your solution.

Thanks

Sure. I recommend creating a seperate object for the head, then all body parts.

Create AoS or SoA:

Array[0-n].X/Y/angle/animation or
Structure.X/Y/angle/animation[0-n]

Initialize all data with your snake head.
With every movement interval you:

  • add a new value at the end of each array

  • cycle through each index and copy each value of [index+1] into your current index

  • if you did not pick up a charm, then delete index 0

  • if you did pick up a charm create SnakeBody, assign ID and keep index 0

  • now cycle through each object and apply your object visualization based on the SoA/AoS (with this method you need to cycle through backwards!)

  • The animation and angle variable are used to determine corner parts / straight parts.

  • The head will always set these values for future parts to come (eg. if the angle of last child value is different to the one of your snake head, you should set animation to cornerPart)

Maybe I can make an example tomorrow.

But please don‘t screw your method. You can make it work. It‘s worthwhile to get the hang of your object-oriented-approach and then also worth to try a more data-driven approach (if interested).

I feel like this is the data-driven approach… the objects are being modified based on the data in the arrays.

This is definitely a good exercise in working with arrays, but if the body pieces all look the same then you wouldn’t actually need to loop through them all. You could just move the head, and then relocate the tail to fill the gap :stuck_out_tongue:

Anyway, I’m also not really sure why it isn’t working just from looking at your events. How is HistoryDir being written? I wonder if the array just has a mistake in how its populated with values.

I did get this working - Although it took a full page of debug output and a lot of manual trial and error as the ‘logic’ seems to defy logic if I’m honest. Here is a screenshot of working animation place ment - You will see animation names like CornerRU - That means the sprite is simply a corner piece connecting right an up - Whilst doesn’t align at all with the variable matching. But what I’ve ascertained is clockwise and anticlockwise matter, they use different sprites.

The only thing I can really summise from this is the incorrect data is being fed into the array - I do recall the logic being inverted when I was looking at the snake head initially as I was capturing the direction based on where the neck was, where in fact it was capturing where the tongue is - And in my mind I’m struggling to understand the difference - I guess for example when the snake head is moving down the sprite head is also down, unlike a character sprite which would always remain in the north south heads up position, even when you move is down -

Arggh, I don’t know it’s messing with my head - BUT IT"S WORKING

I should also add the the initial incorrect sprite matching was due to some weird anomoly I think that meant that
VariableString(SnakeBody.OutDir) didn’t match anything

where as
The variable OutDir of SnakeBody did

Anyone undersrand why that might be?

It took me a bit to understand your methodology. I think when I tried something similar, I used the angles between the segments. I love your method.

I think you could optimize the events though by replacing all of the conditions that check the in and out and just assign the animation by building the name using the in and out variables. You would need to rename the animations so they match the directions. Currently, they’re a bit of the opposite. You might also need to duplicate some animations so “SnakeUpUp” used the same file as “SnakeDownDown”. Or you could use just the first letter of each direction like “SnakeUU” and “SnakeUL”.

If it’s the tail
… Set animation to “Tail” + OutDir

If it’s not the head
If it’s not the tail
… Set animation to “Snake” + InDir + OutDir

(IDK if the head condition is needed)

You could add a seemless pattern to the snake and use different images for each direction. The snake could have scales or spots as long as each connected direction blended seemlessly with the next. The connecting edges would all match.

VariableString() and Variable() are obsolete and don’t need to be used anymore, although they should still work.

Anyway I think it was supposed to be SnakeBody.VariableString(OutDir)

You can try,

  • get detection of movement based on which button was pressed, you update the string variable.

Object= body.

  • if the variable = “right”
    then
    object x set to add object: object.width

  • if the variable = “left”
    then
    object x set to “subtract” object: object.width

  • if the variable = “up”
    then
    object y set to “subtract” object: object.height

  • if the variable = “down”
    then
    object y set to “add” object: object.height