pygame.Rect.move_ip()无法更新rect属性

时间:2019-03-07 05:00:10

标签: python pygame

我正在pygame中创建一个蛇克隆,目前正在管理蛇的转向机制及其运动。我在打开pygame时创建了一个点,然后将其存储在snake.pos_at_turn中。之后,我调整每个蛇段的方向,应该移动直到其x或y坐标等于snake.pos_at_turn的坐标,然后再次更改其方向。问题在于,由于某种原因,蛇形段完全没有移动。任何帮助将不胜感激!

蛇对象和事件循环的代码:

import pygame,sys,random
from pygame.locals import *

pygame.init()

WINDOW_HEIGHT = 500
WINDOW_WIDTH = 500

RECTANGLE_HEIGHT = 20
RECTANGLE_WIDTH = 20

GREEN = (0,255,0)
WHITE = (255,255,255)
BLACK = (0,0,0)
RED = (255,0,0)

clock = pygame.time.Clock()
SCREEN = pygame.display.set_mode((WINDOW_WIDTH,WINDOW_HEIGHT))
pygame.display.set_caption("Snake")

class Snake(object):
    def __init__(self, color, width, height):
        self.body = []
        self.image = pygame.Surface((width,height))
        self.image.fill(GREEN)
        self.rect = self.image.get_rect()
        self.speed = 20 
        self.direction = 'right'
        self.living = True
        self.move = (0,0)
        self.pos_at_turn = [0,0]

    def movement(self):
        if self.direction == 'right':
            self.move = (self.speed,0)
        elif self.direction == 'left':
            self.move = (-self.speed,0)
        elif self.direction == 'up':
            self.move = (0,-self.speed)
        elif self.direction == 'down':
            self.move = (0,self.speed)

        self.rect.move_ip(self.move)
        self.rect.clamp_ip(SCREEN.get_rect())

    def blit(self):
        SCREEN.blit(self.image,self.rect)

    def update(self,food):
        self.movement()
        self.add_segment(food)
        self.draw_snake()
        for snake_segment in self.body:
            print(snake_segment.rect)

    def add_segment(self,food):
        snake_segment = Snake(GREEN,RECTANGLE_WIDTH,RECTANGLE_HEIGHT)

        if len(self.body) == 0:
            self.body.append(snake_segment)

        if self.rect.colliderect(food.rect):
            self.body.append(snake_segment)

    def draw_snake(self):
        for snake_segment in self.body:
            if self.body.index(snake_segment) == 0:
                self.blit()
            else:
                # original movement code:

                # if self.direction == 'right':
                #     snake_segment.rect.x = self.rect.x - RECTANGLE_WIDTH * self.body.index(snake_segment)
                #     snake_segment.rect.y = self.rect.y
                #     snake_segment.blit()
                # elif self.direction == 'left':
                #     snake_segment.rect.x = self.rect.x + RECTANGLE_WIDTH * self.body.index(snake_segment)
                #     snake_segment.rect.y = self.rect.y
                #     snake_segment.blit()
                # elif self.direction == 'up':
                #     snake_segment.rect.x = self.rect.x
                #     snake_segment.rect.y = self.rect.y + RECTANGLE_HEIGHT * self.body.index(snake_segment)
                #     snake_segment.blit()
                # elif self.direction == 'down':
                #     snake_segment.rect.x = self.rect.x
                #     snake_segment.rect.y = self.rect.y - RECTANGLE_HEIGHT * self.body.index(snake_segment)
                #     snake_segment.blit()

                if self.direction == 'right':
                    if snake_segment.rect.y >= self.pos_at_turn[1]:
                        snake_segment.direction = 'down'
                    elif snake_segment.rect.y <= self.pos_at_turn[1]:
                        snake_segment.direction = 'up'

                    if snake_segment.rect.y == self.pos_at_turn[1]:
                        if snake_segment.rect.x >= self.pos_at_turn[0]:
                            snake_segment.direction = 'left'
                        elif snake_segment.rect.x <= self.pos_at_turn[0]:
                            snake_segment.direction = 'right'

                    snake_segment.blit()
                elif self.direction == 'left':
                    if snake_segment.rect.y >= self.pos_at_turn[1]:
                        snake_segment.direction = 'down'
                    elif snake_segment.rect.y <= self.pos_at_turn[1]:
                        snake_segment.direction = 'up'

                    if snake_segment.rect.y == self.pos_at_turn[1]:
                        if snake_segment.rect.x >= self.pos_at_turn[0]:
                            snake_segment.direction = 'left'
                        elif snake_segment.rect.x <= self.pos_at_turn[0]:
                            snake_segment.direction = 'right'
                    snake_segment.blit()

                elif self.direction == 'up':
                    if snake_segment.rect.x >= self.pos_at_turn[0]:
                        snake_segment.direction = 'left'
                    elif snake_segment.rect.x <= self.pos_at_turn[0]:
                        snake_segment.direction = 'right'

                    if snake_segment.rect.x == self.pos_at_turn[0]:
                        if snake_segment.rect.y >= self.pos_at_turn[1]:
                            snake_segment.direction = 'down'
                        elif snake_segment.rect.y <= self.pos_at_turn[1]:
                            snake_segment.direction = 'up'
                    snake_segment.blit()

                elif self.direction == 'down':
                    if snake_segment.rect.x >= self.pos_at_turn[0]:
                        snake_segment.direction = 'left'
                    elif snake_segment.rect.x <= self.pos_at_turn[0]:
                        snake_segment.direction = 'right'

                    if snake_segment.rect.x == self.pos_at_turn[0]:
                        if snake_segment.rect.y >= self.pos_at_turn[1]:
                            snake_segment.direction = 'down'
                        elif snake_segment.rect.y <= self.pos_at_turn[1]:
                            snake_segment.direction = 'up'
                    snake_segment.blit()


