Python 具有Rect类的PyGame中与帧无关的运动问题

Python 具有Rect类的PyGame中与帧无关的运动问题,python,pygame,Python,Pygame,我正在用PyGame编写一个简单的游戏,但是我遇到了一个问题,那就是如何让事情正常运行。我对游戏编程没有经验,所以我不确定我的方法是否正确 我有一个班级舞会,它扩展了PyGame的精灵课程。每一帧,球对象都应该在屏幕上移动。我使用的是与帧无关的(?)/基于时间的运动,每次都由PyGame的时钟对象返回时间增量。比如, class Ball(pygame.sprite.Sprite): # . . . def update(self, delta): self.rect.

我正在用PyGame编写一个简单的游戏,但是我遇到了一个问题,那就是如何让事情正常运行。我对游戏编程没有经验,所以我不确定我的方法是否正确

我有一个班级舞会,它扩展了PyGame的精灵课程。每一帧,球对象都应该在屏幕上移动。我使用的是与帧无关的(?)/基于时间的运动,每次都由PyGame的时钟对象返回时间增量。比如,

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()时,任何额外的像素移动都会丢失,而不是像应该的那样随时间累积。以“每秒像素数”表示的速度在这种情况下并不准确。更糟糕的是,如果每帧的移动量小于一个像素,球在这些帧中根本不会移动,因为球总是向下舍入到零。(即,如果pps 我不知道该怎么处理。我尝试向Ball添加单独的x和y值,这些值不是强制为整数,并在每次更改时更新rect。这样,x和y值将像素的分数累加为正常值。如:

class 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)
。我认为这一切都要归结于你自己。很高兴你了解了自己的具体情况。:)