【问题标题】:Pygame Rotated ShootingPygame旋转射击
【发布时间】:2019-01-08 15:37:03
【问题描述】:

我和几个朋友一直在编写一个有趣的新射击机制。为了让它发挥作用,我们需要朝玩家面对的方向射击。 Sprite 正在使用 Pygame.Transform.Rotate 进行旋转。我们怎样才能找到一个角度,然后朝那个方向发射子弹?

这是我们的 Sprite 旋转代码

 char_image_number = pygame.mouse.get_pressed()

    if char_image_number == (0, 0, 0):
            char_image = pygame.image.load(player_none).convert_alpha()
            char_image = pygame.transform.rotate(char_image, angle)
            screen.blit(background, (0,0))
            screen.blit(char_image,(540, 260))
            pygame.display.update()
    elif char_image_number == (1, 0, 0):
            print (angle)
            char_image = pygame.image.load(player_left).convert_alpha()
            angle+=1
            char_image = pygame.transform.rotate(char_image, angle)
            screen.blit(background, (0,0))
            screen.blit(char_image,(540, 260))
            pygame.display.update()
    elif char_image_number == (0, 0, 1):
            print (angle)
            angle-=1
            char_image = pygame.image.load(player_right).convert_alpha()

            char_image=pygame.transform.rotate(char_image, angle)
            screen.blit(background, (0,0))
            screen.blit(char_image,(540, 260))

            pygame.display.update()

    elif char_image_number == (1, 0, 1):
            char_image = pygame.image.load(player_both).convert_alpha()
            char_image = pygame.transform.rotate(char_image, angle)
            screen.blit(background, (0,0))
            screen.blit(char_image,(540, 260))
            pygame.display.update()

我们如何以玩家面对的角度射击?

【问题讨论】:

  • 使用带有angle 和一些speed 值的三角函数得到move_xmove_y
  • 您能否将我链接到教程或文档?我对向量很熟悉,但不知道如何在代码中做到这一点。

标签: python pygame


【解决方案1】:

这是一个快速的可执行示例,说明如何使用矢量数学来做你想做的事。

import pygame

