pythonpygamebulletmouse-position

How do I make the bullets to shoot towards my mouse when I leftclick in this code?


    import pygame
import random
import math
from pygame import mixer


pygame.init()

screen = pygame.display.set_mode((1280, 720)) 
background = pygame.image.load('1264.jpg') 
background = pygame.transform.scale(background, (1290, 720)) 

pygame.display.set_caption("FlySwapper") 
icon = pygame.image.load('logo.png') 
pygame.display.set_icon(icon) 

playerImg = pygame.image.load('Frosk.png') 
playerX = 580 
playerY = 550 
playerX_change = 0 
playerY_change = 0 

enemyImg = []
enemyX = []
enemyY = []
enemyX_change = []
enemyY_change = []
num_of_enemies = 6



for i in range(num_of_enemies):
    enemyImg.append(pygame.image.load('flue.png'))
    enemyX.append(random.randint(0, 1290)) 
    enemyY.append(random.randint(0, 310)) 
    enemyX_change.append(0.5) 
    enemyY_change.append(0.5)


bulletImg = pygame.image.load('skudd.png')
bulletX = 0
bulletY = 0
bulletX_change = 2
bulletY_change = 2
bullet_state = "ready"



def player(x, y): 
    screen.blit(playerImg, (x, y))

def enemy(x, y, i):
    screen.blit(enemyImg[i], (x, y))

def fire_bullet(x, y):
    global bullet_state
    bullet_state = "fire"
    screen.blit(bulletImg, (x + 35, y + 10))



running = True  
while running:

    screen.blit(background, (0, 0)) 

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

     

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_a:
                playerX_change = -1
            if event.key == pygame.K_d:
                playerX_change = 1
            if event.key == pygame.K_w:
                playerY_change = -1
            if event.key == pygame.K_s:
                playerY_change = 1

        if event.type == pygame.KEYUP:
            if event.key == pygame.K_a or event.key == pygame.K_d:
                playerX_change = 0
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_w or event.key == pygame.K_s:
                playerY_change = 0

   
        LEFT = 1
        RIGHT = 3

        if event.type == pygame.MOUSEBUTTONUP and event.button == LEFT:
            if bullet_state == "ready":
                #bullet_Sound = mixer.Sound('.wav')
                #bullet_Sound.play()
                bulletX = playerX
                bulletY = playerY
                fire_bullet(bulletX, bulletY)

    playerX += playerX_change
    playerY += playerY_change

    if playerX <= 0:
        playerX = 0
    elif playerX >= 1150:
        playerX = 1150
    if playerY <= 310: 
        playerY = 310
    elif playerY >= 590:
        playerY = 590

    player(playerX, playerY)



    for i in range(num_of_enemies):
      
        enemyX[i] += enemyX_change[i]
        enemyY[i] += enemyY_change[i]

        if enemyX[i] <= 0:
            enemyX_change[i] = 0.5
        elif enemyX[i] >= 1150:
            enemyX_change[i] = -0.5
        if enemyY[i] <= 0:
            enemyY_change[i] = 0.5
        elif enemyY[i] >= 590:
            enemyY_change[i] = -0.5


 
        enemy(enemyX[i], enemyY[i], i)


    if bulletY <= 0:
        bullet_state = "ready"
    if bullet_state == "fire":
        fire_bullet(bulletX, bulletY)
        bulletY -= bulletY_change

   
    pygame.display.update()

I have been trying to make the bullet go towards my mouse on left click for weeks, my teacher can't help me apparantly and I am pretty new to python. I know that I have made the bullet to only go forward in this code, but I was planning on changing it to go towards the mouse click later.

I'm sorry if this was a bad explanation of my problem.


Solution

  • When you click the mouse, you need to calculate the normalized direction vector (Unit vector) from the start position of the bullet to the mouse position. Define the speed of the bullet and multiply the direction vector by the speed:

    dx = event.pos[0] - bulletX
    dy = event.pos[1] - bulletY
    dist = math.sqrt(dx*dx + dy*dy)
    bulletX_change = bullet_speed * dx/dist 
    bulletY_change = bullet_speed * dy/dist 
    

    relevant changes:

    def fire_bullet(x, y):
        screen.blit(bulletImg, (x + 35, y + 10))
    
    running = True  
    while running:
        # [...]
    
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            # [...]
    
            if event.type == pygame.MOUSEBUTTONUP and event.button == LEFT:
                if bullet_state == "ready":
                    #bullet_Sound = mixer.Sound('.wav')
                    #bullet_Sound.play()
                    bulletX = playerX
                    bulletY = playerY
                    bullet_state = "fire"
                    dx = event.pos[0] - bulletX
                    dy = event.pos[1] - bulletY
                    dist = math.sqrt(dx*dx + dy*dy)
                    bulletX_change = bullet_speed * dx/dist 
                    bulletY_change = bullet_speed * dy/dist 
    
        # [...]
    
        if playerX < 0 or bulletY < 0 or playerX > 1280 or bulletY > 720:
            bullet_state = "ready"
        if bullet_state == "fire":
            bulletX += bulletX_change
            bulletY += bulletY_change
            fire_bullet(bulletX, bulletY)
    
        pygame.display.update()