class Food(object):
    def __init__(self,color,width,height):
        self.image = pygame.Surface((width,height))
        self.image.fill(RED)
        self.rect = self.image.get_rect()
        self.rect.x = random.randrange(20,500,20) 
        self.rect.y = random.randrange(20,500,20) 
        self.state = 'uneaten'

    def check_eaten(self,snake):
        if snake.rect.colliderect(self.rect):
            self.state = 'eaten'

    def blit(self):
        SCREEN.blit(self.image,self.rect)

    def update_state(self,snake):
        self.check_eaten(snake)
        if self.state == 'uneaten':
            self.blit()
        elif self.state == 'eaten':
            self.rect.x = random.randrange(0,500,20) 
            self.rect.y = random.randrange(0,500,20) 

            if self.rect.x == snake.rect.x or self.rect.x == snake.rect.y:
                self.rect.x = random.randrange(0,500,20) 
                self.rect.y = random.randrange(0,500,20)

            self.blit()
            self.state = 'uneaten'

    def update(self,snake):
        self.update_state(snake)

def event_loop(snake,food):
    while True:
        SCREEN.fill(BLACK)

        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == KEYDOWN:
                snake.pos_at_turn = [snake.rect.x, snake.rect.y]
                if event.key == K_RIGHT:
                    snake.direction = 'right'
                elif event.key == K_LEFT:
                    snake.direction = 'left'
                elif event.key == K_UP:
                    snake.direction = 'up'
                elif event.key == K_DOWN:
                    snake.direction = 'down'

        snake.update(food)
        food.update(snake)

        pygame.display.update()
        clock.tick(5)

SNAKE = Snake(GREEN,RECTANGLE_WIDTH,RECTANGLE_HEIGHT)
FOOD = Food(RED,RECTANGLE_WIDTH,RECTANGLE_HEIGHT)
event_loop(SNAKE,FOOD)

1 个答案:

答案 0 :(得分:1)

您必须按照方法movement以相反的顺序穿过蛇的身体。对于身体的每个部位,复制上一个部位的位置。头部获取蛇的当前位置:

class Snake(object):
    # [...]

    def movement(self):
        if self.direction == 'right':
            self.move = (self.speed,0)
        elif self.direction == 'left':
            self.move = (-self.speed,0)
        elif self.direction == 'up':
            self.move = (0,-self.speed)
        elif self.direction == 'down':
            self.move = (0,self.speed)

        self.rect.move_ip(self.move)
        self.rect.clamp_ip(SCREEN.get_rect())

        for i in range(len(self.body)-1, 0, -1):
            self.body[i].rect.center = self.body[i-1].rect.center
        if self.body:
            self.body[0].rect.center = self.rect.center

在方法add_segment中将新零件添加到主体时,初始化零件的位置:

class Snake(object):
    # [...]

    def add_segment(self,food):
        if len(self.body) == 0 or self.rect.colliderect(food.rect):
            snake_segment = Snake(GREEN,RECTANGLE_WIDTH,RECTANGLE_HEIGHT)
            snake_segment.rect.center = self.rect.center
            self.body.append(snake_segment)

在方法draw_snake中,遍历身体的各个部分并“ blit”的每个部分就足够了:

class Snake(object):
    # [...]

    def draw_snake(self):
        for snake_segment in self.body:
            snake_segment.blit()