class Player(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.Surface((32, 32))
        self.image.fill((0, 0, 0))
        self.image.set_colorkey((0, 0, 0))
        pygame.draw.polygon(self.image, pygame.Color('dodgerblue'), ((0, 0), (32, 16), (0, 32)))
        self.org_image = self.image.copy()
        self.angle = 0
        self.direction = pygame.Vector2(1, 0)
        self.rect = self.image.get_rect(center=(200, 200))
        self.pos = pygame.Vector2(self.rect.center)

    def update(self, events, dt):
        for e in events:
            if e.type == pygame.KEYDOWN:
                if e.key == pygame.K_SPACE:
                    self.groups()[0].add(Projectile(self.rect.center, self.direction.normalize()))
        pressed = pygame.key.get_pressed()
        if pressed[pygame.K_a]:
            self.angle += 3
        if pressed[pygame.K_d]:
            self.angle -= 3

        self.direction = pygame.Vector2(1, 0).rotate(-self.angle)
        self.image = pygame.transform.rotate(self.org_image, self.angle)
        self.rect = self.image.get_rect(center=self.rect.center)

class Projectile(pygame.sprite.Sprite):
    def __init__(self, pos, direction):
        super().__init__()
        self.image = pygame.Surface((8, 8))
        self.image.fill((0, 0, 0))
        self.image.set_colorkey((0, 0, 0))
        pygame.draw.circle(self.image, pygame.Color('orange'), (4, 4), 4)
        self.rect = self.image.get_rect(center=pos)
        self.direction = direction
        self.pos = pygame.Vector2(self.rect.center)

    def update(self, events, dt):
        self.pos += self.direction * dt
        self.rect.center = self.pos
        if not pygame.display.get_surface().get_rect().contains(self.rect):
            self.kill()

def main():
    pygame.init()
    screen = pygame.display.set_mode((500, 500))
    sprites = pygame.sprite.Group(Player())
    clock = pygame.time.Clock()
    dt = 0

    while True:
        events = pygame.event.get()
        for e in events:
            if e.type == pygame.QUIT:
                return
        sprites.update(events, dt)
        screen.fill((30, 30, 30))
        sprites.draw(screen)
        pygame.display.update()
        dt = clock.tick(60)

if __name__ == '__main__':
    main()

注意:您似乎每帧都在加载播放器的图像。您不应该这样做,因为这非常慢。只需加载每个图像一次。此外,最好在您的代码中只有 一个 点调用pygame.display.update(),因为您应该确保每帧只调用一次。

【讨论】:

    【解决方案2】:

    你有angle 度数,所以试试这个:

    import math
    
    # angle examples 
    for angle in [0, 30, 45, 60, 0+90, 30+90, 45+90, 60+90, 0+180, 30+180, 45+180, 60+180, 0+270, 30+270, 45+270, 60+270]: 
    
        bullet_speed = 10
    
        bullet_move_x = bullet_speed * math.cos( math.radians(angle) )
        bullet_move_y = -bullet_speed * math.sin( math.radians(angle) )
    
        print angle, bullet_move_x, bullet_move_y
    

    现在您可以将bullet_move_xbullet_move_y 添加到子弹位置。

    为了获得更好的结果,请将子弹位置保持为float,并在您使用子弹时转换为int

    【讨论】:

      【解决方案3】:

      这个例子演示了如何利用矢量来控制子弹的位置、速度以及起始偏移。

      在 while 循环中,我们使用math.atan2 计算与目标的角度,然后将其用于旋转大炮图像并传递给Bullet 实例。在Bullets 的__init__ 方法中,我们将偏移矢量、速度矢量和精灵图像旋转角度。

      为了移动子弹,我们将(旋转的)速度向量添加到位置向量,并将矩形位置设置为pos 向量。 rect 必须移动,因为它保持 blit 位置并用于碰撞检测。

      import math
      import pygame as pg
      from pygame.math import Vector2
      
      
      pg.init()
      screen = pg.display.set_mode((640, 480))
      FONT = pg.font.Font(None, 24)
      BLACK = pg.Color('black')
      BULLET_IMAGE = pg.Surface((20, 11), pg.SRCALPHA)
      pg.draw.polygon(BULLET_IMAGE, pg.Color('grey11'), [(0, 0), (20, 5), (0, 11)])
      
      
      class Bullet(pg.sprite.Sprite):
      
          def __init__(self, pos, angle):
              super(Bullet, self).__init__()
              self.image = pg.transform.rotate(BULLET_IMAGE, -angle)
              self.rect = self.image.get_rect(center=pos)
              # To apply an offset to the start position,
              # create another vector and rotate it as well.
              offset = Vector2(40, 0).rotate(angle)
              # Add the offset vector to the position vector.
              self.pos = Vector2(pos) + offset  # Center of the sprite.
              # Rotate the velocity vector (9, 0) by the angle.
              self.velocity = Vector2(9, 0).rotate(angle)
      
          def update(self):
              # Add velocity to pos to move the sprite.
              self.pos += self.velocity
              self.rect.center = self.pos
      
      
      def main():
          clock = pg.time.Clock()
          # The cannon image and rect.
          cannon_img = pg.Surface((60, 22), pg.SRCALPHA)
          pg.draw.rect(cannon_img, pg.Color('grey19'), [0, 0, 35, 22])
          pg.draw.rect(cannon_img, pg.Color('grey19'), [35, 6, 35, 10])
          orig_cannon_img = cannon_img  # Store orig image to preserve quality.
          cannon = cannon_img.get_rect(center=(320, 240))
          angle = 0
          # Add bullets to this group.
          bullet_group = pg.sprite.Group()
      
          playing = True
          while playing:
              for event in pg.event.get():
                  if event.type == pg.QUIT:
                      playing = False
                  elif event.type == pg.MOUSEBUTTONDOWN:
                      # Left button fires a bullet from cannon center with
                      # current angle. Add the bullet to the bullet_group.
                      if event.button == 1:
                          bullet_group.add(Bullet(cannon.center, angle))
      
              bullet_group.update()
              # Find angle to target (mouse pos).
              x, y = Vector2(pg.mouse.get_pos()) - cannon.center
              angle = math.degrees(math.atan2(y, x))
              # Rotate the cannon image.
              cannon_img = pg.transform.rotate(orig_cannon_img, -angle)
              cannon = cannon_img.get_rect(center=cannon.center)
      
              # Draw
              screen.fill(pg.Color('darkseagreen4'))
              bullet_group.draw(screen)
              screen.blit(cannon_img, cannon)
              txt = FONT.render('angle {:.1f}'.format(angle), True, BLACK)
              screen.blit(txt, (10, 10))
              pg.draw.line(
                  screen, pg.Color(150, 60, 20),
                  cannon.center, pg.mouse.get_pos(), 2)
              pg.display.update()
      
              clock.tick(30)
      
      if __name__ == '__main__':
          main()
          pg.quit()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-13
        • 2015-04-14
        • 2016-07-31
        • 1970-01-01
        • 2023-01-21
        • 1970-01-01
        相关资源
        最近更新 更多