2014-01-21 4 views
0

Я испытываю странную ошибку обнаружения столкновений, которую я не могу найти. Я строю маленькую змеиную игру, и, как говорит традиция, мне нужна змея, чтобы умереть, когда он сталкивается с самим собой. Поэтому я сказал голова змеи умереть, если она столкнулась с любым сегментом, отличным от первых трех. Но он продолжает бросать столкновение, хотя, очевидно, не столкновение .. Я сделал код полностью стоять одна для тех, кто хочет видеть для себя:Weird обнаружение столкновения с Snake Game

import pygame 
from pygame.locals import * 
from random import randint 
pygame.init() 
screen=pygame.display.set_mode((320,240)) 
run=True 
prevpos=(0,0) 
curid=0 
clock=pygame.time.Clock() 
points=0 
def DrawSeg(x,y,col,size): 
    pygame.draw.circle(screen, col, (x,y), size, 0) 
class HeadSegment(object): 
    def __init__(self,x,y): 
     self.x=x 
     self.y=y 
     self.direct=(0,0) 
     self.prevpos=(self.x,self.y) 
     self.time=2 
     self.rect=pygame.Rect(self.x-5,self.y-5,10,10) 
    def update(self): 
     global segs 
     self.rect=pygame.Rect(self.x-5,self.y-5,10,10) 
     self.time-=1 
     for s in segs[5:]: 
      if self.rect.colliderect(s.rect): 
       print 'die' 
     if self.time==0: 
      self.time=2 
      self.prevpos=(self.x,self.y) 
     key=pygame.key.get_pressed() 
     if key[K_LEFT]: 
      if self.direct != (3,0): 
       self.direct=(-3,0) 
     elif key[K_RIGHT]: 
      if self.direct != (-3,0): 
       self.direct=(3,0) 
     elif key[K_UP]: 
      if self.direct != (0,3): 
       self.direct=(0,-3) 
     elif key[K_DOWN]: 
      if self.direct != (0,-3): 
       self.direct=(0,3) 
     self.x+=self.direct[0] 
     self.y+=self.direct[1] 
     DrawSeg(self.x,self.y,(255,0,0),5) 
head=HeadSegment(20,20) 
class Segment(object): 
    def __init__(self,x,y): 
     global curid 
     self.x=x 
     self.y=y 
     self.direct=(0,0) 
     self.id=curid+1 
     curid+=1 
     self.prevpos=(self.x,self.y) 
     self.time=2 
     self.rect=pygame.Rect(self.x-5,self.y-5,10,10) 
    def update(self): 
     self.time-=1 
     if self.time==0: 
      self.time=2 
      self.prevpos=(self.x,self.y) 
     global segs 
     try: 
      nextpos=segs[self.id+1] 
      self.x=nextpos.prevpos[0] 
      self.y=nextpos.prevpos[1] 
     except: 
      self.x=head.prevpos[0] 
      self.y=head.prevpos[1] 
     self.rect=pygame.Rect(self.x-5,self.y-5,10,10) 
     DrawSeg(self.x,self.y,(200,0,0),5) 
class Fruit(object): 
    def __init__(self): 
     self.x=randint(7,315) 
     self.y=randint(7,235) 
     self.rect=pygame.Rect(self.x-6,self.y-6,12,12) 
    def update(self): 
     global points 
     global segs 
     DrawSeg(self.x,self.y,(0,0,220),6) 
     if self.rect.colliderect(head.rect): 
      self.x=randint(7,315) 
      self.y=randint(7,235) 
      self.rect=pygame.Rect(self.x-6,self.y-6,12,12) 
      points+=1 
      try: 
       segs.append(Segment(segs[len(segs)-1].prevpos[0],segs[len(segs)-1].prevpos[1])) 
      except: 
       segs.append(Segment(20,20)) 

segs=[] 
fruit=Fruit() 
while run: 
    screen.fill((0,200,0)) 
    for s in segs: 
     s.update() 
    fruit.update() 
    head.update() 
    for e in pygame.event.get(): 
     if e.type==QUIT: 
      exit() 
    clock.tick(60) 
    pygame.display.flip() 

Может кто-то указать, что это не так? Проверьте класс HeadSegment. Вот где я считаю, что ошибка возникает.

+0

Итак, из некоторых тестов, которые я запускал, кажется, что они только сталкиваются на одном пикселе. – KodyVanRy

+0

Почему они сталкиваются? –

+0

Вы пытались вместо этого использовать все прямоугольники вместо сегментов? И просто каждый раз обновляйте прямоугольник? Просто избавитесь от расширения объекта все вместе, а затем просто используйте все те же переменные. – KodyVanRy

ответ

1

Проблема, насколько я могу судить, заключается в том, как вы обновляете позиции сегмента. То, как оно теперь закодировано, каждый новый сегмент становится одним непосредственно за головой, а не «безопасными» сегментами, которые следуют за головой.

Фактическая ошибка в Segment.update функции:

try: 
    nextpos=segs[self.id+1] 
    self.x=nextpos.prevpos[0] 
    self.y=nextpos.prevpos[1] 
except: 
    self.x=head.prevpos[0] 
    self.y=head.prevpos[1] 

Я включил логику конструктора, так что curid равен индексу сегмента в списке Segs, то используется этот код:

if self.id < 1: 
    self.x = head.prevpos[0] 
    self.y = head.prevpos[1] 
else: 
    nextpos = segs[self.id-1] 
    self.x = nextpos.prevpos[0] 
    self.y = nextpos.prevpos[1] 

Это только сталкивается, когда вы сталкиваетесь с собой с более длинной змеей. Самый ранний сегмент, который я мог заставить столкнуться, был 19.

+0

Спасибо за ответ, но я переключился на определение цвета вместо прямого столкновения, это намного быстрее. Но я по-прежнему буду применять модификацию класса «Сегмент». –

+0

Как вы получили индекс 'self' из segs? –

+1

Изменение было связано с тем, как вы определили 'curid'. В вашем коде вы помещаете 'self.id = curid + 1', а затем увеличиваете' curid'. Я инициализировал 'curid' как 0, сбросил' curid + 1', чтобы он выглядел так: 'self.id = curid curid + = 1' Таким образом,' self.id' является индексом сегмента. – pathunstrom

Смежные вопросы