Search code examples
pythonpygamegame-development

My enemies stop moving if i move my player


https://i.sstatic.net/jjDi8.jpg

Sorry for the lag, but as visible my enemies(green) spawn but after if i move my player(gray) they sometimes stop moving until i move my player again.

But even after moving my player the pre existing enemies dont move closer to the player and retain their distance to the player

this is the file which contains the main loop of the game

this is the file which contains the player class

this is the file which contains the enemy class

and this is the file which is the main run file

i feel the problem exists in my main loop class which is as follows:

import pygame, random
from Folder.scripts.TopDown.script_files.td_Player import Player
from Folder.scripts.TopDown.script_files.td_enemy import Enemy
from Folder.scripts.TopDown.script_files.td_colours import colours

pygame.init()

class Main:
    def __init__(self):
        self.FPS = 60
        self.WIDTH = self.HEIGHT = 1280
        self.MAP = pygame.Surface((self.WIDTH, self.HEIGHT))
        self.enemies = []

    def main(self,WINDOW ,clock):

        WINDOW.fill(colours['white'])
        player = Player()

        camera_pos = (0, 0)
        enemy_time = 0

        run = True
        while run:

            clock.tick(self.FPS)

            enemy_y = random.randint(0, 1220)
            enemy_x = random.randint(0, 1220)
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    run = False

            current_time = pygame.time.get_ticks()
            if current_time > enemy_time:
                enemy_time = current_time + 1000
                self.enemies.append(Enemy(enemy_y, enemy_x))

            camera_pos = player.movement(camera_pos)

            self.WindowUpdate(WINDOW, player, camera_pos)

        pygame.quit()

    def WindowUpdate(self,WINDOW, player, camera_pos):

        player_x, player_y = player.playerMove()

        WINDOW.fill((255, 255, 255))
        self.MAP.fill(colours['gray'])
        player.renderPlayer(self.MAP)
        WINDOW.blit(self.MAP, camera_pos)

        for e in self.enemies:
            e.renderEnemy(WINDOW)
            e.enemyMovement(player_x, player_y)

        pygame.display.update()

Enemy class:

import pygame, os, random, math

pygame.init()

# current_time = pygame.time.get_ticks()
#         if current_time > self.enemy_time:
#             self.enemy_time = current_time + 1000
#             self.enemies.append()

class Enemy:

    def __init__(self, enemy_y, enemy_x):
        self.ENEMY_HEIGHT = self.ENEMY_WIDTH = 64
        self.ENEMY_ACCELERATION = 5

        self.enemy_rect = pygame.Rect(enemy_x, enemy_y, self.ENEMY_HEIGHT, self.ENEMY_WIDTH)

        self.ENEMY = {
            'up': pygame.transform.scale(pygame.image.load(
                os.path.join(r'C:\Users\ajeen\PycharmProjects\Games\Folder\scripts\TopDown\assets', 'enemy_up.png')),
                (self.ENEMY_HEIGHT, self.ENEMY_WIDTH)),

            'down': pygame.transform.scale(pygame.image.load(
                os.path.join(r'C:\Users\ajeen\PycharmProjects\Games\Folder\scripts\TopDown\assets', 'enemy_down.png')),
                (self.ENEMY_HEIGHT, self.ENEMY_WIDTH)),

            'left': pygame.transform.scale(pygame.image.load(
                os.path.join(r'C:\Users\ajeen\PycharmProjects\Games\Folder\scripts\TopDown\assets', 'enemy_left.png')),
                (self.ENEMY_HEIGHT, self.ENEMY_WIDTH)),

            'right': pygame.transform.scale(pygame.image.load(
                os.path.join(r'C:\Users\ajeen\PycharmProjects\Games\Folder\scripts\TopDown\assets', 'enemy_right.png')),
                (self.ENEMY_HEIGHT, self.ENEMY_WIDTH))
        }

        self.enemy_state = 'up'

    def enemyMovement(self, player_x, player_y):
        ene_x, ene_y = player_x - self.enemy_rect.x, player_y - self.enemy_rect.y
        dist = math.hypot(ene_x, ene_y)
        ene_x, ene_y = ene_x // dist, ene_y // dist

        self.enemy_rect.x += ene_x * self.ENEMY_ACCELERATION
        self.enemy_rect.y += ene_y * self.ENEMY_ACCELERATION
        print(self.enemy_rect.x, self.enemy_rect.y)

    def renderEnemy(self, WINDOW):
        WINDOW.blit(self.ENEMY[self.enemy_state] , (self.enemy_rect.x, self.enemy_rect.y))

I hope the imgur link to the vid showcasing my problem gets embedded. Any input or help will be appreciated


Solution

  • The result of ene_x // dist and ene_y // dist is always 0. To calculate the movement, you must use the / (division) operator rather than the // (floor division) operator

    ene_x, ene_y = ene_x // dist, ene_y // dist

    ene_x, ene_y = ene_x / dist, ene_y / dist
    

    Since pygame.Rect is supposed to represent an area on the screen, a pygame.Rect object can only store integral data.

    The coordinates for Rect objects are all integers. [...]

    The fraction part of the movement gets lost when the position of the object incremented:

    self.enemy_rect.x += ene_x * self.ENEMY_ACCELERATION
    self.enemy_rect.y += ene_y * self.ENEMY_ACCELERATION
    

    If you want to store object positions with floating point accuracy, you have to store the location of the object in separate variables respectively attributes and to synchronize the pygame.Rect object. round the coordinates and assign it to the location (e.g. .topleft) of the rectangle:

    x, y = # floating point coordinates
    rect.topleft = round(x), round(y)
    

    Add floating point coordinates to the Enemy class:

    class Enemy:
    
        def __init__(self, enemy_y, enemy_x):
            # [...]
    
            self.enemy_rect = pygame.Rect(enemy_x, enemy_y, self.ENEMY_HEIGHT, self.ENEMY_WIDTH)
            self.x, self.y = self.enemy_rect.topleft
    
            # [...]
            
    
        def enemyMovement(self, player_x, player_y):
            ene_x, ene_y = player_x - self.x, player_y - self.y
            dist = math.hypot(ene_x, ene_y)
            ene_x, ene_y = ene_x / dist, ene_y / dist
    
            self.x += ene_x * self.ENEMY_ACCELERATION
            self.y += ene_y * self.ENEMY_ACCELERATION
            self.enemy_rect = round(self.x), round(self.y)