Я написал платформер с некоторыми полезными ссылками на различные источники. Конечная идея моего платформера заключается в том, чтобы иметь возможность перемещать линии, которые вы рисуете мышью. К сожалению, я до сих пор не смог получить базовое обнаружение столкновения, работающее в сочетании с физикой и движением. Движение работает само по себе, но не в сочетании с обнаружением физики/столкновения. Я верю, что что-то пошло не так, я собрал все вместе, и, честно говоря, я не могу понять, что.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 прекрасно.
Можете ли вы попытаться удалить код и сделать более простую ситуацию, которая все еще обнаруживает проблему? Это поможет сузить проблему, и поможет нам найти ошибки. – Xymostech
Да. Я думаю, что есть проблема со смещением - если я попытаюсь возвратить смещение от моей функции adjPosition (она должна корректировать позицию при возникновении столкновений) - игра замерзает. Я уверен, что это проблема, содержащаяся в этих классах, а не мой основной цикл, но я буду продолжать отлаживать небольшие части. – user3064211
ОК. Поэтому используемые некоторые заявления о печати, по-видимому, ВСЕГДА считают, что существует горизонтальное столкновение. Моя физика/движение может быть запутано, но это основная проблема. – user3064211