I tried to make the enemies(yellow box) follow the player(red box) with a constant velocity from all directions.

The problem of my code is the speed of the enemy from x+(Right) and y+(Bottom) axis to the player is slower than x-(Left) and y-(Above).

Image: <https://i.stack.imgur.com/qJNp7.png>

I think the problem is in here. I can't find it. It may be somewhere else.

```
for enemy_types in Global_Obj[2]:
            zetas = math.sqrt((enemy_types.rect.center[1] - FirstPlayer.rect.center[1])**2 + (FirstPlayer.rect.center[0] - enemy_types.rect.center[0])**2)

            print(enemy_types.rect.center)

            x,y = enemy_types.rect.center
            x += dt * enemy_types.speed * (FirstPlayer.rect.center[0] - enemy_types.rect.center[0]) / zetas
            y += dt * enemy_types.speed * (FirstPlayer.rect.center[1] - enemy_types.rect.center[1]) / zetas

            enemy_types.rect.center = (x,y) 

```

Here is all of my code.

```
# -*- coding: utf-8 -*-
"""
Created on Wed Sep  8 21:56:06 2021

@author: Toon
"""
import pygame
import cv2
import numpy as np
import math
import random
import time

dt = 0.01
window = (1280, 720)
win = pygame.display.set_mode(window)
background = pygame.Surface(window)
pygame.display.set_caption("First Game")
run = True
class playerIO():
    def __init__(self):
        self.name = 'Player'
        self.width = 30
        self.height = 30
        self.speed = 1000
        self.color = (255,0,0)
        self.HPwidth = 50
        self.HPheight = 8
        self.HPoffset = 10
        self.MAXHP = 1000
        self.HP = self.MAXHP
        self.HPregeneration_per_sec = 5

        self.MANAwidth = 50
        self.MANAheight = 8
        self.MANAoffset = 10
        self.MAXMANA = 3000
        self.MANA = self.MAXMANA
        self.MANAregeneration_per_sec = 10

        self.image = pygame.Surface([self.width, self.height])
        self.image.fill(self.color)
        self.rect = self.image.get_rect(topleft=(80, 80))

        self.bullet_delay = [0, 0, 0]
    def draw(self):
        self.HPbar_high = self.rect.y-self.HPheight-self.HPoffset
        self.MANAbar_high = self.HPbar_high-self.MANAheight-self.MANAoffset 
        pygame.draw.rect(win, self.color, self.rect)

        pygame.draw.rect(win, (255,255,255), (self.rect.x + self.width/2 - self.HPwidth/2, self.HPbar_high, self.HPwidth, self.HPheight))
        pygame.draw.rect(win, (0,255,0), (self.rect.x + self.width/2 - self.HPwidth/2, self.HPbar_high, self.HPwidth*self.HP/self.MAXHP, self.HPheight))

        pygame.draw.rect(win, (255,255,255), (self.rect.x + self.width/2 - self.MANAwidth/2, self.MANAbar_high, self.MANAwidth, self.MANAheight))
        pygame.draw.rect(win, (0,0,255), (self.rect.x + self.width/2 - self.MANAwidth/2, self.MANAbar_high, self.MANAwidth*self.MANA/self.MAXMANA, self.MANAheight))

class BulletIO():
    def __init__(self):
        self.MANA_usage =  5
        self.zeta = 0
        self.width = 15
        self.height = 15
        self.speed = 1600
        self.damage = 8
        self.color = (0,255,0)
        self.image = pygame.Surface([self.width, self.height])
        self.image.fill(self.color)
        self.rect = self.image.get_rect()
        self.reload_delay = 0.2 #shot delay  
    def variant(self,X,Y, Zeta):
        self.rect.x = X
        self.rect.y = Y
        self.zeta = Zeta

    def draw(self):
        pygame.draw.rect(win, self.color, self.rect)

class LaserIO():
    def __init__(self):
        self.MANA_usage =  10
        self.zeta = 0
        self.width = 8
        self.height = 8
        self.speed = 500
        self.damage = 20
        self.color = (0,0,160)
        self.image = pygame.Surface([self.width, self.height])
        self.image.fill(self.color)
        self.rect = self.image.get_rect()
        self.reload_delay = 0 #shot delay  
    def variant(self,X,Y, Zeta):
        self.rect.x = X
        self.rect.y = Y
        self.zeta = Zeta

    def draw(self):
        pygame.draw.rect(win, self.color, self.rect)    

class LaserBeamIO():
    def __init__(self):
        self.MANA_usage_per_sec =  1000
        self.zeta = 0
        self.width = 8
        self.height = 8
        self.speed = 500
        self.damage = 20
        self.color = (0,160,160)
        self.image = pygame.Surface([self.width, self.height])
        self.image.fill(self.color)
        self.rect = self.image.get_rect()
        self.reload_delay = 5 #shot delay
        self.charge_time = 0
        self.beam_distance = 60
        self.max_charge_time = 10
        self.charge_size_per_sec = 20
        self.charge_damage_per_sec = 100

    def charge_beam(self, player, Zeta):
        self.charge_time+=dt
        self.width += self.charge_size_per_sec * dt
        self.height += self.charge_size_per_sec * dt
        self.damage += self.charge_damage_per_sec * dt
        self.image = pygame.Surface([self.width, self.height])
        self.image.fill(self.color)
        self.rect = self.image.get_rect()
        self.rect.center = (player[0] + self.beam_distance * math.cos(Zeta), player[1] + self.beam_distance * math.sin(Zeta))
        self.zeta = Zeta

    def draw(self):
        pygame.draw.rect(win, self.color, self.rect)    

class EnemyIO():
    def __init__(self):
        self.name = 'enemy'
        self.width = 15
        self.height = 15
        self.zeta = 0
        self.speed = 200
        self.color = (255,255,0)
        self.MAXHP = 16
        self.regeneration = 0.2

        self.HPwidth = 20
        self.HPheight = 5
        self.HPoffset = 8
        self.HP = self.MAXHP

        self.damage = 10
        self.image = pygame.Surface([self.width, self.height])
        self.image.fill(self.color)
        self.rect = self.image.get_rect(topleft=(20, 20))

    def randompos(self, spawn_offset = 200):
        while 1 :
            try:
                rand_pole = random.randint(1,4)
                if rand_pole == 1 or rand_pole == 2:
                    self.rect.x = random.randint(FirstPlayer.rect.x+1+spawn_offset, window[0]-self.width)
                else:
                    self.rect.x = random.randint(1,FirstPlayer.rect.x-spawn_offset)

                if rand_pole == 1 or rand_pole == 4:
                    self.rect.y = random.randint(FirstPlayer.rect.y+1+spawn_offset, window[1]-self.height)
                else:
                    self.rect.x = random.randint(1,FirstPlayer.rect.y-spawn_offset)
                return 0
            except:
                pass
    def draw(self):
        self.HPbar_high = self.rect.y-self.HPheight-self.HPoffset

        pygame.draw.rect(win, self.color, self.rect)
        pygame.draw.rect(win, (255,255,255), (self.rect.x + self.width/2 - self.HPwidth/2, self.HPbar_high, self.HPwidth, self.HPheight))
        pygame.draw.rect(win, (0,255,0), (self.rect.x + self.width/2 - self.HPwidth/2, self.HPbar_high, self.HPwidth*self.HP/self.MAXHP, self.HPheight))

def direction(mouse, obj):
    #y = 1 clockwise
    zeta = math.atan2((mouse[1]-obj[1]),(mouse[0]-obj[0]))
    return zeta

def enemy_spawn(Enemy_max = 30, slow_rate = 2):

    num = len(Global_Obj[2])
    if  num < Enemy_max:
        # random spawn enemy 1/100
        rand = random.randint(1, int((num+1)*slow_rate))
        if rand == 1:
            ene = EnemyIO()
            ene.randompos()
            Global_Obj[2].append(ene)

#Global_Obj[0] are player obj type, Global_Obj[1] are bullet obj type, Global_Obj[2] are enemy obj type, Global_Obj[3] are beam obj type
Global_Obj = [[],[],[],[]]
FirstPlayer = playerIO()
Global_Obj[0].append(FirstPlayer)
win.blit(background,(0, 0))
mouse_pos = (-1,-1)
beam_load = False

pygame.init()

# define the RGB value for white,
#  green, blue colour .
text_color = (0, 0, 0)
white = (255, 255, 255)
# set the pygame window name
pygame.display.set_caption('Game')

# create a font object.
# 1st parameter is the font file
# which is present in pygame.
# 2nd parameter is size of the font
font = pygame.font.Font('freesansbold.ttf', 32)

# create a text surface object,
# on which text is drawn on it.
text = font.render('Game start', True, text_color)

# create a rectangular object for the
# text surface object
textRect = text.get_rect()

# set the center of the rectangular object.
textRect.center = (window[0] // 2, window[1] // 2)
inteface_run = True
# infinite loop
while inteface_run:

    # completely fill the surface object
    # with white color
    win.fill(white)

    # copying the text surface object
    # to the display surface object
    # at the center coordinate.
    win.blit(text, textRect)

    # iterate over the list of Event objects
    # that was returned by pygame.event.get() method.
    for event in pygame.event.get():
        if pygame.mouse.get_pressed()[0] or event.type == pygame.QUIT:
            inteface_run = False
        # Draws the surface object to the screen.
        pygame.display.update()
pygame.time.delay(1000)
font = pygame.font.Font('freesansbold.ttf', 16)
end_time = 300 # sec
t0= time.time()

while run:
        pygame.display.flip() 
        pygame.time.delay(int(dt*1000))

        # player move event
        keys = pygame.key.get_pressed()
        if keys[pygame.K_ESCAPE]:
            run = False
        if keys[pygame.K_SPACE] :
            FirstPlayer.rect.x, FirstPlayer.rect.y = (80,80)
        if (keys[pygame.K_a] or keys[pygame.K_LEFT]):
            FirstPlayer.rect.x, FirstPlayer.rect.y = (FirstPlayer.rect.x - FirstPlayer.speed * dt, FirstPlayer.rect.y)
        if keys[pygame.K_d] or keys[pygame.K_RIGHT]:
            FirstPlayer.rect.x, FirstPlayer.rect.y = (FirstPlayer.rect.x + FirstPlayer.speed * dt, FirstPlayer.rect.y)
        if keys[pygame.K_w] or keys[pygame.K_UP]:
            FirstPlayer.rect.x, FirstPlayer.rect.y = (FirstPlayer.rect.x, FirstPlayer.rect.y - FirstPlayer.speed * dt)
        if keys[pygame.K_s] or keys[pygame.K_DOWN]:
            FirstPlayer.rect.x, FirstPlayer.rect.y = (FirstPlayer.rect.x, FirstPlayer.rect.y + FirstPlayer.speed * dt)

        if FirstPlayer.rect.x < 0:
            FirstPlayer.rect.x = 0
        if FirstPlayer.rect.x+FirstPlayer.width > window[0]:
            FirstPlayer.rect.x = window[0] - FirstPlayer.width
        if FirstPlayer.rect.y < 0:
            FirstPlayer.rect.y = 0
        if FirstPlayer.rect.y+FirstPlayer.height > window[1]:
            FirstPlayer.rect.y = window[1] - FirstPlayer.height

        #player HP regen
        if FirstPlayer.HP < FirstPlayer.MAXHP:
            FirstPlayer.HP +=FirstPlayer.HPregeneration_per_sec*dt
            if FirstPlayer.HP > FirstPlayer.MAXHP:
                FirstPlayer.HP = FirstPlayer.MAXHP

        #player MANA regen
        if FirstPlayer.MANA < FirstPlayer.MAXMANA:
            FirstPlayer.MANA +=FirstPlayer.MANAregeneration_per_sec*dt
            if FirstPlayer.MANA > FirstPlayer.MAXMANA:
                FirstPlayer.MANA = FirstPlayer.MAXMANA

        #bullet reload time
        for i in range(len(FirstPlayer.bullet_delay)):
            if FirstPlayer.bullet_delay[i]>0:
                FirstPlayer.bullet_delay[i]-= dt 
                if FirstPlayer.bullet_delay[i]<0:
                    FirstPlayer.bullet_delay[i] =0

        # bullet click event
        mouse_pos = pygame.mouse.get_pos()

        if pygame.mouse.get_pressed()[0] and FirstPlayer.MANA >= BulletIO().MANA_usage and FirstPlayer.bullet_delay[0]==0:
            bullet = BulletIO()
            FirstPlayer.MANA -= bullet.MANA_usage
            zeta = direction(mouse_pos, FirstPlayer.rect.center)
            bullet.variant(*FirstPlayer.rect.center, zeta)
            FirstPlayer.bullet_delay[0] = bullet.reload_delay
            Global_Obj[1].append(bullet)

        if pygame.mouse.get_pressed()[2] and FirstPlayer.MANA >= LaserIO().MANA_usage and FirstPlayer.bullet_delay[1]==0:
            laser = LaserIO()
            FirstPlayer.MANA -= laser.MANA_usage
            zeta = direction(mouse_pos, FirstPlayer.rect.center)
            laser.variant( *FirstPlayer.rect.center, zeta)
            FirstPlayer.bullet_delay[1] = laser.reload_delay
            Global_Obj[1].append(laser)

        # Global_Obj[1] bullet obj type movement
        for bullet_type in Global_Obj[1]:
            bullet_type.rect.x += dt * bullet_type.speed * math.cos(bullet_type.zeta)
            bullet_type.rect.y += dt * bullet_type.speed * math.sin(bullet_type.zeta)
            if bullet_type.rect.x > window[0] or bullet_type.rect.x < 0 or bullet_type.rect.y > window[1] or bullet_type.rect.y < 0:
                Global_Obj[1].remove(bullet_type)
        # Global_Obj[3] beam obj type movement
        for bullet_type in Global_Obj[3]:
            bullet_type.rect.x += dt * bullet_type.speed * math.cos(bullet_type.zeta)
            bullet_type.rect.y += dt * bullet_type.speed * math.sin(bullet_type.zeta)
            if bullet_type.rect.x > window[0] or bullet_type.rect.x < 0 or bullet_type.rect.y > window[1] or bullet_type.rect.y < 0:
                Global_Obj[3].remove(bullet_type)
        # enemy
        enemy_spawn()

        # Global_Obj[2] enemy obj type movement
        for enemy_types in Global_Obj[2]:
            zetas = math.sqrt((enemy_types.rect.center[1] - FirstPlayer.rect.center[1])**2 + (FirstPlayer.rect.center[0] - enemy_types.rect.center[0])**2)

            print(enemy_types.rect.center)

            x,y = enemy_types.rect.center
            x += dt * enemy_types.speed * (FirstPlayer.rect.center[0] - enemy_types.rect.center[0]) / zetas
            y += dt * enemy_types.speed * (FirstPlayer.rect.center[1] - enemy_types.rect.center[1]) / zetas

            enemy_types.rect.center = (x,y)

        # enemy-player damage check
        for enemy_type in Global_Obj[2]:
            if FirstPlayer.rect.colliderect(enemy_type.rect):
                FirstPlayer.HP -= enemy_type.damage
                Global_Obj[2].remove(enemy_type)

        # bullet - enemy damage check
        for bullet_type in Global_Obj[1]:
            for enemy_type in Global_Obj[2]:
                if bullet_type.rect.colliderect(enemy_type.rect):
                    enemy_type.HP -= bullet_type.damage
                    if enemy_type.HP<=0:
                        Global_Obj[2].remove(enemy_type)
                    Global_Obj[1].remove(bullet_type)
                    break

        # beam - enemy damage check
        for bullet_type in Global_Obj[3]:
            for enemy_type in Global_Obj[2]:
                if bullet_type.rect.colliderect(enemy_type.rect):
                    enemy_type.HP -= bullet_type.damage
                    if enemy_type.HP<=0:
                        Global_Obj[2].remove(enemy_type)

        #end game
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
            elif event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 2 and FirstPlayer.bullet_delay[2]==0: # left mouse button
                    beam = LaserBeamIO()
                    Global_Obj[3].append(beam)
                    beam_load = True

            elif event.type == pygame.MOUSEBUTTONUP:
                if event.button == 2 and beam_load:
                    zeta = direction(mouse_pos, FirstPlayer.rect.center)
                    beam.charge_beam( FirstPlayer.rect.center, zeta)
                    FirstPlayer.bullet_delay[2] = beam.reload_delay
                    beam_load = False

        if beam_load:
            if FirstPlayer.MANA <= beam.MANA_usage_per_sec * dt:
                zeta = direction(mouse_pos, FirstPlayer.rect.center)
                beam.charge_beam( FirstPlayer.rect.center, zeta)
                FirstPlayer.bullet_delay[2] = beam.reload_delay
                beam_load = False
            else:
                FirstPlayer.MANA -= beam.MANA_usage_per_sec * dt
                zeta = direction(mouse_pos, FirstPlayer.rect.center)
                beam.charge_beam( FirstPlayer.rect.center, zeta)

        if FirstPlayer.HP <= 0:
            run = False
        te = int(time.time() - t0)
        if te >= end_time:
            run = False

        # draw obj
        win.blit(background,(0, 0))

        for obj_types in Global_Obj:
            for obj in obj_types:
                obj.draw()

        text = font.render(f'timer:{te}/{end_time} sec', True, white)

        # create a rectangular object for the
        # text surface object
        textRect = text.get_rect()

        # set the center of the rectangular object.
        textRect.center = (window[0] // 2, window[1]-40)
        win.blit(text, textRect)

pygame.quit()

```

Feel free to give me any suggestions to improve my code. I'm very new to Pygame.