2017-11-18 4 views
1

私は、pygameドキュメントでスプライトの.rect属性が.image属性と同じ幅と同じ高さで初期化されることが多いことを発見しました。sprite.rectとsprite.image座標の起点間のオフセット

ただし、.rectが.imageよりも大きくなるように、または.imageと.rectの両方の起点(topleft corners)が常に同じになるように、縦または横の高さを変更できます。

ここに私の質問があります: スプライトの.rectと.rectのスプライトの起点(つまりコーナー)の間にオフセットを作成する方法はありますか? .rectが

  • が使用してしまうたびに更新される(例えば.collide_rect)第二のRect属性を作成し、使用して

    • 私はあなたがすることでこれを回避することができます知っています提供されるイメージの透明度

    しかし、これらの方法は非常に非効率的であり、私は本当に「はい/いいえ」の答えに感謝します。

    私は公式の文書を何時間も検索しましたが、私はそのようなオフセットを作成する方法を見つけられなかったので、私の質問に対する答えは「いいえ」です(.inflate_ip()の方法でさえドキュメントの中に書かれているように正しい場所の中心を保持しません)。

  • +0

    私は.image'は 'topleft'を値を使用することはありません'を知っている - それだけの幅と高さを返すために、 'Rect'を使用しています。 '.image'をblitするには、位置を保持する' .rect'( 'topleft')を使用する必要があります。 – furas

    答えて

    0

    あなたはスプライトクラスに追加offset属性(Vector2)を得た後、forループでスプライトを反復して、画像を、ブリットしているとき.rect.topleft位置にこのoffsetを追加することができます。完全を期すために

    import pygame as pg 
    from pygame.math import Vector2 
    
    
    class Player(pg.sprite.Sprite): 
    
        def __init__(self, pos, *groups): 
         super().__init__(*groups) 
         self.image = pg.Surface((220, 120)) 
         self.image.fill(pg.Color('steelblue2')) 
         self.rect = self.image.get_rect(center=pos) 
         self.rect.inflate_ip(-42, -72) # Make the rect smaller. 
         self.vel = Vector2(0, 0) 
         self.pos = Vector2(pos) 
         # Offset is half of the inflation size, 
         # so that the rect will be centered. 
         self.offset = Vector2(-21, -36) 
    
        def update(self): 
         self.pos += self.vel 
         self.rect.center = self.pos 
    
    
    def main(): 
        screen = pg.display.set_mode((640, 480)) 
        clock = pg.time.Clock() 
        all_sprites = pg.sprite.Group() 
        player = Player((300, 200), all_sprites) 
    
        done = False 
    
        while not done: 
         for event in pg.event.get(): 
          if event.type == pg.QUIT: 
           done = True 
          elif event.type == pg.KEYDOWN: 
           if event.key == pg.K_d: 
            player.vel.x = 5 
          elif event.type == pg.KEYUP: 
           if event.key == pg.K_d: 
            player.vel.x = 0 
    
         all_sprites.update() 
    
         screen.fill((30, 30, 30)) 
         # Assign `blit` to a local variable to improve the performance. 
         screen_blit = screen.blit 
         for sprite in all_sprites: 
          # Now blit the sprites at topleft + offset. 
          screen_blit(sprite.image, sprite.rect.topleft+sprite.offset) 
          pg.draw.rect(screen, (250, 30, 0), sprite.rect, 2) 
    
         pg.display.flip() 
         clock.tick(30) 
    
    
    if __name__ == '__main__': 
        pg.init() 
        main() 
        pg.quit() 
    

    、ここでは第二と解決策だ、「ヒットボックス」RECTとあなたはpygame.sprite.spritecollideのような衝突検出機能の一つに渡すことができるカスタムcollidedコールバック関数をスケールされました。

    import pygame as pg 
    from pygame.math import Vector2 
    
    
    class Player(pg.sprite.Sprite): 
    
        def __init__(self, pos, *groups): 
         super().__init__(*groups) 
         self.image = pg.Surface((70, 40)) 
         self.image.fill(pg.Color('steelblue4')) 
         self.rect = self.image.get_rect(center=pos) 
         # A inflated rect as the hitbox. 
         self.hitbox = self.rect.copy() 
         self.hitbox.inflate_ip(-42, -22) 
         self.vel = Vector2(0, 0) 
         self.pos = Vector2(pos) 
    
        def update(self): 
         self.pos += self.vel 
         self.rect.center = self.pos 
         self.hitbox.center = self.pos # Also update the hitbox coords. 
    
    
    def collided(sprite, other): 
        """Check if the hitboxes of the two sprites collide.""" 
        return sprite.hitbox.colliderect(other.hitbox) 
    
    
    def main(): 
        screen = pg.display.set_mode((640, 480)) 
        clock = pg.time.Clock() 
        all_sprites = pg.sprite.Group() 
        player = Player((300, 200), all_sprites) 
        enemies = pg.sprite.Group(
         Player((100, 250), all_sprites), 
         Player((400, 300), all_sprites), 
         ) 
    
        done = False 
    
        while not done: 
         for event in pg.event.get(): 
          if event.type == pg.QUIT: 
           done = True 
          elif event.type == pg.MOUSEMOTION: 
           player.pos = event.pos 
    
         all_sprites.update() 
         # Pass the custom collided callback function to spritecollide. 
         collided_sprites = pg.sprite.spritecollide(
          player, enemies, False, collided) 
         for sp in collided_sprites: 
          print('Collision', sp) 
    
         screen.fill((30, 30, 30)) 
    
         all_sprites.draw(screen) 
         for sprite in all_sprites: 
          # Draw rects and hitboxes. 
          pg.draw.rect(screen, (0, 230, 0), sprite.rect, 2) 
          pg.draw.rect(screen, (250, 30, 0), sprite.hitbox, 2) 
    
         pg.display.flip() 
         clock.tick(30) 
    
    
    if __name__ == '__main__': 
        pg.init() 
        main() 
        pg.quit() 
    
    +0

    公式の文書では、私は"コールバック関数 "の使用を理解していませんでした。確かにそれは素晴らしいことです、それは私の質問(それはまだグループの検出を使用することができますので)よりもはるかに効率的な.hitbox属性の使用を可能にします。私は信じています)。ありがとう。 –

    関連する問題