0 votes

I'm trying to use a dictionary to keep track of the movements of the snake in a snake game. So far, I've managed to keep track of the head of the snake, but I fail to see how I should keep track of the body movements.

What I'm doing is this: When the head of the snake moves one cell I fill the gap with the last segment of the body (when the snake doesn't grow) or with a new body segment (when the snake grows). How should I keep track of that movement? What should I erase?

My code for the head movement (GridData.Content is the dictionary):

func _on_Timer_timeout():
    GridData.previousHeadPosition = GridData.GetCellPosition(self.position)
    GridData.Content[GridData.previousHeadPosition] = GridData.Item.SNAKE
    match direction:
        Here I check which direction the head should go (this works fine)
    GridData.currentHeadPosition = GridData.GetCellPosition(self.position)
    GridData.Content[GridData.currentHeadPosition] = GridData.Item.SNAKE

My code for the body movement so far (There are a total of 90 body segments, but I'm only using 10 of them):

var noOfBodySegments := 90
var bodySegmentArray := []
var startCell := Vector2(7, 7)
var counterStart := 0
var counterEnd := 9
var counter := counterStart

onready var timer = get_node("Timer")


func _ready():
    var bodySegment
    for _i in range(noOfBodySegments):
        bodySegment = Sprite.new()
        bodySegment.texture = load("res://Sprites/Body.png")
        add_child(bodySegment)
        bodySegment.position = GridData.GetPixelPosition(Vector2(-1, -1))
        bodySegmentArray.append(bodySegment)

func _on_Timer_timeout():
    bodySegmentArray[counter].position = GridData.GetPixelPosition(GridData.currentHeadPosition)
    counter += 1
    if counter > counterEnd:
        counter = counterStart

Thanks for having a look at this.

Godot version 3.5
in Engine by (18 points)

2 Answers

0 votes

I can't really see full use of this dictionary we were talking about in previous question.
You could just do something like this with it once every snake grid move :

for i in segments:
      GridData[i.position] = enum.SNAKE

Alternatively, You could keep track of all past positions of a head, since body segments always follow head anyway. For example - current position of 3rd segment of the body is the same as position of the head 3 turns ago. This would even make things like spawning new segments easier - You won't risk spawning new segment into a wall, they will just spawn at positions head were before.

by (8,101 points)

Thanks for your reply. Body segments do indeed follow the head, but not indefinitely. The body has a certain length and once the whole body is past a certain cell, that cell has to be unlocked again. Anyway, your comments have me thinking about it thoroughly. I hope to find a solution soon.

0 votes

I'm answering this question myself, because I think I've found a solution. I'm using an array and a dictionary. First I push the new head position to the front of the array Snake.segments. Then I add the same new head position as a key to the dictionary Grid.content. I set the matching value to the enum value Grid.item.SNAKE. If the array size is longer than the snake length I remove the last element from the array and erase it from the dictionary.

func _on_Timer_timeout():
    match direction:
        Checking which direction the head should go
    Snake.headPosition = Grid.GetCellPosition(self.position)
    Snake.segments.push_front(Snake.headPosition)
    Grid.content[Snake.headPosition] = Grid.item.SNAKE
    if Snake.segments.size() > Snake.length:
        var freedCell = Snake.segments.pop_back()
        Grid.content.erase(freedCell)
by (18 points)
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.