从旋转枪中射击子弹

时间:2017-02-16 16:57:56

标签: python-2.7 pygame

我的问题与这个问题有关: rotating gun with restricted movement

你需要做些什么计算才能从枪口射出子弹?

我的代码在下面给出

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

当英雄进入枪的圆形区域时,它会被激活,子弹从枪的中心射出。

我用

移动子弹
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
子弹以正确的方向更新并射击,但是从枪的中心射击。如何将拍摄点移动到枪口?

2 个答案:

答案 0 :(得分:1)

这是一个射击大炮的例子。您只需将当前角度和大炮的rect.center传递给新创建的项目符号,然后在__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()

您也可以使用math.cos和sin来计算偏移量。

run = math.cos(math.radians(angle)) * 80
rise = math.sin(math.radians(angle)) * 80
offset = run, rise

答案 1 :(得分:1)

我通过下面的代码实现了我需要做的事情,并且代码中对此进行了非常细微的修改。 @skrx的答案和Nick A.的评论帮助我实现了这个目标。

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