蛇的身体没有正确地附在蛇身上

2024-04-19 00:07:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我终于想出了如何给我的蛇添加身体部位,但它们以一种不同寻常的方式添加。我已经为此奋斗了一段时间,终于成功了。但他们做得不对。看起来他们在后面附加了1个像素,而不是整个身体的长度。有人知道为什么吗

# Constants
WIN_WIDTH = 500
WIN_HEIGHT = 600
HALF_WIN_WIDTH = WIN_WIDTH / 2
HALF_WIN_HEIGHT = WIN_HEIGHT / 2
FPS = 10

# Colors
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
DARK_GREEN = (0, 100, 0)
YELLOW = (255, 255, 0)

# Variables
screen = pygame.display.set_mode((WIN_WIDTH, WIN_HEIGHT))
pygame.display.set_caption("Snake")
clock = pygame.time.Clock()
running = True


class Text:

    def __init__(self, x, y, size, font, color, text):
        self.x = x
        self.y = y
        self.size = size
        self.font = font
        self.color = color
        self.text = text

    def draw(self):
        self.my_font = pygame.font.SysFont(self.font, self.size)
        self.text_surface = self.my_font.render(self.text, True, self.color)
        screen.blit(self.text_surface, (self.x, self.y))


class Food:

    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.width = 25
        self.height = 25

    def draw(self):
        self.rect = (self.x, self.y, self.width, self.height)
        pygame.draw.rect(screen, BLUE, self.rect)

    def events(self):
        pass

    def update(self):
        pass


class Body:

    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.width = 25
        self.height = 25

    def draw(self):
        self.rect = pygame.Rect(self.x, self.y, self.width, self.height)
        pygame.draw.rect(screen, YELLOW, self.rect)


# Snake class
class Snake:

    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.width = 25
        self.height = 25
        self.direction = 1
        self.kill = False
        self.collide = False
        self.speed = 3
        self.score = 0
        self.bodies = []

    def draw(self):
        self.rect = pygame.Rect(self.x, self.y, self.width, self.height)
        pygame.draw.rect(screen, BLACK, self.rect)

    def events(self):
        # change direction on key press
        self.keys = pygame.key.get_pressed()

        if self.keys[pygame.K_UP] and self.direction != 3:
            self.direction = 1
        if self.keys[pygame.K_DOWN] and self.direction != 1:
            self.direction = 3
        if self.keys[pygame.K_LEFT] and self.direction != 2:
            self.direction = 4
        if self.keys[pygame.K_RIGHT] and self.direction != 4:
            self.direction = 2

        if self.rect.colliderect(food.rect):
            self.speed += 0.5
            food.x = random.randint(0, WIN_WIDTH)
            food.y = random.randint(0, WIN_HEIGHT)
            self.score += 5
            self.colliide = False
            self.bodies.append(Body(0, 0))

        # Move the end bodies first in reverse order
        for i in range(len(self.bodies)-1, 0, -1):
            x = snake.bodies[i-1].x
            y = snake.bodies[i-1].y
            snake.bodies[i].x = x
            snake.bodies[i].y = y
            snake.bodies[i].draw()

        # Move body 0 to where the head is
        if len(snake.bodies) > 0:
            x = snake.x
            y = snake.y
            snake.bodies[0].x = x
            snake.bodies[0].y = y
            snake.bodies[0].draw()


    def update(self):
        # move
        if self.direction == 1:
            self.y -= self.speed
        if self.direction == 2:
            self.x += self.speed
        if self.direction == 3:
            self.y += self.speed
        if self.direction == 4:
            self.x -= self.speed

        # if on edge of screen
        if self.rect.right > WIN_WIDTH:
            self.kill = True
        if self.x < 0:
            self.kill = True
        if self.y < 0:
            self.kill = True
        if self.rect.bottom > WIN_HEIGHT:
            self.kill = True


# Create the snake object
snake = Snake(HALF_WIN_WIDTH, HALF_WIN_HEIGHT)
food = Food(random.randint(0, WIN_WIDTH), random.randint(0, WIN_HEIGHT))

# Main Loop
while running:
    score_text = Text(220, 5, 40, 'arial', WHITE, f'Score: {snake.score}')
    # Draw
    screen.fill(DARK_GREEN)
    snake.draw()
    food.draw()
    score_text.draw()

    # Event handling
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

    if snake.kill:
        running = False

    snake.events()

    # Update
    snake.update()
    food.update()
    clock.tick(60)
    pygame.display.update()

多谢各位


Tags: textrectselfifdefwidthscreenpygame
1条回答
网友
1楼 · 发布于 2024-04-19 00:07:54

你必须追踪蛇遇到的位置。将列表属性self.position添加到类Snake

class Snake:

    def __init__(self, x, y):
        # [...]

        self.positions = [(self.x, self.y)]

    # [...]

当蛇移动时,将新位置添加到列表中:

class Snake:
    # [...]

    def update(self):

        # move
        if self.direction == 1:
            self.y -= self.speed
        if self.direction == 2:
            self.x += self.speed
        if self.direction == 3:
            self.y += self.speed
        if self.direction == 4:
            self.x -= self.speed

        # add ne position
        if self.x != self.positions[0][0] or self.y != self.positions[0][1]:
            self.positions.insert(0, (self.x, self.y))

沿events中存储的位置更新主体的xy坐标。定义车身各部分之间的距离(例如35)。并使用方法getPos通过其索引获取零件的位置:

class Snake:
    # [...]

    def events(self):
        # change direction on key press
        self.keys = pygame.key.get_pressed()

        if self.keys[pygame.K_UP] and self.direction != 3:
            self.direction = 1
        if self.keys[pygame.K_DOWN] and self.direction != 1:
            self.direction = 3
        if self.keys[pygame.K_LEFT] and self.direction != 2:
            self.direction = 4
        if self.keys[pygame.K_RIGHT] and self.direction != 4:
            self.direction = 2

        if self.rect.colliderect(food.rect):
            self.speed += 0.5
            food.x = random.randint(100, WIN_WIDTH - 125)
            food.y = random.randint(150, WIN_HEIGHT - 175)
            self.score += 5
            self.colliide = False
            self.bodies.append(Body(0, 0))

        # Move the end bodies first in reverse order
        for i in range(len(self.bodies)):
            pos = self.getPos(i+1, 35, i == len(self.bodies)-1)
            snake.bodies[i].x = pos[0]
            snake.bodies[i].y = pos[1]
            snake.bodies[i].draw()

方法getPos的参数是主体部分的索引、部分与delToEnd之间的距离delToEnd当主体的最后一部分为get并指示可以删除列表末尾“位于”蛇的最后一部分后面的位置时,变为true:

class Snake:
    # [...]

    def getPos(self, i, dist, delToEnd):
        lenToI = i * dist
        lenAct = 0
        px, py = self.positions[-1]
        for j in range(len(self.positions)-1):
            px, py = self.positions[j]
            pnx, pny = self.positions[j+1]
            delta = math.sqrt((px-pnx)*(px-pnx) + (py-pny)*(py-pny))
            lenAct += delta
            if lenAct >= lenToI:
                w = (lenAct - lenToI) / delta
                px = pnx - (pnx-px) * w
                py = pny - (pny-py) * w
                if delToEnd:
                    del self.positions[j:]
                break
        return (round(px), round(py))

相关问题 更多 >