2013-12-04 6 views
1

Я написал платформер с некоторыми полезными ссылками на различные источники. Конечная идея моего платформера заключается в том, чтобы иметь возможность перемещать линии, которые вы рисуете мышью. К сожалению, я до сих пор не смог получить базовое обнаружение столкновения, работающее в сочетании с физикой и движением. Движение работает само по себе, но не в сочетании с обнаружением физики/столкновения. Я верю, что что-то пошло не так, я собрал все вместе, и, честно говоря, я не могу понять, что.PyGame Collision Detection - Платформер замораживания

Я считаю, что проблема в моем классе игроков. Как я делаю столкновение прямо сейчас, я проверяю объекты listOfObjects (rects), которые я создал на верхнем слое ландшафта (он же красный квадрат). Что-то не так с тем, как физика взаимодействует со всем остальным.

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

class Physics: 
def __init__(self): 
    self.xv = 0 
    self.yv = 0 
    self.yvi = 0 
    self.gravity = 20 
    self.falling = False 
    self.timer = None 
def timerUpdate(self): 
    if self.falling: 
     if not self.timer: 
      self.timer = pygame.time.get_ticks() 
      #not sure about 1000 
     self.yv = self.gravity*((pygame.time.get_ticks()-self.timer)/1000.0)+self.yvi 
    else: 
     #if not falling no need for timer/y velocity 
     self.timer = None 
     self.yv = 0 

class Player(Physics): 
    def __init__(self): 
    #inherit Physics 
     Physics.__init__(self) 
     self.animObjs = {} 
     self.running = False 
     self.moveLeft = False 
     self.moveRight = False 
     self.jump = False 
     self.walkrate = 2 
     self.runrate = 4 
     self.xwidth = 50 
     self.yheight = 80 
     self.x = 0 
     self.y = 0 
     self.bounce = 10 
     self.listOfCollisions = [] 
     self.rate = 0 
     #rectOverride with built-in offset 
     self.rectOverride = pygame.Rect(0,0,self.xwidth,self.yheight) 
     self.rectOverride.topleft = (0,0) 


def calcPosition(self, listOfObjects): 
    #fall off edge 
    if not (self.falling and self.collision(listOfObjects,[0,1])): 
     self.falling = True 
    #vertical collisions 
    elif (self.falling and self.collision(listOfObjects,[0,int(self.yv)])): 
     self.yv = self.adjPosition(self.listOfCollisions,[0,int(self.yv)],1) 
     print self.yv 
     self.yvi = 0 
     self.falling = False 
    self.rectOverride.y += int(self.yv) 
    #horizontal collisions 
    if self.collision(listOfObjects, (int(self.xv),0)): 
     self.xv = self.adjPosition(self.listOfCollisions,[int(self.xv),0],0) 
    self.rectOverride.x += int(self.xv) 
def adjPosition(self, listOfObjects, offset, t): 
    #accounts for extra offset from objects 
    if offset[t] < 0: 
     offset[t] += 1 
    else: 
     offset[t] -= 1 
    while True: 
     if any(self.collision(self.listOfCollisions,offset)): 
      print offset 
      if offset[t] < 0: 
       offset[t] += 1 
      elif offset[t] > 0: 
       offset[t] -= 1 
      else: #moving that out breaks it for some reason where it's supposed to be.. 
       return offset[t] 
def collision(self, listOfObjects, offset): 
    temp = pygame.Rect((self.rectOverride.x + offset[0],self.rectOverride.y + offset[1]), self.rectOverride.size) 
    self.listOfCollisions = [] 
    for i in listOfObjects: 
     if temp.colliderect(i): 
      self.listOfCollisions.append(i) 
    return self.listOfCollisions 
def updatePlayer(self,listOfObjects): 
    self.calcPosition(listOfObjects) 
    self.timerUpdate() 

И вот мой код движения (там что-то не так с переменным/блиттингом):

