Machine gun shooting

My question is related to this question: revolving pistol with limited movement

What calculations do you need to get cannon bullets?

my code is below

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)

                self.blt_timer -= 1  #count down the timer. when zero calculate vector and add bullet to fired_blts

                if self.blt_timer<= 0:
                    w, h = p.rect.center
                    angle_in_rad = p.current_angle * (math.pi) / 180
                    w = w + math.cos(angle_in_rad)
                    h = h + math.sin(-angle_in_rad)
                    bullet = Bombullet(bulletimage, w, h)


                    bullet.xvel = bullet.speed * math.cos(angle_in_rad)
                    bullet.yvel = bullet.speed * math.sin(angle_in_rad)

                    bullet.rect.x += bullet.xvel
                    bullet.rect.y += bullet.yvel

                    self.fired_blts.add(bullet)
                    self.blt_timer = 100

      

when the hero hits the round area of ​​the pistol, it activates and the bullet fires from the center of the pistol.

I move the bullet with

def move(self):

        self.rect.x += self.xvel

        self.rect.y += self.yvel
        print self.rect.x, self.rect.y, self.life
        self.life -= 1

      

the bullet refreshes and fires in the right direction, but fires from the center of the pistol. How to transfer the shooting point to the face?

+1


source to share


2 answers


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

.

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

      

+1


source


I achieved what I needed to do with the following code, which was the same as above, with very little modification explained in the code. @skrx's answer and Nick A.'s comment helped me 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

      

+1


source







All Articles