Maddox Styles
Maddox Styles

Reputation: 3

Why is my enemybullets shooting from wrong area in Pygame

I am currently creating a top-down shooter in Pygame and currently need my enemies to shoot bullets at my player. The problem is that when I move my character the position where the bullets are shooting from moves as well when they are meant to be shot from the enemies at all times. I have watched many different tutorials but non of which have proven helpful. Hoping someone can help.

import pygame
import sys
import math
import random
import time
import multiprocessing
from pygame import mixer

pygame.init()

displayWidth = 100
displayHeight = 200
enemytime = time.time() + 10
enemyshoottime = time.time() + 1

#Enemy

class Enemy1(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.hit_box = (self.x-10, self.y -10, 70, 70)
        self.animation_images = [pygame.image.load("Enemy1_animation_0.png"), pygame.image.load("Enemy1_animation_1.png"),
        pygame.image.load("Enemy1_animation_2.png"), pygame.image.load("Enemy1_animation_3.png")]
        self.animation_count = 0
        self.reset_offset = 0
        self.offset_x = random.randrange(-150, 150)
        self.offset_y = random.randrange(-150, 150)
        self.health = 4


    def main(self, display):
        if self.animation_count + 1 == 16:
            self.animation_count = 0
        self.animation_count += 1

        if self.reset_offset == 0:
            self.offset_x = random.randrange(-150, 150)
            self.offset_y = random.randrange(-150, 150)
            self.reset_offset = random.randrange(120, 150)
        else:
            self.reset_offset -= 1

        if player.x + self.offset_x > self.x-display_scroll[0]:
            self.x += 1
        elif player.x + self.offset_x < self.x-display_scroll[0]:
            self.x -= 1

        if player.y + self.offset_y > self.y-display_scroll[1]:
            self.y += 1
        elif player.y + self.offset_y < self.y-display_scroll[1]:
            self.y -= 1

        display.blit(pygame.transform.scale(self.animation_images[self.animation_count//4], (50, 50)), (self.x-display_scroll[0], self.y-display_scroll[1]))

        self.hit_box = (self.x-display_scroll[0]-10, self.y-display_scroll[1]-10, 70, 70)
        pygame.draw.rect(display, (255, 0, 0), self.hit_box, 2)

#Enemy Bullet

class EnemyBullet:
    def __init__(self, x, y, playerx, playery):
        self.x = x
        self.y = y
        self.playerx = 300
        self.playery = 300
        self.speed = 7
        self.angle = math.atan2(y-playerx, x-playery)
        self.x_vel = math.cos(self.angle) * self.speed
        self.y_vel = math.sin(self.angle) * self.speed
    def main(self, display):
        self.x -= int(self.x_vel)
        self.y -= int(self.y_vel)


        EnemyBulletRect = pygame.draw.circle(display, (255,0,0), (self.x, self.y), 5)

#list's

enemies = [ Enemy2(800, -200), Enemy3(-300, 500), Enemy4(1000, 400)]

enemy = Enemy1(600, 400)

enemy_bullets = []

sounds = ['explosion1.mp3', 'explosion2.mp3', 'explosion3.mp3']

player = Player(400, 300, 32, 32)

display_scroll = [0,0]

player_bullets = []

while True:
    display.fill((0, 0, 0))
    display.blit(displayImage, (0, 0))
    #display.blit(ImageBackground, (0, 0))
    display.blit(Earth, (700, 100))
    show_score(textX, textY)


    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
            pygame.quit()

#Enemy shoots

  if time.time() >= enemyshoottime:


        enemy_bullets.append(EnemyBullet(enemy.x, enemy.y, playerx, playery))
        from playsound import playsound
        playsound('lazer.mp3', block=False)


        enemyshoottime = time.time() + 1

    for bullets in enemy_bullets:
        bullets.main(display)

#spawn enemies

    if time.time() >= enemytime:
        # Time to spawn a new enemy.
        enemies.append( Enemy3( 100, 500 ) )
        enemies.append( Enemy3( 600, 400 ) )
        # Reset the alarm.
        enemytime = time.time() + 10

Upvotes: 0

Views: 79

Answers (1)

Rabbid76
Rabbid76

Reputation: 211220

The motion vector of the bullet can be calculated from the normalized direction vector (Unit vector) multiplied by the velocity. The unit vector is obtained by dividing the components of the vector by the Euclidean length of the vector.
Do not round the velocity before adding it to the position, but round the position when using it to draw the bullet. If you round the component vectors before adding them or round the position attributes themselves, there will be an inaccuracy that accumulates over time. Round only the values that are used in pygame.draw.circle Use round instead of int.

class EnemyBullet:
    def __init__(self, x, y, playerx, playery):
        self.x = x
        self.y = y
        self.speed = 7

        dx = playerx - x
        dy = playery - y
        d = math.sqrt(dx*dx, dy*dy) # or  d = math.hypot(dx, dy)
        self.x_vel = self.speed * dx / d
        self.y_vel = self.speed * dy / d

    def main(self, display):
        self.x += self.x_vel
        self.y += self.y_vel
        EnemyBulletRect = pygame.draw.circle(
            display, (255,0,0), (round(self.x), round(self.y)), 5)

Upvotes: 0

Related Questions