How do I get the snake to grow and chain the movement of the snake's body?
Как мне заставить змею расти и упорядочить движение тела змеи?
Я хочу реализовать игру со змеями. Змея бродит по игровой площадке. Каждый раз, когда змея ест какую-нибудь еду, длина змеи увеличивается на один элемент. Элементы тела змеи следуют за ее головой, как цепочка.
Как мне добиться, чтобы части тела следовали за головой змеи на ее пути, когда голова змеи движется вперед?
Переведено автоматически
Ответ 1
В общем, вы должны различать 2 разных типа змеи. В первом случае змея перемещается по сетке, и каждый раз, когда змея перемещается, она продвигается на одно поле в сетке. В другом типе позиция змеи не находится в растре и не привязана к полям сетки, позиция свободна, и змея плавно скользит по полям. В первом случае каждый элемент тела привязан к полям сетки, как и голова. В другом больше хитрости, потому что положение элемента body зависит от размера элемента и динамических предыдущих положений головы змеи.
Сначала змея, которая привязана к сетке.
Элементы snake могут храниться в списке кортежей. Каждый кортеж содержит столбец и строку элемента snakes в сетке. Изменения элементов в списке непосредственно следуют за движением змеи. Если змея перемещается, новая позиция добавляется в начало списка, а конец списка удаляется.
Например, у нас есть змея со следующими элементами:
body = [(3, 3), (3, 4), (4, 4), (5, 4), (6, 4)]
Когда голова змеи перемещается из формы (3, 3) в (3, 2), новая позиция головы добавляется в начало списка (body.insert(0, (3, 2)):
length = 1 body = [(COLUMNS//2, ROWS//2)] dir = (1, 0) food = random_pos(body)
run = True while run: clock.tick(5) for event in pygame.event.get(): if event.type == pygame.QUIT: run = False if event.type == pygame.KEYDOWN: if event.key == pygame.K_LEFT: dir = (-1, 0) elif event.key == pygame.K_RIGHT: dir = (1, 0) elif event.key == pygame.K_UP: dir = (0, -1) elif event.key == pygame.K_DOWN: dir = (0, 1)
screen.blit(background, (0, 0)) pygame.draw.rect(screen, (255, 0, 255), (food[0]*SIZE, food[1]*SIZE, SIZE, SIZE)) for i, pos inenumerate(body): color = (255, 0, 0) if i==0else (0, 192, 0) if (i%2)==0else (255, 128, 0) pygame.draw.rect(screen, color, (pos[0]*SIZE, pos[1]*SIZE, SIZE, SIZE)) pygame.display.flip()
Теперь змея с полностью свободным позиционированием.
Мы должны отслеживать все позиции, которые посетила голова змеи, в списке. Мы должны разместить элементы тела змеи на позициях в списке, как жемчужины цепочки.
Ключ в том, чтобы вычислить евклидово расстояние между последним элементом тела в цепочке и следующими позициями на дорожке. Когда найдена новая точка с достаточно большим расстоянием, в цепочку (тело) добавляется новая жемчужина (элемент).
dx, dy = body[-1][0]-pos[0], body[-1][1]-pos[1] if math.sqrt(dx*dx + dy*dy) >= distance: body.append(pos)
Следующая функция имеет 3 аргумента. track это список положений головы. no_pearls тогда это количество элементов тела shakes и distance это евклидово расстояние между элементами. Функция создает и возвращает список положений тела змеи.
defcreate_body(track, no_pearls, distance): body = [(track[0])] track_i = 1 for i inrange(1, no_pearls): while track_i < len(track): pos = track[track_i] track_i += 1 dx, dy = body[-1][0]-pos[0], body[-1][1]-pos[1] if math.sqrt(dx*dx + dy*dy) >= distance: body.append(pos) break whilelen(body) < no_pearls: body.append(track[-1]) del track[track_i:] return body
run = True while run: clock.tick(60) for event in pygame.event.get(): if event.type == pygame.QUIT: run = False if event.type == pygame.KEYDOWN: if event.key == pygame.K_LEFT: dir = (-1, 0) elif event.key == pygame.K_RIGHT: dir = (1, 0) elif event.key == pygame.K_UP: dir = (0, -1) elif event.key == pygame.K_DOWN: dir = (0, 1)