# NaaLaa

Full Version: Question about snake game
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I have a question about the snake game. The snake's body is divided into small pieces and they follow the head. How can I make the pieces that make up the body follow the head of the snake when I move it?
Here's a port of an n6 example game. Hopefully you can find some clues by looking at the code   I don't remember why I implemented the game like this, and probably there are smarter ways.

Code:
```' Port of n6 example game. SNAKE_MAX_LENGTH = 30*40 UP = 1 DOWN = 2 LEFT = 3 RIGHT = 4 snake = dim(SNAKE_MAX_LENGTH, 2) level = dim(40, 30) set window "Smape", 320, 240, false, 2 set redraw off do     snakeLength = 1     snakeHead = 0     snakeDirection = 0     speed = 10     speedCounter = speed     snake[snakeHead][0] = 20     snake[snakeHead][1] = 15     for y = 0 to 29  for x = 0 to 39  level[x][y] = 0     gameOver = false     nextPlupTime = clock()     do         if clock() >= nextPlupTime             if rnd(3) = 0  level[rnd(40)][rnd(30)] = 2             else  level[rnd(40)][rnd(30)] = 1             nextPlupTime = clock() + 2000 + rnd(2000)         endif         if keydown(38) and snakeDirection <> DOWN  snakeDirection = UP         if keydown(40) and snakeDirection <> UP  snakeDirection = DOWN         if keydown(37) and snakeDirection <> RIGHT  snakeDirection = LEFT         if keydown(39) and snakeDirection <> LEFT  snakeDirection = RIGHT             speedCounter = speedCounter - 1         if speedCounter = 0             prev = snakeHead             if snakeDirection > 0  snakeHead = (snakeHead + 1)%SNAKE_MAX_LENGTH             speedCounter = speed             if snakeDirection = UP                 snake[snakeHead][0] = snake[prev][0]                 snake[snakeHead][1] = snake[prev][1] - 1             elseif snakeDirection = DOWN                 snake[snakeHead][0] = snake[prev][0]                 snake[snakeHead][1] = snake[prev][1] + 1             elseif snakeDirection = LEFT                 snake[snakeHead][0] = snake[prev][0] - 1                 snake[snakeHead][1] = snake[prev][1]             elseif snakeDirection = RIGHT                 snake[snakeHead][0] = snake[prev][0] + 1                 snake[snakeHead][1] = snake[prev][1]             endif             x = snake[snakeHead][0]             y = snake[snakeHead][1]             if x < 0 or x >= 40 or y < 0 or y >= 30                 gameOver = true             else                 if level[x][y] > 0                     snakeLength = snakeLength + 1                     if level[x][y] = 2  speed = max(speed - 1, 0)                     level[x][y] = 0                 endif             endif         endif         set color 0, 0, 0         cls         for y = 0 to 29             for x = 0 to 39                 if level[x][y] = 1                     set color 0, 255, 0                     draw rect x*8, y*8, 8, 8 , true                 elseif level[x][y] = 2                     set color 255, 0, 0                     draw rect x*8, y*8, 8, 8, true                 endif             next         next         set color 255, 255, 255         set caret 0, 0         x = snake[snakeHead][0]         y = snake[snakeHead][1]         for i = snakeHead to snakeHead - snakeLength + 1             j = i             if j < 0 then j = j + SNAKE_MAX_LENGTH             draw rect snake[j][0]*8, snake[j][1]*8, 8, 8, true             if i <> snakeHead                 if snake[j][0] = x and snake[j][1] = y then gameOver = true             endif         next         wait 10         redraw     until gameOver loop```
Love the "classics"...

Could not help myself... Added a few minor upgrades: Little bit of colour; Score/Hiscore; Quit level and restart (ESC); Quit game (Q).  Note: No external hiscore.

Scoring has been modified. "Green" food is the normal 10 points. "Red" food is worth 100 points. Note: The speed of the snake will still increase... Moo Ha Ha Ha...

[attachment=319]

Challenge: Sound and messages?

J
(07-20-2024, 10:46 AM)johnno56 Wrote: [ -> ]Love the "classics"...

Could not help myself... Added a few minor upgrades: Little bit of colour; Score/Hiscore; Quit level and restart (ESC); Quit game (Q).  Note: No external hiscore.

Scoring has been modified. "Green" food is the normal 10 points. "Red" food is worth 100 points. Note: The speed of the snake will still increase... Moo Ha Ha Ha...

Challenge: Sound and messages?

J

Would be interesting to modify the visuals so that the snake uses tiles with rounded corners where it turns etc. But I'm too busy with that game jam thing (right now I'm sitting on a bench at the mall though, not jamming at all, wife and youngest daughter running around in clothes stores ...).
(07-20-2024, 09:23 AM)Marcus Wrote: [ -> ]Here's a port of an n6 example game. Hopefully you can find some clues by looking at the code   I don't remember why I implemented the game like this, and probably there are smarter ways.

