速度が1未満の場合、スプライトがウィンドウの境界に貼り付いた[重複]

Dec 28 2020

ゲームで動く雲を作ろうとしていますが、雲の速度を1未満に設定すると、雲のスプライトが境界線にくっつきます。雲の一部がすでに画面の外にある場合は、雲を動かし続けたいと思います。rectのxが0に等しい場合、スプライトがスタックしていることがわかりました。修正するにはどうすればよいですか?

私のコード:

class Cloud(pygame.sprite.Sprite):
    def __init__(self):
        super(Cloud, self).__init__()
        images = [load_image(f"cloud{i}.png") for i in range(1, 5)]
        self.image = random.choice(images)
        self.rect = self.image.get_rect()

        self.rect.x = random.randrange(WIDTH - self.rect.w)
        self.rect.y = random.randrange(HEIGHT - self.rect.h)

        self.vel = 10 / FPS  # It returns value less then 1

    def update(self, event=None):
        if not event:
            self.rect.x -= self.vel

回答

2 Rabbid76 Dec 28 2020 at 21:01

pygame.Rect画面上の領域を表すことになっているため、pygame.Rectオブジェクトは整数データのみを格納できます。

Rectオブジェクトの座標はすべて整数です。[...]

オブジェクトの新しい位置がRectオブジェクトに設定されると、座標の小数部分が失われます。

self.rect.x -= self.vel

浮動小数点の精度でオブジェクトの位置を保存する場合は、オブジェクトの場所をそれぞれ別の変数の属性に保存し、オブジェクトを同期する必要がありpygame.Rectます。round座標とそれを.topleft長方形の位置(例)に割り当てます。

class Cloud(pygame.sprite.Sprite):
    def __init__(self):
        super(Cloud, self).__init__()
        images = [load_image(f"cloud{i}.png") for i in range(1, 5)]
        self.image = random.choice(images)
        self.rect = self.image.get_rect()

        self.rect.x = random.randrange(WIDTH - self.rect.w)
        self.rect.y = random.randrange(HEIGHT - self.rect.h)
        self.x, self.y = self.rect.topleft

        self.vel = 10 / FPS  # It returns value less then 1

    def update(self, event=None):
        if not event:
            self.x -= self.vel
            self.rect.topleft = round(self.x), round(self.y)