0

I want to design a snake game with smoother movement than others, using the pygame library. My issue does not concern the movement part - I have been able to move the snake, but this came at the cost of 2 FPS and changing the speed to TILE_SIZE, creating an effect of lag/choppiness which I don't like. Is there a solution, such that I can move the snake more often in smaller intervals to create smoother movement? I know about LERP / interpolation but I am not too sure how to use it / if this is the best solution. Thanks

import pygame as pg
import random

# Initialising
pg.init()

# Creating screen
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 800
screen = pg.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))

# Creating clock
clock = pg.time.Clock()
fps = 60

# Creating game variables
TILE_SIZE = 40
right = left = down = up = False

# Colours
black = (0, 0, 0)


class Snake(pg.sprite.Sprite):
    def __init__(self, x, y):
        super().__init__()
        self.body = [[x, y]]
        self.length = len(self.body)

        self.direction = pg.math.Vector2()
        self.speed = TILE_SIZE // 5

    def update(self):
        # Movement
        self.direction.x = 1 if right else -1 if left else 0
        self.direction.y = 1 if down else -1 if up else 0

        self.body[0][0] += self.speed * self.direction.x
        self.body[0][1] += self.speed * self.direction.y

    def draw(self):
        pg.draw.rect(screen, "green", (self.body[0][0], self.body[0][1], TILE_SIZE, TILE_SIZE))


# Creating snake at a random tile starting point
snake = Snake(random.randrange(0, SCREEN_WIDTH, TILE_SIZE), (random.randrange(0, SCREEN_WIDTH, TILE_SIZE)))

running = True
while running:
    # Set frame rate
    clock.tick(fps)
    # Fill screen
    screen.fill("beige")
    # Draw grid
    for i in range(0, SCREEN_WIDTH, TILE_SIZE):
        pg.draw.line(screen, black, (i, 0), (i, SCREEN_HEIGHT))
    for i in range(0, SCREEN_HEIGHT, TILE_SIZE):
        pg.draw.line(screen, black, (0, i), (SCREEN_WIDTH, i))
    # Draw snake
    snake.update()
    snake.draw()

    for e in pg.event.get():
        if e.type == pg.QUIT:
            running = False

    keys = pg.key.get_pressed()
    if (keys[pg.K_RIGHT] or keys[pg.K_d]) and not left:
        right = True
        left = down = up = False
    if (keys[pg.K_LEFT] or keys[pg.K_a]) and not right:
        left = True
        right = down = up = False
    if (keys[pg.K_DOWN] or keys[pg.K_s]) and not up:
        down = True
        right = left = up = False
    if (keys[pg.K_UP] or keys[pg.K_w]) and not down:
        up = True
        right = left = down = False

    pg.display.update()
  • Could you attach your code? – Jerry Aug 25 '22 at 18:33
  • Please show your code so others could have better judgment. – Jobo Fernandez Aug 25 '22 at 22:33
  • Please [edit] your question to include a [mre]. If you're concerned about speed, you should [profile](https://stackoverflow.com/a/582337/2280890) your code to see which portions are taking too long. A common mistake for newcomers is loading images every game loop instead of at the beginning. – import random Aug 26 '22 at 00:48
  • This is very vague, do you just want to know if you should separate draw and update loops ? Short answer is "Yes" but mostly for code readability. Most likely it won't affect the performances nor the smoothness of your animations. If your game is laggy it must come from an other part of your code, please provide some code, better yet try to extract a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) as @importrandom suggested. – Anto Aug 26 '22 at 06:56
  • I have added my code to show what I am talking about. At the moment, if I want smooth snake movement, I have no way of binding the snake to the grid. It can move freely in any x and y, rather than just increments of TILE_SIZE. –  Aug 26 '22 at 15:03

1 Answers1

0

Solved - I decided to only change the snake's direction when the snake is inside the grid pattern (using MOD operator %) -

if self.rect.topleft[0] % TILE_SIZE == 0 and self.rect.topleft[1] % TILE_SIZE == 0:
    # change direction