1

I'm making a top down space shooter game similar to Asteroids using Pygame. I have the player, controlled with the arrow keys, shooting lasers with the mouse button but I also want to make the lasers move towards the direction of the mouse cursor, not just in a straight line. Does anyone know how to do this?

import pygame
pygame.init()

import random
from pygame.math import Vector2

inPlay = True
screen = pygame.display.set_mode((900, 700))

#colour
BLUE=(0,0,255)
RED=(255,0,0)
WHITE=(255,255,255)
BLACK=(0,0,0)

#bullet
bulletSpeed=15

class Player(pygame.sprite.Sprite):

    def __init__(self,x,y,speed,picture=None):
        pygame.sprite.Sprite.__init__(self)

        self.pic = pygame.Surface((50, 30), pygame.SRCALPHA)
        pygame.draw.rect(self.pic, BLUE,(0, 5, 60, 60),0)
        self.orig_pic = self.pic  # Store a reference to the original.

        self.rect = self.pic.get_rect(center=(x,y))
        self.pos = Vector2(x,y)

        self.image=pygame.image.load(picture)
        self.x=x
        self.y=y
        self.speed=speed

    def rotate(self):
        # The vector to the target (the mouse position or middle shape).
        direction = pygame.mouse.get_pos() - self.pos
        radius, angle = direction.as_polar()
        # Rotate the pic by the negative angle 
        self.pic = pygame.transform.rotate(self.orig_pic, -angle)
        # Create another rect
        self.rect = self.pic.get_rect(center=self.rect.center)

    def moveRight(self):
        self.x=self.x+self.speed
        self.update()

    def moveLeft(self):
        self.x=self.x-self.speed
        self.update()

    def moveUp(self):
        self.y=self.y-self.speed
        self.update()

    def moveDown(self):
        self.y=self.y+self.speed
        self.update()

    def update(self):
        self.rotate()
        self.rect=pygame.Rect(self.x,self.y, self.rect.width, self.rect.height)


    def draw_on(self, surface):
        surface.blit(self.image, self.rect)


class Bullets(pygame.sprite.Group):
    def __init__(self):
        pygame.sprite.Group.__init__(self)

    def move(self):
        for bullet in self:
            bullet.moveUp()

    def decay(self):
        for bullet in self:
            if bullet.y < -100:
                self.remove(bullet)

def redraw_game_window():
    screen.fill(BLACK)
    player.draw_on(screen)
    bullets.draw(screen)
    pygame.display.update()

#player
shipSpeed=5
player = Player(450,600,shipSpeed,'player.png')

RB=width-player.rect.width
CEILING = 3*player.rect.height            # for ship movement
FLOOR = height - player.rect.height       #

#bullet
bullets = Bullets()

clock = pygame.time.Clock()


while inPlay:

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            inPlay=False
        if event.type == pygame.MOUSEBUTTONDOWN:
            bullet = Player(player.x, player.y, bulletSpeed, "bullet.png")
            bullet.x = bullet.x + round(player.rect.width/2) - round(bullet.rect.width/2) +10
            bullet.y = bullet.y - bullet.rect.height -30
            bullets.add(bullet)            

    keys=pygame.key.get_pressed()                       
    pygame.event.get()        
    if keys[pygame.K_LEFT] or keys[pygame.K_a] and player.x>0:
        player.moveLeft()
    if keys[pygame.K_RIGHT] or keys[pygame.K_d] and player.x<RB:            # if right arrow has been pressed
        player.moveRight()      # move the ball right
    if keys[pygame.K_UP] or keys[pygame.K_w] and player.y > CEILING:
        player.moveUp()
    if keys[pygame.K_DOWN] or keys[pygame.K_s] and player.y <FLOOR:
        player.moveDown()


    redraw_game_window()

    bullets.move()
    bullets.decay()

    player.update()

    clock.tick(30)

pygame.quit()

1 Answers1

0

Define an attribute pos and dir of type pygame.math.Vector2 when a new bullet is created. The attribute pos contains the current position of the bullet and the attribute dir is a vector which contains the direction of movement. The amount of the vector is the speed. The direction is the vector from the bullet to the position of the mouse click event event.pos:

while inPlay:

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            inPlay=False
        if event.type == pygame.MOUSEBUTTONDOWN:
            bullet = Player(player.x, player.y, bulletSpeed, "bullet.png")
            bullet.x = bullet.x + round(player.rect.width/2) - round(bullet.rect.width/2) +10
            bullet.y = bullet.y - bullet.rect.height -30

            bullet.pos = pygame.math.Vector2(bullet.x, bullet.y)
            mouse_pos  = pygame.math.Vector2(event.pos[0], event.pos[1])
            bullet.dir = (mouse_pos - bullet.pos).normalize() * bullet.speed

            bullets.add(bullet)    

Calculate the new position of the bullet by adding bullet.dir to bullet.pos in he method move of the class Bullets:

class Bullets(pygame.sprite.Group):
    def __init__(self):
        pygame.sprite.Group.__init__(self)

    def move(self):
        for bullet in self:
            bullet.pos += bullet.dir
            bullet.x = bullet.pos[0]
            bullet.y = bullet.pos[1]
            self.update()

    def decay(self):
        for bullet in self:
            if bullet.y < -100:
                self.remove(bullet)
Rabbid76
  • 202,892
  • 27
  • 131
  • 174