Pygame蛇与自己随机碰撞

问题描述 投票:0回答:1

我已经尝试从头开始创建Snake游戏,并且除了在蛇随机碰撞自身之前不会运行很长时间之外,它大部分都可以运行。

我已经尝试通过打印语句跟踪蛇在何处/何时与自身碰撞(必须是头部和第一段,因为我将碰撞设置为仅在头部位于其段之一的坐标内时才调用碰撞)。我还放置了一个网格,所以也许我可以看到两个部分重叠的地方,然后我以空白/速度玩而无济于事。

下面是所有代码。我很抱歉,因为我是一个初学者,因为我是编码的新手。如果您对我的清理方法也有一些建议,因为它很长,我也将不胜感激!

import pygame        #Import pygame and random
import random
import time
import sys

pygame.init()        #Initialize pygame

scrWdt = 500         #Set up screen width and height
scrHgt = 500

win = pygame.display.set_mode((scrWdt,scrHgt))  #Display window, set up globals
pygame.display.set_caption("Snek")

clock = pygame.time.Clock()

head_locs = [] #set global locations
seg_locs = {}
segs = []
apples = []
badApples = []

level = 1 #set game stats
eaten = 0
velocity = 20
margin = 2
seg_sizex = 20
seg_sizey = 20

red = (255, 0, 0)
pink = (255, 192, 203)
blue = (0, 0, 255)
lightblue = (173, 216, 230)
green = (173, 255, 47)
black = (0, 0, 0)
white = (255, 255, 255)

right = 1
down = 1
left = -1
up = -1

def rotate(sourcelist, appendlist): #rotates new locations into locations lists and filters out old locations
    if len(appendlist) >= 2:
        del appendlist[0]

    appendlist.append(sourcelist)

class player(object):
    def __init__(self, x, y, length):
        self.x = x
        self.y = y
        self.length = length
        self.xchange = right
        self.ychange = 0
        self.vel = velocity
        self.eatgood = False
        self.eatbad = False

    def head(self, win): #create head, save locations
        head = pygame.draw.rect(win, white, (self.x, self.y, 20, 20))
        current_head_loc = [self.x, self.y, self.xchange, self.ychange]
        rotate(current_head_loc, head_locs) #update head locations  

    def eatGood(self): #adds length
        self.eatgood = True
        seg_locs[self.length] = []
        self.length += 1

    def eatBad(self):
        self.eatbad = True
        if self.length > 1:
            del seg_locs[self.length-1]
        self.length -= 1

class Segment(object):
    def __init__(self, x, y, xchange, ychange):
        self.x = x
        self.y = y
        self.xchange = xchange
        self.ychange = ychange
        self.vel = velocity
        self.change = False

    def draw(self, i, win):
        new_stats = [self.x, self.y, self.xchange, self.ychange]

        if self.xchange == left or self.xchange == right: #Creates segment with margin
            self.x = self.x + (margin * -self.xchange)
        else:
            self.y = self.y + (margin * -self.ychange)

        current_list = seg_locs[i]
        rotate(new_stats, current_list)

        segment = pygame.draw.rect(win, white, (self.x, self.y, 20, 20))

class food(object):
    def __init__(self, x, y, radius=10):
        self.x = x
        self.y = y
        self.radius = radius

    def drawGood(self, win):
        pygame.draw.circle(win, green, (self.x, self.y), self.radius) #draw apples

    def drawBad(self, win):
        pygame.draw.circle(win, red, (self.x, self.y), self.radius) #draw bad apples

def redrawGameWindow():
    win.fill(black)
    pygame.draw.line(win, white, (0,40), (scrWdt,40), 2) #draw header bar
    length_text = font1.render('Length: ' + str(snake.length), 1, white)
    level_text = font2.render('Level: ' + str(level), 1, white)
    win.blit(length_text, (350, 10))
    win.blit(level_text, (20, 10))

    for i in range(40, scrHgt, 20): #draw grid
        pygame.draw.line(win, white, (0, i), (scrWdt, i), 1)
    for i in range(20, scrWdt, 20):
        pygame.draw.line(win, white, (i, 40), (i, scrHgt), 1) 

    snake.head(win)

    num_apps = level + (level-1) #number of apples per level
    num_bads = level + 1 #number of bad apples per level

    if len(apples) == 0:
        while len(apples) < num_apps:   #creates instances of food to match level
            apple = food(random.randint(10, 480), random.randint(40, 480)) #create random apple
            apples.append(apple) #add apple to apples list

    for apple in apples:  #draws good apples
        apple.drawGood(win)

    if level >= 2: #sets up bad apples
        while len(badApples) < num_bads:
            badApple = food(random.randint(10, 480), random.randint(60, 480))
            badApples.append(badApple)

    for bad in badApples: #draws bad apples
        bad.drawBad(win)

    for i in seg_locs.keys(): #create instance of segment to draw
        if i == 1:
            old_head_loc = head_locs[0][:]
            seg = Segment(*old_head_loc)
        else:
            old_seg_loc = seg_locs[i-1][0]
            seg = Segment(*old_seg_loc)

        seg.draw(i, win)
        segs.append(seg)
    if snake.length > 1:
        print("Head_locs: ", str(head_locs), "; Seg_loc: ", str(seg_locs))

    pygame.display.update()

