Firing bullets from a rotating gun

后端 未结 2 2053
甜味超标
甜味超标 2020-12-04 03:30

My question is connected to this question: rotating gun with restricted movement

What calculations do you need to do to get bullets firing from the gun muzzle?

相关标签:
2条回答
  • 2020-12-04 03:48

    I achieved what I needed to do with thefollowing code which is the same as above with a very slight modification which is explained in the code. @skrx answer and the comment by Nick A. aided me to achieve this.

    def gun_radar(self):
    
        for p in self.gameobjects:
    
            if "R" in p.name or "L" in p.name:
    
                if abs(p.rect.centerx - self.hero.rect.centerx) < p.radar and abs(p.rect.centery - self.hero.rect.centery) < p.radar:  # if hero within radar
    
                    p.vec_to_target = pygame.math.Vector2(self.hero.rect.center) - p.rect.center
                    p.direction = p.orig_direction.rotate(p.current_angle)
                    p.orientation = p.vec_to_target.dot(p.direction)
    
                    if p.orientation > 2:
                        p.current_angle += 1
                    elif p.orientation < -2:
                        p.current_angle -= 1
    
                    p.current_angle = p.clamp(p.current_angle, p.clamp_min, p.clamp_max)
    
                    p.gun_rotate(-p.current_angle)
    
                    p.timer -= 1  #count down the timer. when zero calculate vector and add bullet to fired_blts
    
                    if p.timer<= 0:
    
                        w, h = p.rect.center
    
                        # adjust for the distance fromm the gun center to the gun muzzle
    
                        w = w + math.cos(math.radians(p.current_angle)) * 28
                        h = h + math.sin(math.radians(p.current_angle)) * 28
                        bullet = Bombullet(bulletimage, w, h)  # create the bullet
    
                        # calculate the velocity
    
                        bullet.xvel = bullet.speed * math.cos(math.radians(p.current_angle))
                        bullet.yvel = bullet.speed * math.sin(math.radians(p.current_angle))
    
                        self.fired_blts.add(bullet)
    
                        p.timer = 100
    
    0 讨论(0)
  • 2020-12-04 04:05

    Here's an example of a firing cannon. You just have to pass the current angle and the rect.center of the cannon to the newly created bullet and then rotate its image and velocity vector in the __init__ method.

    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')
    BG_COLOR = pg.Color('darkseagreen4')
    
    
    class Bullet(pg.sprite.Sprite):
    
        def __init__(self, pos, angle):
            super(Bullet, self).__init__()
            self.image = pg.Surface((20, 11), pg.SRCALPHA)
            pg.draw.rect(self.image, pg.Color('grey11'), [0, 0, 13, 11])
            pg.draw.polygon(
                self.image, pg.Color('grey11'), [(13, 0), (20, 5), (13, 10)])
            self.image = pg.transform.rotate(self.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(80, 0).rotate(angle)
            # Use the offset to change the starting position.
            self.pos = Vector2(pos) + offset
            self.velocity = Vector2(5, 0)
            self.velocity.rotate_ip(angle)
    
        def update(self):
            self.pos += self.velocity
            self.rect.center = self.pos
    
    
    def main():
        clock = pg.time.Clock()
        # The cannon image and rect.
        surf = pg.Surface((40, 22), pg.SRCALPHA)
        surf.fill(pg.Color('grey27'))
        pg.draw.rect(surf, pg.Color('grey11'), [30, 6, 10, 10])
        orig_surf = surf
        rect = surf.get_rect(center=(320, 240))
        angle = 0  # Angle of the cannon.
        # 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
                if event.type == pg.MOUSEBUTTONDOWN:
                    if event.button == 1:  # Left button fires bullet.
                        # Fire a bullet from cannon center with current angle.
                        bullet_group.add(Bullet(rect.center, angle))
    
            bullet_group.update()
            # Find angle to target (mouse pos).
            x, y = Vector2(pg.mouse.get_pos()) - rect.center
            angle = math.degrees(math.atan2(y, x))
            # Rotate the cannon image.
            surf = pg.transform.rotate(orig_surf, -angle)
            rect = surf.get_rect(center=rect.center)
    
            # Draw
            screen.fill(BG_COLOR)
            bullet_group.draw(screen)
            screen.blit(surf, rect)
            txt = FONT.render('angle {:.1f}'.format(angle), True, BLACK)
            screen.blit(txt, (10, 10))
            pg.draw.line(
                screen, pg.Color(150, 60, 20), rect.center, pg.mouse.get_pos(), 2)
            pg.display.update()
    
            clock.tick(30)
    
    if __name__ == '__main__':
        main()
        pg.quit()
    

    You can also use math.cos and sin to calculate the offset.

    run = math.cos(math.radians(angle)) * 80
    rise = math.sin(math.radians(angle)) * 80
    offset = run, rise
    
    0 讨论(0)
提交回复
热议问题