Code:
```' Port of n6 example game. SNAKE_MAX_LENGTH = 30*40 UP = 1 DOWN = 2 LEFT = 3 RIGHT = 4 snake = dim(SNAKE_MAX_LENGTH, 2) level = dim(40, 30) set window "Smape", 320, 240, false, 2 set redraw off do     snakeLength = 1     snakeHead = 0     snakeDirection = 0     speed = 10     speedCounter = speed     snake[snakeHead][0] = 20     snake[snakeHead][1] = 15     for y = 0 to 29  for x = 0 to 39  level[x][y] = 0     gameOver = false     nextPlupTime = clock()     do         if clock() >= nextPlupTime             if rnd(3) = 0  level[rnd(40)][rnd(30)] = 2             else  level[rnd(40)][rnd(30)] = 1             nextPlupTime = clock() + 2000 + rnd(2000)         endif         if keydown(38) and snakeDirection <> DOWN  snakeDirection = UP         if keydown(40) and snakeDirection <> UP  snakeDirection = DOWN         if keydown(37) and snakeDirection <> RIGHT  snakeDirection = LEFT         if keydown(39) and snakeDirection <> LEFT  snakeDirection = RIGHT             speedCounter = speedCounter - 1         if speedCounter = 0             prev = snakeHead             if snakeDirection > 0  snakeHead = (snakeHead + 1)%SNAKE_MAX_LENGTH             speedCounter = speed             if snakeDirection = UP                 snake[snakeHead][0] = snake[prev][0]                 snake[snakeHead][1] = snake[prev][1] - 1             elseif snakeDirection = DOWN                 snake[snakeHead][0] = snake[prev][0]                 snake[snakeHead][1] = snake[prev][1] + 1             elseif snakeDirection = LEFT                 snake[snakeHead][0] = snake[prev][0] - 1                 snake[snakeHead][1] = snake[prev][1]             elseif snakeDirection = RIGHT                 snake[snakeHead][0] = snake[prev][0] + 1                 snake[snakeHead][1] = snake[prev][1]             endif             x = snake[snakeHead][0]             y = snake[snakeHead][1]             if x < 0 or x >= 40 or y < 0 or y >= 30                 gameOver = true             else                 if level[x][y] > 0                     snakeLength = snakeLength + 1                     if level[x][y] = 2  speed = max(speed - 1, 0)                     level[x][y] = 0                 endif             endif         endif         set color 0, 0, 0         cls         for y = 0 to 29             for x = 0 to 39                 if level[x][y] = 1                     set color 0, 255, 0                     draw rect x*8, y*8, 8, 8 , true                 elseif level[x][y] = 2                     set color 255, 0, 0                     draw rect x*8, y*8, 8, 8, true                 endif             next         next         set color 255, 255, 255         set caret 0, 0         x = snake[snakeHead][0]         y = snake[snakeHead][1]         for i = snakeHead to snakeHead - snakeLength + 1             j = i             if j < 0 then j = j + SNAKE_MAX_LENGTH             draw rect snake[j][0]*8, snake[j][1]*8, 8, 8, true             if i <> snakeHead                 if snake[j][0] = x and snake[j][1] = y then gameOver = true             endif         next         wait 10         redraw     until gameOver loop```
I'll see if I can understand the code where the body follows the head, thank you.
(07-20-2024, 06:50 PM)aliensoldier Wrote: [ -> ]
(07-20-2024, 09:23 AM)Marcus Wrote: [ -> ]Here's a port of an n6 example game. Hopefully you can find some clues by looking at the code   I don't remember why I implemented the game like this, and probably there are smarter ways.

