我已经尝试从头开始创建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()
我希望能够继续玩下去,直到我用完所有片段或遇到自己,但它会随机遇到自己,然后关闭游戏。我从上面的代码中删除了一个介绍,暂停和丢失的屏幕,因为我不想让它太长。
问题很简单。吃完苹果后,新元素(段)将连续添加到段列表(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)