Python 具有Rect类的PyGame中与帧无关的运动问题
我正在用PyGame编写一个简单的游戏,但是我遇到了一个问题,那就是如何让事情正常运行。我对游戏编程没有经验,所以我不确定我的方法是否正确 我有一个班级舞会,它扩展了PyGame的精灵课程。每一帧,球对象都应该在屏幕上移动。我使用的是与帧无关的(?)/基于时间的运动,每次都由PyGame的时钟对象返回时间增量。比如,Python 具有Rect类的PyGame中与帧无关的运动问题,python,pygame,Python,Pygame,我正在用PyGame编写一个简单的游戏,但是我遇到了一个问题,那就是如何让事情正常运行。我对游戏编程没有经验,所以我不确定我的方法是否正确 我有一个班级舞会,它扩展了PyGame的精灵课程。每一帧,球对象都应该在屏幕上移动。我使用的是与帧无关的(?)/基于时间的运动,每次都由PyGame的时钟对象返回时间增量。比如, class Ball(pygame.sprite.Sprite): # . . . def update(self, delta): self.rect.
class Ball(pygame.sprite.Sprite):
# . . .
def update(self, delta):
self.rect.x += delta * self.speed # speed is pixels per second
self.rect.y += delta * self.speed # ... or supposed to be, anyway
。。。而且
class Game(object):
# . . .
def play(self):
self.clock = pygame.time.Clock()
while not self.done:
delta = self.clock.tick(self.fps) / 1000.0 # time is seconds
self.ball.update(delta)
PyGame的精灵类由跟踪精灵位置的Rect对象(Rect)支持。每当值更新时,Rect的坐标会自动转换为整数。所以,我的问题是,每次调用update()时,任何额外的像素移动都会丢失,而不是像应该的那样随时间累积。以“每秒像素数”表示的速度在这种情况下并不准确。更糟糕的是,如果每帧的移动量小于一个像素,球在这些帧中根本不会移动,因为球总是向下舍入到零。(即,如果ppsclass Ball(pygame.sprite.Sprite):
# . . .
def update(self, delta):
self.x += delta * self.speed
self.y += delta * self.speed
def getx(self):
return self._x
def setx(self, val):
self._x = val # this can be a float
self.rect.x = val # this is converted to int
def gety(self):
return self._y
def sety(self, val):
self._y = val # this can be a float
self.rect.y = val # this is converted to int
x = property(getx,setx)
y = property(gety,sety)
但这最终会造成混乱:当x和y发生变化时,很容易更新rect对象,但反过来就不行了。更不用说Rect对象还有很多其他可以操作的有用坐标(如centerx、top、bottomleft等——这就是为什么人们仍然希望直接移动Rect的原因)。我将或多或少地不得不在Ball中重新实现整个Rect类,在它将浮动传递给Rect对象之前存储它们,或者只基于x和y执行所有操作,以牺牲Rect类的一些便利性为代价
有没有更聪明的方法来处理这个问题?我不知道你是否还需要答案,但我早就知道了,我想我应该给这个问题一个答案,因为我在试图弄清楚到底发生了什么时遇到了这个问题。(顺便说一句,谢谢你帮我确认这个问题。) 您可以使用Python的
round
函数。基本上,只要把你想要的东西扔进那个函数,它就会给出一个适当的四舍五入数
我让它工作的第一个方法是这样的:
x = box['rect'].x
if leftDown:
x -= 300 * deltaTime
if rightDown:
x += 300 * deltaTime
box['rect'].x = round(x)
(其中,我的deltaTime是一个浮点,是一秒的一小部分。)
只要在应用前将通过round
函数获得的浮点值放入,就可以了。它不必使用单独的变量或任何东西
值得注意的是,您不能绘制像素的分数。曾经如果您熟悉Lite Brite,那么像素就是这样工作的,它是一个单独点亮的灯。这就是为什么您最后使用的数字必须是整数。我不确定您的解决方案是否有任何效果。看起来您正试图使用这个额外的
x
变量来跟踪微小的像素分数,但第一行用存储在Rect对象的x
值中的整数值覆盖它们。它与默认行为略有不同,因为您显式使用round()
函数,而不是强制转换为int
(Rect在默认情况下显然是这样做的)。不管怎样,对于我的问题,结果证明这并不像我想象的那么大。我在别处清理了我的代码,移动问题自行解决了。Rect存储在那里的字典中x
获取该矩形的x位置的副本。关键点调整该位置,其中我的deltaTime是一个浮动。因此,x
以浮点形式结束。最后,根据我的理解,浮点正确舍入,Rect截断了0。它至少对我和我的简单移动盒有效。我也可以做一些类似于box['rect']+=round(300*deltaTime)
。我认为这一切都要归结于你自己。很高兴你了解了自己的具体情况。:)