#############GAME LOGIC############ 
def move(self): 
    if self.moveLeft or self.moveRight: 
    # draw the correct walking/running sprite from the animation object 
     self.moveConductor.play() # calling play() while the animation objects are already playing is okay; in that case play() is a no-op 
     if self.running: 
      if self.direction == 'LEFT': 
       self.animObjs['left_run'].blit(self.screen, (self.rectOverride.topleft[0], self.rectOverride.topleft[1])) 
      elif self.direction == 'RIGHT': 
       self.animObjs['right_run'].blit(self.screen, (self.rectOverride.topleft[0], self.rectOverride.topleft[1])) 
     else: 
      # walking 
      if self.direction == 'LEFT': 
       self.animObjs['left_walk'].blit(self.screen, (self.rectOverride.topleft[0], self.rectOverride.topleft[1])) 
      elif self.direction == 'RIGHT': 
       self.animObjs['right_walk'].blit(self.screen, (self.rectOverride.topleft[0], self.rectOverride.topleft[1])) 

     # actually move the position of the player 
     if self.running: 
      self.rate = self.runrate 
     else: 
      self.rate = self.walkrate 
     if self.moveLeft: 
      self.xv -= self.rate 
     if self.moveRight: 
      self.xv += self.rate 

    elif self.jump: 
     #self.moveConductor.stop() #do i need this? 
     if self.direction == 'LEFT': 
      self.screen.blit(self.left_jump, (self.rectOverride.topleft[0], self.rectOverride.topleft[1])) 
     elif self.direction == 'RIGHT': 
      self.screen.blit(self.right_jump, (self.rectOverride.topleft[0], self.rectOverride.topleft[1])) 
     self.rate = self.bounce 
     self.yvi = -self.rate 

    else: 
     # standing still 
     self.moveConductor.stop() # calling stop() while the animation objects are already stopped is okay; in that case stop() is a no-op 
     if self.direction == 'LEFT': 
      self.screen.blit(self.left_standing, (self.rectOverride.topleft[0], self.rectOverride.topleft[1])) 
     elif self.direction == 'RIGHT': 
      self.screen.blit(self.right_standing, (self.rectOverride.topleft[0], self.rectOverride.topleft[1])) 

    # make sure the player doesnt move off the screen 
    # if self.x < 0: 
    # self.x = 0 
    #if self.x > self.WINDOWWIDTH - self.xwidth: 
    # self.x = self.WINDOWWIDTH - self.xwidth 
    #if self.y < 0: 
    # self.y = 0 
    #if self.y > self.WINDOWHEIGHT - self.yheight: 
    # self.y = self.WINDOWHEIGHT - self.yheight 

Заранее спасибо за любую помощь ... Я в тупике и пытался отладки с печатью на какое-то время, но я действительно не знаю, куда идти отсюда.

Это всегда возвращает истину: если self.collision (СПИСОК_ОБЪЕКТОВ, (Int (self.xv), 0)):

СПИСОК_ОБЪЕКТОВ печатает гигантский список "" снова и снова, потому что я пользователь -пределенные вершины, чтобы иметь только один «1». Я не знаю, что происходит.

listOfObjects создается в моем классе Terrain. По этой функции.

def drawToScreen(self, surface): 
    i = 0 
    listOfObjects = [] 
    sizeX, sizeY = self.sizeOnScreen 
    for top in self.tops: 
     if top == '1' and ((i*sizeX-self.levelPos)<self.WINDOWWIDTH): 
      x = i * sizeX 
      y = self.height - self.gaps[i] 
      if (x + sizeX - self.levelPos > 0): 
       #rectangle coordinates? 
       tileRect = (x - self.levelPos, y, sizeX, sizeY) 
       surface.blit(self.tileDict['Element0'], tileRect) 
       obj = pygame.Rect(x-self.levelPos, y, sizeX, sizeY)#create a rect   object at the top 
       self.listOfObjects.append(obj) 
       pygame.draw.rect(surface, (255,0,0), tileRect) #create red visual representation 
       for j in range(1,6): #fills the bottom 
        tileRect = (x-self.levelPos, y+j*sizeY,sizeX,sizeY) 
        surface.blit(self.tileDict['Element0Fill'], tileRect) 
      i += 1 

EDIT/ Хорошо через отладочную проблему определенно находится в моем классе игрока, Terrain прекрасно.

+0

Можете ли вы попытаться удалить код и сделать более простую ситуацию, которая все еще обнаруживает проблему? Это поможет сузить проблему, и поможет нам найти ошибки. – Xymostech

+0

Да. Я думаю, что есть проблема со смещением - если я попытаюсь возвратить смещение от моей функции adjPosition (она должна корректировать позицию при возникновении столкновений) - игра замерзает. Я уверен, что это проблема, содержащаяся в этих классах, а не мой основной цикл, но я буду продолжать отлаживать небольшие части. – user3064211

+0

ОК. Поэтому используемые некоторые заявления о печати, по-видимому, ВСЕГДА считают, что существует горизонтальное столкновение. Моя физика/движение может быть запутано, но это основная проблема. – user3064211

ответ

0

Для перемещения необходимо установить self.moveLeft = True или self.moveRight = True.

Я не вижу, как вы это делаете.

+0

Спасибо, но я действительно позабочусь об этом в моей основной петле. Я снова начал движение (хотя прыжки перепутаны), но обнаружение столкновений полностью нарушено. Есть ли у вас какие-либо рекомендации относительно того, как я могу переписать это на основе приведенного выше кода? Я думаю, мне понадобится чистая переработка, потому что я пытался отладить этот код некоторое время, и этого просто не происходит. Код обнаружения столкновений все тот же, что и выше (в классе Player). – user3064211