繁体   English   中英

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

[英]Frame-independent movement issue in PyGame with Rect class

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

我有一个Ball类,它扩展了PyGame的Sprite类。 每帧,Ball对象都应该在屏幕上移动。 我正在使用与帧无关的(?)/基于时间的运动,每次都由PyGame的Clock对象返回的时间增量。 如,

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的Sprite类由跟踪该Sprite位置的Rect对象(rect)支持。 每当更新值时,Rect的坐标都会自动转换为整数。 所以,我的问题是,每次调用update()时,像素多余的运动都将丢失,而不是随时间累积。 这样,“每秒像素数”的速度是不准确的。 更糟糕的是,如果每帧的移动量少于一个像素,则这些帧的球根本不会移动,因为它总是四舍五入为零。 (即,如果pps <fps,则不移动)

我不确定如何处理。 我尝试向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,像素就是单个照亮的光源,它可以这种方式工作。 这就是为什么最后使用的数字必须是整数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM