滚动对象不流畅,有时会向右跳动几像素 [pygame]
为了制作一个抽象的、可以滚动的城市天际线原型,我创建了一个类来生成随机的矩形。这些矩形被添加到一个列表中,然后从这个列表中取出要在屏幕上绘制的内容。这些矩形一开始在屏幕右侧外面,然后向左滚动,直到它们离开视野并被丢弃。建筑物的移动看起来有点卡顿,而且在屏幕的某个特定位置,它们还会向右移动几个像素。
这个原型的视频拍得相当准确,几乎没有延迟。请注意建筑物之间的间隙,当它们接近显示区域的最右侧三分之一时,间隙会突然缩小,就好像左边的建筑物突然向右移动了几个像素。间隙越小,这种现象越明显。视频中的其他异常是由于录制者造成的,在应用程序中并不存在。这里有一个很短的视频,清楚地展示了这个现象: https://www.youtube.com/watch?v=0cdhrezjcY8
在大约1秒的时候,你会注意到后面一层建筑物之间有一个非常窄的间隙。在4秒时,这个间隙与蓝色玩家对象平齐,左边的矩形移动,间隙消失了。右边还有一个更大的间隙也发生了同样的情况,但由于间隙较大,它并没有完全消失。我已经多次检查代码,但仍然看不出是什么导致了这个异常。我希望有人能告诉我这是我做错了什么,还是我遇到了某种限制。
我最开始是线性编写这个程序的,没有使用类或函数。后来我重写了它,使用一个类来生成层对象,并处理所有的生成和滚动。在这两种情况下,问题依然存在。弄不明白为什么建筑物移动得不流畅让我很抓狂。我甚至写了一个版本,使用png图片而不是随机生成的矩形。在那个版本中,png图片滚动得非常流畅和无缝: https://www.youtube.com/watch?v=Uiw_giAvbOo(视频有点卡顿,但实际程序运行得很流畅)所以这个问题只出现在这些随机矩形上。
这是程序的代码: https://www.refheap.com/73079
这是类的代码:
class Scroller():
def __init__(self, speed, color, heightMax):
# Speed of the layer scroll, the color of the layer and the maximum height for buildings
# set up the building parameters
self.buildingHeightMax = heightMax
self.buildingHeightMin = 100
self.buildingWidthMax = 125
self.buildingWidthMin = 75
self.buildings = []
self.layerspeed = speed
self.buildTime = True
self.buildCountdown = 10
self.color = color
def update(self):
# Check if it's time to build. If not, decrement counter
if self.buildTime == False:
self.buildCountdown -= 1
# If time is 0, time to build, reset counter to a new random time
if self.buildCountdown <= 0:
self.buildTime = True
self.buildCountdown = random.randint(3, self.layerspeed)
# create building if it's time
if self.buildTime:
# generate random width and height of building
buildingHeight = random.randint(self.buildingHeightMin, self.buildingHeightMax)
buildingWidth = random.randint(self.buildingWidthMin, self.buildingWidthMax)
buildingTop = WINDOWHEIGHT - buildingHeight
# This generates the building object from the above parameters
building = pygame.Rect(WINDOWWIDTH, buildingTop, buildingWidth, WINDOWHEIGHT)
self.buildTime = False
self.buildCountdown = random.randint(3, self.layerspeed * 5)
# add building to buildings list
self.buildings.append(building)
# move all buildings on layer at set speed
for building in self.buildings:
# if the building is off the screen, trash it. If not, move it to the
# right at the objects speed.
if building.right < 0:
self.buildings.remove(building)
else:
building.left -= self.layerspeed
# draw the Front buildings
for i in range(len(self.buildings)):
pygame.draw.rect(windowSurface, self.color, self.buildings[i])
1 个回答
你的问题很可能出在这里:
# move all buildings on layer at set speed
for building in self.buildings:
# if the building is off the screen, trash it. If not, move it to the
# right at the objects speed.
if building.right < 0:
self.buildings.remove(building)
else:
building.left -= self.layerspeed
你在遍历列表的时候使用了remove
,这会导致跳过下一个建筑物。所以不是右边的建筑物移动得更快,而是左边的建筑物被跳过了。
你可以通过这个简单的例子自己看看:
a = [2, 3, 4, 1.5, 6, 8, 3.2]
for element in a:
if element == 4:
a.remove(element)
else:
print element
试试看,你会发现不仅4
不会被打印出来,1.5
也会被跳过。
一个比较好的做法是,先遍历所有建筑物,看看哪些需要被移除,然后再把它们全部移除,最后再移动剩下的建筑物。
你可以查看这个链接,里面有一些不错的建议。
另外,你在倒计时的部分更新了两次,第一次在第47行,第二次在第58行。这样做有什么特别的原因吗?