Code:
```' Port of n6 example game. SNAKE_MAX_LENGTH = 30*40 UP = 1 DOWN = 2 LEFT = 3 RIGHT = 4 snake = dim(SNAKE_MAX_LENGTH, 2) level = dim(40, 30) set window "Smape", 320, 240, false, 2 set redraw off do     snakeLength = 1     snakeHead = 0     snakeDirection = 0     speed = 10     speedCounter = speed     snake[snakeHead][0] = 20     snake[snakeHead][1] = 15     for y = 0 to 29  for x = 0 to 39  level[x][y] = 0     gameOver = false     nextPlupTime = clock()     do         if clock() >= nextPlupTime             if rnd(3) = 0  level[rnd(40)][rnd(30)] = 2             else  level[rnd(40)][rnd(30)] = 1             nextPlupTime = clock() + 2000 + rnd(2000)         endif         if keydown(38) and snakeDirection <> DOWN  snakeDirection = UP         if keydown(40) and snakeDirection <> UP  snakeDirection = DOWN         if keydown(37) and snakeDirection <> RIGHT  snakeDirection = LEFT         if keydown(39) and snakeDirection <> LEFT  snakeDirection = RIGHT             speedCounter = speedCounter - 1         if speedCounter = 0             prev = snakeHead             if snakeDirection > 0  snakeHead = (snakeHead + 1)%SNAKE_MAX_LENGTH             speedCounter = speed             if snakeDirection = UP                 snake[snakeHead][0] = snake[prev][0]                 snake[snakeHead][1] = snake[prev][1] - 1             elseif snakeDirection = DOWN                 snake[snakeHead][0] = snake[prev][0]                 snake[snakeHead][1] = snake[prev][1] + 1             elseif snakeDirection = LEFT                 snake[snakeHead][0] = snake[prev][0] - 1                 snake[snakeHead][1] = snake[prev][1]             elseif snakeDirection = RIGHT                 snake[snakeHead][0] = snake[prev][0] + 1                 snake[snakeHead][1] = snake[prev][1]             endif             x = snake[snakeHead][0]             y = snake[snakeHead][1]             if x < 0 or x >= 40 or y < 0 or y >= 30                 gameOver = true             else                 if level[x][y] > 0                     snakeLength = snakeLength + 1                     if level[x][y] = 2  speed = max(speed - 1, 0)                     level[x][y] = 0                 endif             endif         endif         set color 0, 0, 0         cls         for y = 0 to 29             for x = 0 to 39                 if level[x][y] = 1                     set color 0, 255, 0                     draw rect x*8, y*8, 8, 8 , true                 elseif level[x][y] = 2                     set color 255, 0, 0                     draw rect x*8, y*8, 8, 8, true                 endif             next         next         set color 255, 255, 255         set caret 0, 0         x = snake[snakeHead][0]         y = snake[snakeHead][1]         for i = snakeHead to snakeHead - snakeLength + 1             j = i             if j < 0 then j = j + SNAKE_MAX_LENGTH             draw rect snake[j][0]*8, snake[j][1]*8, 8, 8, true             if i <> snakeHead                 if snake[j][0] = x and snake[j][1] = y then gameOver = true             endif         next         wait 10         redraw     until gameOver loop```
I'll see if I can understand the code where the body follows the head, thank you.

I barely looked at the code. But I believe the snake "moves" through the 'snake' array. Every element in the array contains a position (x and y value). The snake's head is a moving index in the array. Every time the snake moves one step, the head index increases and a new position is added to the array. That way, the tail is always present as earlier indexes in the array. So if the length of the snake is 4, the positions drawn are those at snake[snakeHead], snake[snakeHead - 1] .. snake[snakeHead - 3].

Edit: The % operator is used to keep the indexes within the array size. When the snake head index reaches the end of the array it starts over at 0. The length of the array is exactly enough for the snake to cover the entire screen

You can probably write smarter code that just stores the turns that the snake does or something. But that would require more complicated code ... I think
I don't understand the code very well, so I have prepared a small example to use as a basis for testing.

In the example I have the player who is the head of the snake and I have the body which is the tail, the player moves with the keys and the body I have added to a list and I show three bodies at the moment. How do I make the body is in the player's position and moves with him like the tail of the snake.

Code:
```'prueba de cola de serpiente 'variables----------------------- visible player,list_body set window "serpiente",640,480,false set redraw off 'player----------------------------- function Player()     obj = []     obj.radius = 14     obj.x = 320 - obj.radius/2     obj.y = 240 - obj.radius/2     obj.speedX = 0     obj.speedY = 0     obj.Active = true         obj.update = function()         if this.Active = true             this.move()             this.Draw()         endif     endfunc         obj.Draw = function()         set color 255,204,0         draw ellipse this.x,this.y,this.radius,this.radius,true     endfunc         obj.move = function()        if keydown(KEY_RIGHT,false)         this.speedX = 2         this.speedY = 0        endif           if keydown(KEY_LEFT,false)         this.speedX = -2         this.speedY = 0           endif                 if keydown(KEY_UP,false)             this.speedX = 0             this.speedY = -2         endif         if keydown(KEY_DOWN,false)             this.speedX = 0             this.speedY = 2         endif                 this.x = this.x + this.speedX         this.y = this.y + this.speedY     endfunc         return obj endfunc 'end player-------------------------- 'body-------------------------------- function Body(x,y)     obj = []     obj.radius = 10     obj.x = x - obj.radius/2     obj.y = y - obj.radius/2         obj.update = function()         this.Draw()     endfunc         obj.Draw = function()         set color 255,0,204         draw ellipse this.x,this.y,this.radius,this.radius,true     endfunc         return obj endfunc 'end body---------------------------- 'iniciar variables------------------- player = Player() list_body = [] list_body[sizeof(list_body)] = Body(320,64) list_body[sizeof(list_body)] = Body(320-32,64) list_body[sizeof(list_body)] = Body(320-64,64) while not keydown(KEY_ESCAPE,true)     set color 0,0,0     cls         'actualizar objetos del juego-----------     player.update()     if sizeof(list_body)         for i = 0 to sizeof(list_body)-1             list_body[i].update()         next     endif     '---------------------------------------             fwait 60     redraw wend```