Я делаю игру на змейке на python с pygame, но у меня возникают проблемы с тем, чтобы программа обнаружила столкновение с самим собой ...
Я попытался настроить его так, чтобы он обнаруживал, если бы Моррисон.head обнаружит Morrison.body, но он выдаст мне ошибку
import pygame
import random
import time
import sys
from collections import deque
# Window size
WINDOW_WIDTH=400
WINDOW_HEIGHT=400
pygame.init()
WINDOW = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ),
pygame.HWSURFACE|pygame.DOUBLEBUF|pygame.RESIZABLE )
SPRITES = pygame.sprite.Group()
pygame.display.set_caption("Picnic!")
background = pygame.image.load("picnic.png")
background_rect = background.get_rect()
HEAD_IMAGE =pygame.image.load('morrison.png').convert_alpha()
#HEAD_IMAGE.fill(pygame.Color('yellow'))
BODY_IMAGE = pygame.image.load('morrison.png').convert_alpha()
#BODY_IMAGE.fill(pygame.Color('orange'))
FOOD1_IMAGE= pygame.image.load("thinMint.png").convert_alpha()
#FOOD1_IMAGE.fill(pygame.Color('green'))
FOOD2_IMAGE =pygame.image.load("cookie.png").convert_alpha()
#FOOD2_IMAGE.fill(pygame.Color('red'))
FOOD3_IMAGE =pygame.image.load("triscuit.png").convert_alpha()
#FOOD3_IMAGE.fill(pygame.Color('blue'))
clock = pygame.time.Clock()
BLACK = (0,0,0)
score = 0
last_positions = deque(maxlen=10)
def generateFoodPosition():
pos = random.randrange(1, 40, 1) * 10, random.randrange(1, 40,
1) * 10
if pos in last_positions:
return generateFoodPosition()
last_positions.append(pos)
return pos
def draw_text(surf, text, size, x, y):
font = pygame.font.SysFont("SquidgySweets.otf", 72)
text_surface = font.render(text, True, BLACK)
text_rect = text_surface.get_rect()
text_rect.midtop = (x, y)
surf.blit(text_surface, text_rect)
class Food(pygame.sprite.Sprite):
def __init__(self, image, *grps):
pygame.sprite.Sprite.__init__(self, *grps)
self.image = image
self.rect = self.image.get_rect()
self.rect.center = generateFoodPosition()
def update(self, dt, snakehead, events):
global score
m=1
if self.rect.colliderect(snakehead):
print("yeet yah")
score += 1
self.rect.center = generateFoodPosition()
if Morrison.head:
Morrison.grow(m)
Morrison.last_grow=Morrison.t
class MorrisonSprite(pygame.sprite.Sprite):
def __init__( self, part_image, position, head, *grps):
pygame.sprite.Sprite.__init__(self, *grps)
self.image = part_image
self.rect = self.image.get_rect()
self.rect.center = position
self.move_step = self.image.get_rect().width # this is how
we know how many pixels per move step
self.t = 0
self.last_move = 0
self.last_grow = 0
self.head = head
self.direction = 'left';
self.body = []
if self.head:
self.body.append(self)
#self.grow(m)
def wrapAroundScreen(self):
# Stay on the screen, and wrap around
if (self.rect.left >= WINDOW_WIDTH ):
self.rect.right = 0
elif (self.rect.right <= 0 ):
self.rect.left = WINDOW_WIDTH
if (self.rect.top >= WINDOW_HEIGHT ):
self.rect.bottom = 0
elif (self.rect.bottom <= 0):
self.rect.top = WINDOW_HEIGHT
def move( self ):
if ( self.direction == 'up' ):
self.rect.y -= self.move_step
elif ( self.direction == 'down' ):
self.rect.y += self.move_step
elif ( self.direction == 'left' ):
self.rect.x -= self.move_step
elif ( self.direction == 'right' ):
self.rect.x += self.move_step
else:
print(" MOVE ERROR - "+direction)
self.wrapAroundScreen()
def update(self, dt, snakehead, events):
if not self.head:
return
keys = pygame.key.get_pressed()
if ( keys[pygame.K_UP] ):
self.direction = "up"
elif ( keys[pygame.K_DOWN] ):
self.direction = "down"
elif ( keys[pygame.K_LEFT] ):
self.direction = "left"
elif ( keys[pygame.K_RIGHT] ):
self.direction = "right"
self.t += dt
if any(e for e in events if e.type == pygame.KEYDOWN) or (
self.t > 3000 and self.t - self.last_move >= 100 ):
self.slither()
self.last_move = self.t
# Grow every 2 seonds
#This is a past test function that is no longer used:
#if (self.t > 3000 and self.t - self.last_grow >= 10000):
#print("Growing...")
#self.grow( 1 )
#self.last_grow = self.t
def slither( self ):
# Move each body part to the location of the previous part
# So we iterate over the tail-parts in reverse
for i in range( len( self.body )-1, 0, -1 ):
self.body[i].rect.center = self.body[i-1].rect.center
# Move the head
self.move()
def getGrowPosition( self ):
# we grow against self.direction
# so if we're moving up, the tail grows down
x,y = self.body[ -1 ].rect.center
if ( self.direction == 'up' ):
y += self.move_step
elif ( self.direction == 'down' ):
y -= self.move_step
elif ( self.direction == 'left' ):
x += self.move_step
elif ( self.direction == 'right' ):
x -= self.move_step
return (x,y)
def grow( self, by_size=1 ):
for i in range( by_size ):
# new body part needs to be added at the tail-position
new_body_part = MorrisonSprite( BODY_IMAGE,
self.getGrowPosition(), False, *self.groups())
self.body.append( new_body_part )
### MAIN
Morrison = MorrisonSprite(HEAD_IMAGE, ((WINDOW_WIDTH//2)-64,
WINDOW_HEIGHT//2 ), True, SPRITES)
clock = pygame.time.Clock()
done = False
Food(FOOD1_IMAGE, SPRITES)
Food(FOOD2_IMAGE, SPRITES)
Food(FOOD3_IMAGE, SPRITES)
dt = 0
while not done:
#this allows you to close the window
events = pygame.event.get()
for event in events:
if ( event.type == pygame.QUIT ):
done = True
elif ( event.type == pygame.VIDEORESIZE ):
# this allows you to resize-window:
WINDOW_WIDTH = event.w
WINDOW_HEIGHT = event.h
WINDOW = pygame.display.set_mode(( WINDOW_WIDTH,
WINDOW_HEIGHT ), pygame.HWSURFACE|pygame.DOUBLEBUF|pygame.RESIZABLE)
#Morrison.head = head
#Morrison.rect = Morrison.head.get_rect()
if Morrison.rect.head.colliderect(Morrison.rect.body):
pygame.quit()
#this basically displays everything on the screen (background,
sprites)...
WINDOW.fill(BLACK)
WINDOW.blit(background, background_rect)
draw_text(WINDOW, str(score), 18, WINDOW_WIDTH / 2, 10)
SPRITES.update(dt, Morrison.rect, events)
SPRITES.draw(WINDOW)
pygame.display.flip()
dt = clock.tick_busy_loop(60)
pygame.quit()
Я ожидал, что программа обнаружит столкновение, если столкнется со своим собственным телом, но вместо этого он просто выдаст ошибку