snake = player(40, 60, 1) #snake instance

apple = food(random.randint(10, 480), random.randint(40, 480)) #food instances
apples.append(apple)

font1 = pygame.font.SysFont('comicsans', 30, True) #level, length labels
font2 = pygame.font.SysFont('comicsans', 30, False, True)

def game_loop():   
    run = True
    while run:  #main loop
        clock.tick(10)

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

        for seg in segs: #check to look for collisions
            if (seg.x < snake.x + 20 and seg.x + 20 > snake.x):
                if (seg.y < snake.y + 20 and snake.y < seg.y + 20):
                    run = False

        for apple in apples: #add length to snake and delete green apple if eaten
            if (apple.y - apple.radius < snake.y + 20 and
                apple.y + apple.radius > snake.y):
                if (apple.x - apple.radius < snake.x + 20 and
                    apple.x + apple.radius > snake.x):
                        snake.eatGood()
                        apples.pop(apples.index(apple))

        for bad in badApples: #remove length from snake and delete red apple if eaten
            if (bad.y - bad.radius < snake.y + 20 and
                bad.y + bad.radius > snake.y):
                if (bad.x - bad.radius < snake.x + 20 and
                    bad.x + bad.radius > snake.x):
                    snake.eatBad()
                    badApples.pop(badApples.index(bad))

        if snake.length == 0: #lose game if length = 0
            run = False

        if len(apples) == 0: #ups vel, level if all apples eaten
            global level
            global velocity
            level += 1
            velocity += 1

        keys = pygame.key.get_pressed()

        if keys[pygame.K_LEFT] and snake.x > snake.vel and snake.xchange != right:
            snake.x -= snake.vel
            snake.xchange = left
            snake.ychange = 0

        elif keys[pygame.K_RIGHT] and snake.x < scrWdt - snake.vel and snake.xchange != left:
            snake.x += snake.vel
            snake.xchange = right
            snake.ychange = 0

        elif keys[pygame.K_UP] and snake.y > 40 + snake.vel and snake.ychange != down:
            snake.y -= snake.vel
            snake.xchange = 0
            snake.ychange = up

        elif keys[pygame.K_DOWN] and snake.y < scrHgt - snake.vel and snake.ychange != up:
            snake.y += snake.vel
            snake.xchange = 0
            snake.ychange = down

        else:
            if snake.xchange == left:
                if snake.x < snake.vel:
                    snake.x = scrWdt - snake.vel
                snake.x -= snake.vel
                snake.xchange = left
                snake.ychange = 0
            elif snake.xchange == right:
                if snake.x > scrWdt - snake.vel:
                    snake.x = 0
                snake.x += snake.vel
                snake.xchange = right
                snake.ychange = 0
            elif snake.ychange == up:
                if snake.y < 40 + snake.vel:
                    snake.y = scrHgt - snake.vel
                snake.y -= snake.vel
                snake.xchange = 0
                snake.ychange = up
            elif snake.ychange == down:
                if snake.y > scrHgt - snake.vel:
                    snake.y = 40 + snake.vel
                snake.y += snake.vel
                snake.xchange = 0
                snake.ychange = down

        redrawGameWindow()

game_loop()
pygame.quit()
quit()

我希望能够继续玩下去,直到我用完所有片段或遇到自己,但它会随机遇到自己,然后关闭游戏。我从上面的代码中删除了一个介绍,暂停和丢失的屏幕,因为我不想让它太长。

python pygame
1个回答
0
投票

问题很简单。吃完苹果后,新元素(段)将连续添加到段列表(segs)中。 segs包含蛇自从吃掉第一个苹果以来的所有位置。segs将在每个帧中重新创建seg_locs,因此必须在添加seg_locs的元素之前创建一个新列表:

segs = [] # <--- this is missing

for i in seg_locs.keys(): #create instance of segment to draw
    if i == 1:
        old_head_loc = head_locs[0][:]
        seg = Segment(*old_head_loc)
    else:
        old_seg_loc = seg_locs[i-1][0]
        seg = Segment(*old_seg_loc)

    seg.draw(i, win)
    segs.append(seg)
© www.soinside.com 2019 - 2024. All rights reserved.