Столкновение границ работает только один раз в pygame

#python #pygame

#python #pygame

Вопрос:

Я создаю игру snake на python, и я почти закончил, но я изо всех сил пытаюсь решить проблему. В основном классе в методе collision я написал некоторый код для обнаружения столкновения snake с границами экрана, и если утверждение верно, snake вернется в исходное состояние. Однако, когда я запускаю программу, обнаружение столкновений срабатывает только один раз. После этого змея может просто исчезнуть с экрана. Заранее спасибо.

 import pygame
import random
pygame.init()

clock = pygame.time.Clock()

# Screen setup
screen_width = 600
screen_height = 600

screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("Snake")

cellSize = 20

# Colors
black = (0, 0, 0)
white = (255, 255, 255)
blue = (255, 0, 0)
green = (0, 0, 255)

# Grid
def draw_grid():
    # Vertical lines
    for x in range(0, screen_height, cellSize):
        pygame.draw.line(screen, white, (x, 0), (x, screen_height))

    # Horizontal lines
    for y in range(0, screen_width, cellSize):
        pygame.draw.line(screen, white, (0, y), (screen_width, y))

# Maze
class MAZE:
    def __init__(self):
        self.rect_width = 20
        self.rect_height = 20
        self.rects = []

    def draw_rects(self):
        # Drawing Maze
        pass


# Snake
class SNAKE(MAZE):
    def __init__(self):
        super().__init__()
        self.width = 20
        self.height = 20
        self.speed = 20
        self.initBody = [[3 * cellSize, 40], [4 * cellSize, 40], [5 * cellSize, 40]]
        self.body = [[3 * cellSize, 40], [4 * cellSize, 40], [5 * cellSize, 40]]
        self.rects = []
        self.move = [0, 0]
        self.grow = False

    def draw_snake(self):
        # Drawing snake body
        for cor in self.body:
            snake_rect = pygame.Rect(cor[0], cor[1], self.width, self.height)
            self.rects.append(snake_rect)
            pygame.draw.rect(screen, blue, snake_rect)

    def move_snake(self):
        # Key bindings
        key = pygame.key.get_pressed()

        if key[pygame.K_UP]:
            self.move = [0, -1]

        if key[pygame.K_DOWN]:
            self.move = [0, 1]

        if key[pygame.K_LEFT]:
            self.move = [-1, 0]

        if key[pygame.K_RIGHT]:
            self.move = [1, 0]

        if self.move[0] != 0 or self.move[1] != 0:
            # Adding rects to the end of snake body
            new_rect = self.body[-1][:]
            new_rect[0]  = self.move[0] * cellSize
            new_rect[1]  = self.move[1] * cellSize
            self.body.append(new_rect)
            # Removing rects from tail
            if self.grow == False:
                self.body.pop(0)

        self.grow = False

# Food
class FOOD_1:
    def __init__(self):
        self.width = 20
        self.height = 20
        self.x = 4 * cellSize
        self.y = 4 * cellSize
        self.food_rect = pygame.Rect(self.x, self.y, self.width, self.height)
    def draw_food_1(self):
        pygame.draw.rect(screen, green, self.food_rect)


maze = MAZE()
snake = SNAKE()
food_1 = FOOD_1()

class MAIN():
    def __init__(self):
        self.maze = MAZE()
        self.snake = SNAKE()
        self.food_1 = FOOD_1()
    def draw(self):
        self.maze.draw_rects()
        self.snake.draw_snake()
        self.food_1.draw_food_1()
    def move(self):
        self.snake.move_snake()
    def collision(self):
        # Snake and food collision
        for rect in self.snake.rects:
            if rect.colliderect(self.food_1.food_rect):
                self.food_1.x = random.randint(0, 29) * cellSize
                self.food_1.y = random.randint(0, 29) * cellSize
                self.food_1.food_rect.topleft = (self.food_1.x, self.food_1.y)
                self.snake.grow = True
        # Border collisions
        if self.snake.body[-1][0] <= 0:
            self.snake.body = self.snake.initBody
        elif self.snake.body[-1][0] >= 600:
            self.snake.body = self.snake.initBody
        elif self.snake.body[-1][1] <= 0:
            self.snake.body = self.snake.initBody
        elif self.snake.body[-1][1] >= 600:
            self.snake.body = self.snake.initBody

main = MAIN()

# Main loop
run = True
while run:

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    # Drawing on screen
    screen.fill(black)
    main.draw()
    draw_grid()

    # Movement and Collisions
    main.move()
    main.collision()

    pygame.display.flip()
    clock.tick(10)

pygame.quit()
 

Ответ №1:

Когда вы это делаете self.snake.body = self.snake.initBody , вы не создаете копию initBody , вы определяете body как тот же объект, initBody что и , поэтому, когда вы изменяете один, другой тоже изменяется … что происходит во время игры.

Таким образом, после первого столкновения initBody они изменяются одновременно body (поскольку они стали одним и тем же), поэтому, когда происходит еще одно столкновение, линия self.snake.body = self.snake.initBody ничего не делает.

Вам нужно заменить его на self.snake.body = self.snake.initBody.copy() такой, чтобы оригинал initBody остался нетронутым.

Комментарии:

1. Кроме того, общее замечание: всякий раз, когда вы копируете и вставляете фрагмент кода несколько раз, вы должны спросить себя: «Разве я не должен создавать метод / функцию для этого?». Иногда ответ может быть отрицательным, но поскольку вы собираетесь исправить 4 идентичные строки кода, вы, вероятно, понимаете, почему было бы неплохо определить reset_body(self) метод 😉

Ответ №2:

Лучше бы вы создали такой код в своем цикле.

 if playerx = 0:
   playerx = 0
if playerx = 600:
   playerx = 600:
 

Используйте тот же метод и для оси y.