python - 如何在pygame中从面向光标方向的角色发射子弹?

标签 python pygame

在我的游戏中,问题是子弹仅从一个地方射出,即从中心射出。当我的玩家沿光标方向旋转时,即使玩家旋转并沿玩家面向的方向沿直线行进,我也希望子弹从玩家顶部发射,当玩家沿光标方向旋转时.

正如您可以在此处看到的,子弹始终朝同一方向,并且始终从同一位置射出。

Image 1 Image 2

我尝试使用 getpos() 方法获取光标位置,并尝试从玩家坐标中减去,但未能得到结果。

我认为问题出在 Rotator 类的 def shot(self) 方法中,即使飞船一直在旋转,我也需要获取飞船尖端的坐标。

import math 
import random 
import os 
import pygame as pg 
import sys

pg.init()
height=650
width=1200

os_x = 100
os_y = 45
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (os_x,os_y)

screen = pg.display.set_mode((width,height),pg.NOFRAME)
screen_rect = screen.get_rect()
background=pg.image.load('background.png').convert()
background = pg.transform.smoothscale(pg.image.load('background.png'), (width,height))
clock = pg.time.Clock()
running = True


class Mob(pg.sprite.Sprite):
    def __init__(self):
        pg.sprite.Sprite.__init__(self)
        self.image = pg.image.load('enemy.png').convert_alpha()
        self.image = pg.transform.smoothscale(pg.image.load('enemy.png'), (33,33))
        self.rect = self.image.get_rect()
        self.rect.x = random.randrange(width - self.rect.width)
        self.rect.y = random.randrange(-100, -40)
        self.speedy = random.randrange(1, 8)
        self.speedx = random.randrange(-3, 3)

    def update(self):
        self.rect.x += self.speedx
        self.rect.y += self.speedy
        if self.rect.top > height + 10 or self.rect.left < -25 or self.rect.right > width + 20:
            self.rect.x = random.randrange(width - self.rect.width)
            self.rect.y = random.randrange(-100, -40)
            self.speedy = random.randrange(1, 8)


class Rotator(pg.sprite.Sprite):
    def __init__(self, screen_rect):
        pg.sprite.Sprite.__init__(self)
        self.screen_rect = screen_rect
        self.master_image = pg.image.load('spaceship.png').convert_alpha()
        self.master_image = pg.transform.smoothscale(pg.image.load('spaceship.png'), (33,33))
        self.image = self.master_image.copy()
        self.rect = self.image.get_rect(center=[width/2,height/2])
        self.delay = 10
        self.timer = 0.0
        self.angle = 0
        self.distance = 0
        self.angle_offset = 0

    def get_angle(self):
      mouse = pg.mouse.get_pos()
      offset = (self.rect.centerx - mouse[0], self.rect.centery - mouse[1])
      self.angle = math.degrees(math.atan2(*offset)) - self.angle_offset
      old_center = self.rect.center
      self.image = pg.transform.rotozoom(self.master_image, self.angle,1)
      self.rect = self.image.get_rect(center=old_center)
      self.distance = math.sqrt((offset[0] * offset[0]) + (offset[1] * offset[1]))


    def update(self):
      self.get_angle()
      self.display = 'angle:{:.2f} distance:{:.2f}'.format(self.angle, self.distance)
      self.dx = 1
      self.dy = 1
      self.rect.clamp_ip(self.screen_rect)


    def draw(self, surf):
        surf.blit(self.image, self.rect)

    def shoot(self):
        bullet = Bullet(self.rect.centerx, self.rect.centery)
        all_sprites.add(bullet)
        bullets.add(bullet)


class Bullet(pg.sprite.Sprite):
    def __init__(self, x, y):
        pg.sprite.Sprite.__init__(self)
        self.image = pg.image.load('bullet.png').convert_alpha()
        self.image = pg.transform.smoothscale(pg.image.load('bullet.png'), (10,10))
        self.rect = self.image.get_rect()
        self.rect.y = y
        self.rect.x = x
        self.speedy = -8

    def update(self):
        self.rect.y += self.speedy
        # kill if it moves off the top of the screen
        if self.rect.bottom < 0:
            self.kill()


all_sprites = pg.sprite.Group()
bullets = pg.sprite.Group()
mobs = pg.sprite.Group()
rotator = Rotator(screen_rect)
all_sprites.add(rotator)

for i in range(5):
    m = Mob()
    all_sprites.add(m)
    mobs.add(m)

while running:
    keys = pg.key.get_pressed()
    for event in pg.event.get():
        if event.type == pg.QUIT:
            sys.exit()
            pygame.quit()
        if event.type == pg.MOUSEBUTTONDOWN:
            rotator.shoot()


    screen.blit(background, [0, 0])
    all_sprites.update()

    hits = pg.sprite.groupcollide(mobs, bullets, True, True)
    for hit in hits:
        m = Mob()
        all_sprites.add(m)
        mobs.add(m)

    hits = pg.sprite.spritecollide(rotator, mobs, False)
    if hits:
        running = False

    all_sprites.draw(screen)
    clock.tick(60)
    pg.display.update()

最佳答案

参见Shooting a bullet in pygame in the direction of mousecalculating direction of the player to shoot pygame 。 当按下鼠标按钮时,将鼠标位置传递给 rotator.shoot():

if event.type == pg.MOUSEBUTTONDOWN:
    rotator.shoot(event.pos)

计算从旋转器到鼠标位置的方向并将其传递给新子弹对象的构造函数:

def shoot(self, mousepos):
    dx = mousepos[0] - self.rect.centerx
    dy = mousepos[1] - self.rect.centery
    if abs(dx) > 0 or abs(dy) > 0:
        bullet = Bullet(self.rect.centerx, self.rect.centery, dx, dy)
        all_sprites.add(bullet)
        bullets.add(bullet)

使用pygame.math.Vector2存储子弹的当前位置和子弹的标准化方向( Unit vector ):

class Bullet(pg.sprite.Sprite):
    def __init__(self, x, y, dx, dy):
        pg.sprite.Sprite.__init__(self)
        self.image = pg.transform.smoothscale(pg.image.load('bullet.png').convert_alpha(), (10,10))
        self.rect = self.image.get_rect()
        self.rect.center = (x, y)
        self.speed = 8
        self.pos = pg.math.Vector2(x, y)
        self.dir = pg.math.Vector2(dx, dy).normalize()

update()中计算子弹的新位置(self.pos += self.dir * self.speed)并更新.rect 属性由新位置决定。
.kill() 子弹离开屏幕时。可以通过self.rect.colliderect()检查:

class Bullet(pg.sprite.Sprite):

    # [...]

     def update(self):
        
        self.pos += self.dir * self.speed
        self.rect.center = (round(self.pos.x), round(self.pos.y))

        if not self.rect.colliderect(0, 0, width, height):
            self.kill()

关于python - 如何在pygame中从面向光标方向的角色发射子弹?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57243332/

相关文章:

python - 当变量值更改时,文本对象不会在屏幕上更新

python - 在python中不递归地求和嵌套列表

python - 在 Matplotlib 上显示 x 轴 - Python

python - df.iloc() 的赋值返回 nan

python - 我如何实时更新pygame中的时间

python - 没有 while True 循环的 Pygame 播放列表

python - Django 1.2 对象级权限 - 第三方解决方案?

python - 单元测试 : assert exception-handling function called

python - 如何使用 Pygame 播放正弦波/方波?

python - 我的 pyvona speak() 函数不工作