Существуют и другие проблемы, с которыми вы столкнетесь в своем коде, например, не проверка на столкновение ребер и столкновение блоков змей. Но вот отправная точка.
Ваша проблема заключалась в том, что вы перемещали начальный блок несколько раз для каждого l oop всякий раз, когда у вас было более одного блока.
Вот полный код с комментариями.
import pygame, math, random
pygame.init()
screen = pygame.display.set_mode((640,640))
pygame.display.set_caption('Snake')
score = 0
x, y = 320,320
dx,dy = 32,32
running = True
dirUp, dirDown = False, False
dirLeft, dirRight = False, True
body = [(x,y)]
pos = []
squares = []
for i in range(640):
if i % 32 == 0:
squares.append(i)
food = pygame.image.load('fruit.png')
food = pygame.transform.scale(food, (32,32))
foodx,foody = random.choice(squares), random.choice(squares)
def isCollision(obsX, obsY, x, y):
return math.sqrt(math.pow(obsX - x, 2) + math.pow(obsY - y, 2)) <= 0
def show_text():
score_font = pygame.font.Font('freesansbold.ttf',32)
score_text = score_font.render('Score: {}'.format(score), True, (255,255,255))
screen.blit(score_text, (0,0))
def move(x, y):
# I changed this function to take arguments and return
# values rather than set globals which is generally bad practice
if dirUp:
y -= dy
elif dirDown:
y += dy
elif dirRight:
x += dx
elif dirLeft:
x -= dx
return x, y
clock = pygame.time.Clock()
while running:
clock.tick(10)
screen.fill((0,128,0))
snakeImg = [pygame.transform.scale(pygame.image.load('snakeblock.png'), (32,32)) for i in range(len(body))]
if x > 608 or x < 0:
running = False
elif y > 608 or y < 0:
running = False
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
dirUp = True
dirLeft = dirDown = dirRight = False
if event.key == pygame.K_DOWN:
dirDown = True
dirUp = dirLeft = dirRight = False
if event.key == pygame.K_RIGHT:
dirRight = True
dirUp = dirDown = dirLeft = False
if event.key == pygame.K_LEFT:
dirLeft = True
dirUp = dirDown = dirRight = False
# this for loop is reversed because you only need to move your first block
# the rest of the blocks can just follow the pattern of the previously
# placed blocks
for i in reversed(range(len(body))):
if isCollision(foodx,foody,body[i][0],body[i][1]):
foodx, foody = random.choice(squares), random.choice(squares)
score += 1
body.insert(0, move(body[i][0], body[i][1]))
elif i == 0:
# Here you only move your first block or element
body[i] = move(body[i][0], body[i][1])
else:
# otherwise you can just place the current element
# at the position of the previous element
body[i] = body[i - 1]
screen.blit(food, (foodx, foody))
screen.blit(snakeImg[i], (body[i][0], body[i][1]))
show_text()
pygame.display.update()