Как исправить удвоение координат? - PullRequest
1 голос
/ 31 марта 2020

В настоящее время я делаю Snake в Pygame. Моя идея сделать так, чтобы я росла, заключалась в том, что я буду составлять список всех его позиций, и всякий раз, когда он ест яблоко, я добавляю еще одну pygame.Surface и перетаскиваю его по координатам за последней позицией. Я столкнулся со странной ошибкой, которая делает змею go в два раза быстрее, чем раньше. Вы можете помочь мне? Это мой код:

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')
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 remove_duplicates(listy):
    new_listy = []
    for item in listy:
        if item not in new_listy:
            new_listy.append(item)
    return new_listy

def move():
    global x,y
    if dirUp:
        y -= dy
    elif dirDown:
        y += dy
    elif dirRight:
        x += dx
    elif dirLeft:
        x -= dx

clock = pygame.time.Clock()

while running:
    clock.tick(10)
    screen.fill((0,128,0))

    body[0] = (x,y)

    snakeImg = [pygame.image.load('snakeblock.png') 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

    for i in 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,pos[-2])

        move()

        pos.append((x,y))
        screen.blit(food, (foodx, foody))
        screen.blit(snakeImg[i], (body[i][0], body[i][1]))
    pos = remove_duplicates(pos)
    show_text()
    pygame.display.update()

Ответы [ 2 ]

2 голосов
/ 31 марта 2020

Существуют и другие проблемы, с которыми вы столкнетесь в своем коде, например, не проверка на столкновение ребер и столкновение блоков змей. Но вот отправная точка.

Ваша проблема заключалась в том, что вы перемещали начальный блок несколько раз для каждого 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()
1 голос
/ 31 марта 2020

Чтобы другие знали, как сделать змею в стене sh и себя:

if body[0][0] > 608 or body[0][0] < 0:
        running = False
    elif body[0][1] > 608 or body[0][1] < 0:
        running = False
[...]

for i in range(len(body)):
        if body[0] in body[1:]:
            running = False
...