编辑:QuadTrees(http://www.pygame.org/wiki/QuadTree?parent=CookBook)可能是我的答案,试试这个并报告回来。不管怎样,请不要犹豫,给我一些建议!
我在pygame中有一系列障碍,我正在转换为Rect对象,在帧的每个刻度之前循环遍历列表,以查看我的Hero Rect对象是否已经碰撞。
我认为这会导致我出现性能问题。我也知道我可以尝试切换到" Dirty rect animation"而不是每次打勾都更新整个屏幕,但在我走这条路之前,我想知道我是否能更有效地做到这一点。
有问题的特定代码发生在最底层附近(如果是pillars.checkCollision(hero.rect):),但我提供了上下文的所有内容:
import sys
import pygame
from pygame.locals import *
import pyganim
from decimal import *
import math
## start pymgame
pygame.init()
## window and lines
windowWidth = 387
windowHeight = 340
lineThickness = 3
animationSpeed = .15
## fps and speed
increaseSpeed = 1
fps = 60
fpsClock = pygame.time.Clock()
## window
##windowSurface = pygame.display.set_mode((windowWidth, windowHeight), pygame.FULLSCREEN)
windowSurface = pygame.display.set_mode((windowWidth, windowHeight))
class Pillars():
def __init__(self):
self.image = pyganim.PygAnimation([("grave.png", animationSpeed)])
self.xSize = self.image.getMaxSize()[0]
self.ySize = self.image.getMaxSize()[1]
self.numberOfColumns = int(math.ceil(Decimal((windowWidth - (self.xSize * 4))) / Decimal((self.xSize * 3))))
self.numberOfRows = int(math.ceil(Decimal((windowHeight - (self.ySize * 4))) / Decimal((self.ySize * 3))))
self.rects = []
self.image.play()
def draw(self):
xPos = (self.xSize * 2)
yPos = (self.ySize * 2)
columnCounter = 1
for num in range(0, (self.numberOfColumns * self.numberOfRows)):
self.rects.append(Rect(xPos, yPos, self.xSize, self.ySize))
self.image.blit(windowSurface, (xPos, yPos))
xPos += (self.xSize * 3)
if columnCounter >= self.numberOfColumns:
columnCounter = 0
xPos = (self.xSize * 2)
yPos += (self.ySize * 3)
columnCounter += 1
def checkCollision(self, Rect):
for pillarRect in self.rects:
if pillarRect.colliderect(hero.rect):
return True
class Hero():
def __init__(self):
self.standingLeft = pyganim.PygAnimation([("left_standing_link.png", animationSpeed)])
self.standingRight = pyganim.PygAnimation([("right_standing_link.png", animationSpeed)])
self.standingUp = pyganim.PygAnimation([("up_standing_link.png", animationSpeed)])
self.standingDown = pyganim.PygAnimation([("down_standing_link.png", animationSpeed)])
self.walkingUp = pyganim.PygAnimation([("up_standing_link.png", animationSpeed), ("up_walking_link.png", animationSpeed)])
self.walkingDown = pyganim.PygAnimation([("down_standing_link.png", animationSpeed), ("down_walking_link.png", animationSpeed)])
self.walkingLeft = pyganim.PygAnimation([("left_standing_link.png", animationSpeed), ("left_walking_link.png", animationSpeed)])
self.walkingRight = pyganim.PygAnimation([("right_standing_link.png", animationSpeed), ("right_walking_link.png", animationSpeed)])
self.walkingRight.play()
self.walkingLeft.play()
self.standingLeft.play()
self.standingRight.play()
self.standingUp.play()
self.standingDown.play()
self.walkingUp.play()
self.walkingDown.play()
self.x = 100
self.y = 100
self.dirX = 0 ## -1 = left 1 = right
self.dirY = 0 ## -1 = up 1 = down
self.orientation = 0 ## 0 = right, 1 = down, 2 = left, 3 = up
self.rect = None
def move(self, animationObj):
self.animationObject = animationObj
animationObj.x = self.x + (self.dirX * increaseSpeed)
animationObj.y = self.y + (self.dirY * increaseSpeed)
self.x = animationObj.x
self.y = animationObj.y
if self.dirX == 1:
self.orientation = 0
elif self.dirX == -1:
self.orientation = 2
elif self.dirY == -1:
self.orientation = 3
elif self.dirY == 1:
self.orientation = 1
tempRect = animationObj.getRect()
self.rect = Rect(animationObj.x, animationObj.y, tempRect[2], tempRect[3])
def draw(self, animationObj):
if self.y > (windowHeight - (lineThickness * 5.5)):
self.y = windowHeight - (lineThickness * 5.5)
elif self.y < lineThickness:
self.y = lineThickness
elif self.x > (windowWidth - (lineThickness * 6)):
self.x = windowWidth - (lineThickness * 6)
elif self.x < lineThickness:
self.x = lineThickness
animationObj.blit(windowSurface, (self.x, self.y))
def moveAndDrawWalkingRight(self):
self.dirX = 1
self.dirY = 0
self.move(self.walkingRight)
self.draw(self.walkingRight)
def moveAndDrawWalkingLeft(self):
self.dirX = -1
self.dirY = 0
self.move(self.walkingLeft)
self.draw(self.walkingLeft)
def moveAndDrawWalkingUp(self):
self.dirX = 0
self.dirY = -1
self.move(self.walkingUp)
self.draw(self.walkingUp)
def moveAndDrawWalkingDown(self):
self.dirX = 0
self.dirY = 1
self.move(self.walkingDown)
self.draw(self.walkingDown)
def drawStanding(self):
if self.orientation == 0:
self.dirX = 0
self.dirY = 0
self.move(self.standingRight)
self.draw(self.standingRight)
elif self.orientation == 2:
self.dirX = 0
self.dirY = 0
self.move(self.standingLeft)
self.draw(self.standingLeft)
elif self.orientation == 1:
self.dirX = 0
self.dirY = 0
self.move(self.standingDown)
self.draw(self.standingDown)
elif self.orientation == 3:
self.dirX = 0
self.dirY = 0
self.move(self.standingUp)
self.draw(self.standingUp)
def drawArena():
windowSurface.fill((0,0,0))
hero = Hero()
pillars = Pillars()
while True: # main loop
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if event.key == K_ESCAPE:
pygame.quit()
sys.exit()
## if event.key == K_RIGHT:
## hero.moveAndDrawWalkingRight()
## elif event.key == K_LEFT:
## hero.moveAndDrawWalkingLeft()
## elif event.key == K_UP:
## hero.moveAndDrawWalkingUp()
## elif event.key == K_DOWN:
## hero.moveAndDrawWalkingDown()
## else:
## hero.drawStanding()
drawArena()
pillars.draw()
priorHeroX = hero.x
priorHeroY = hero.y
keys = pygame.key.get_pressed() #checking pressed keys
if keys[pygame.K_RIGHT]:
hero.moveAndDrawWalkingRight()
elif keys[pygame.K_LEFT]:
hero.moveAndDrawWalkingLeft()
elif keys[pygame.K_UP]:
hero.moveAndDrawWalkingUp()
elif keys[pygame.K_DOWN]:
hero.moveAndDrawWalkingDown()
else:
hero.drawStanding()
if pillars.checkCollision(hero.rect):
hero.x = priorHeroX
hero.y = priorHeroY
pygame.display.update()
fpsClock.tick(fps)
答案 0 :(得分:1)
不是使用Rect
检查每个.colliderect(..)
,而是可以像.collidelist(..)
一样使用 .. # in class Pillars ..
def checkCollision(self): # `Rect` was in there as an argument; I'm not sure what it did...?
if hero.rect.collidelist(self.rects) != -1: # collidelist returns a list index if it collides, or -1 if it does not.
return True
:
def checkCollision(self):
return False if hero.rect.collidelist(self.rects) == -1 else True
# Be aware that this returns False instead of nothing if there is no collision.
......甚至只是......
Rect
我不确定Pygame是否有比你的循环更有效的迭代器,但可能呢?如果不出意外,它会为您节省几行代码。如果您需要知道具体与hero
def getColliding(self): # this returns something slightly different...
idx = hero.rect.collidelist(self.rects)
return None if idx == -1 else self.rects[idx]
发生冲突,请考虑以下事项:
Rect
如果有hero
对象发送回None
对象,或者如果有多个就发送回列表中的第一个这样的Rect,或者{{1}}如果没有碰撞完全没有。