首页 > 解决方案 > Pygame-使子弹朝光标方向射击

问题描述

我试图让游戏中的子弹朝着光标的方向射击,直到它击中窗口边框。我的子弹目前朝我的光标移动,但一旦到达光标所在的位置就会停止。

我注意到如果我的光标不在屏幕上,子弹可能会到达边界,因此我尝试通过乘法和加法修改用于计算子弹移动的光标位置,使其始终位于窗口之外,但我不太明白以我想要的方式工作。

win = pygame.display.set_mode((1000, 800))
pos = pygame.mouse.get_pos()
keys = pygame.key.get_pressed()

def shoot(bullets):
    for bullet in bullets:
        if bullet.x > 0 and bullet.x <1000 and bullet.y > 0 and bullet.y < 800:
            pygame.draw.circle(win, (255, 255, 255), (round(bullet.x) ,round(bullet.y)),5)
            diffX = bullet.targetX - bullet.x
            diffY = bullet.targetY - bullet.y
            ang = math.atan2(diffY,diffX)
            bullet.x += math.cos(ang)*bullet.vel
            bullet.y += math.sin(ang)*bullet.vel

if keys[pygame.K_SPACE] and RegBullet.canShoot:
        RegBullet.canShoot = False
        regBullets.append(RegBullet(win,x=p1.getX(),y=p1.getY(),targetX=pos[0],targetY=pos[1]))
        pause = threading.Thread(target=cool_down,args=(1,))
        pause.start()

标签: pythonmathpygame

解决方案


问题是您通过从子弹当前位置到目标点 ( bullet.targetX, bullet.targetY) 的向量计算子弹的方向。
一旦子弹到达目标,那么这个方向就是 (0, 0) 并且子弹不再移动。
不要将目标位置存储在bullet. 而是存储初始方向向量。例如:

bullet.diffX = targetX - bullet.x
bullet.diffY = targetY - bullet.y
ang = math.atan2(bullet.diffY, bullet.diffX)
bullet.x += math.cos(ang)*bullet.vel
bullet.y += math.sin(ang)*bullet.vel

使用pygame.Rectand.collidepoint()来验证子弹是否在窗口内:

for bullet in bullets:
   if pygame.Rect(0, 0, 1000, 800).collidepoint(bullet.x, bullet.y):
       # [...]

甚至.colliderect

for bullet in bullets:
   radius = 5
   bullet_rect = pygame.Rect(-radius, -radius, radius, radius);
   bullet_rect.center = (bullet.x, bullet.y)
   if pygame.Rect(0, 0, 1000, 800).colliderect(bullet_rect):
       # [...]

我建议pygame.math.Vector2用于计算子弹的运动,例如:

bullet.pos = pg.math.Vector2(bullet.x, bullet.y)
bullet.dir = pg.math.Vector2(targetX, targetY) - bullet.pos
bullet.dir = bullet.dir.normalize()
for bullet in bullets:

    if #[...]

        bullet.pos += bullet.dir * bullet.vel
        bullet.x, bullet.y = (round(bullet.pos.x), round(bullet.pos.y))

推荐阅读