Pygame jerky player movement

Viewed 62

so, I'm making this simple game in python 3.7.7 with pygame and I'm trying to make a "random" movement for the enemies. But when I run the program with the enemies movement, my player moves a bit jerky (I hope I'm using the verb as it's intended). I cannot find what is making me move so weird. I have tried 2 diferent aproaches for the enemy movement and in both the problem is the same.

1st Try:

import pygame,random
pygame.init()
clock = pygame.time.Clock()
run= True
#imatges


#screen
sw= 1000
sh= 1000




wind = pygame.display.set_mode((sw,sh))
pygame.display.set_caption('PYgeon')

#sounds


####################################################################################################################
#                   PLAYER
####################################################################################################################
#Prot
class prot (object):
    def __init__(self,x,y,width,height):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.vel = 10

####################################################################################################################
#                   ENEMY
####################################################################################################################
#Enemy
class enem (object):
    def __init__(self,x,y,width,height):
        self.x = x
        self.y = y
        self.width = width
        self. height = height
        self.vel = 5
        self.cem = 0
    def mov (self):
        self.cem +=1
        if self.cem >= 3:
            self.cem=0
            opt = random.randint(1,2)#1 o 2 directions
            dis = random.randint(5,10)#distance
            screenupdt()
            if opt == 1:
                pos = random.randint(1,2)#positive / negative (1->+||2->-)
                if pos == 1:
                    dir = random.randint(1,2)#movement x(1) o movement y(2)
                    if dir == 1:
                        for ul in range (dis):
                            if enemy.x + enemy.width <= sw:
                                enemy.x += enemy.vel
                                screenupdt()
                    else:
                        for ul in range (dis):
                            if enemy.y + enemy.height <= sh:
                                enemy.y += enemy.vel
                                screenupdt()
                else:
                    dir = random.randint(1,2)#movement x(1) o movement y(2)
                    if dir == 1:
                        for ul in range (dis):
                            if enemy.x - enemy.width >= 0:
                                enemy.x -= enemy.vel
                                screenupdt()
                    else:
                        for ul in range (dis):
                            if enemy.y - enemy.height >= 0:
                                enemy.y -= enemy.vel
                                screenupdt()
            else:
                dirb = random.randint(1,4)#to choose one of the four directions 1(+x,+y) 2(+x,-y) 3(-x,+y) 4(-x,-y)
                if dirb == 1:
                    for ul in range (dis):
                        if enemy.x + enemy.width < sw and enemy.y + enemy.height < sh:
                            enemy.x += enemy.vel
                            enemy.y += enemy.vel
                            screenupdt()
                elif dirb == 2:
                    for ul in range (dis):
                        if enemy.x + enemy.width < sw and enemy.y - enemy.height > 0:
                            enemy.x += enemy.vel
                            enemy.y -= enemy.vel
                            screenupdt()
                elif dirb == 3:
                    for ul in range (dis):
                        if enemy.x - enemy.width > 0 and enemy.y + enemy.height < sh:
                            enemy.x -= enemy.vel
                            enemy.y += enemy.vel
                            screenupdt()
                else:
                    for ul in range (dis):
                        if enemy.x - enemy.width > 0 and enemy.y - enemy.height > 0:
                            enemy.x -= enemy.vel
                            enemy.y -= enemy.vel
                            screenupdt()
####################################################################################################################
#                   BOSS
####################################################################################################################

class boss (object):
    def __init__(self):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.vel = 5

####################################################################################################################
#                   PROJECTILES
####################################################################################################################

class proj (object):
    def __init__(self,x,y,width,height):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.vel = 25
####################################################################################################################
#                                   SCREEN LOADING
####################################################################################################################
#screen loading
def screenupdt ():
    wind.fill(0)
    pygame.draw.rect(wind , (255,100,255) , (aris.x,aris.y,aris.width,aris.height))
    pygame.draw.circle(wind, (250,255,100), (enemy.x,enemy.y), 25)
    pygame.display.update()

####################################################################################################################
####################################################################################################################
#                   LOOP
####################################################################################################################
####################################################################################################################


#variables
aris = prot(250,250,64,64)
enemy = enem (500,500,25,25)
enemy2 = enem (510,510,25,25)
cem= 0 #contador per el moviment dels enemics
#while

while run:
    clock.tick(40)
    screenupdt()
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run= False
    keys = pygame.key.get_pressed()
    if keys[pygame.K_a] and aris.x > 0:
        aris.x -= aris.vel
        screenupdt()
    if keys[pygame.K_d] and aris.x + aris.width < 1000:
        aris.x += aris.vel
        screenupdt()
    if keys[pygame.K_w] and aris.y > 0:
        aris.y -= aris.vel
        screenupdt()
    if keys[pygame.K_s] and aris.y + aris.height < 1000:
        aris.y += aris.vel
        screenupdt()
    enemy.mov()
pygame.quit()

2n Try:

import pygame,random
pygame.init()
clock = pygame.time.Clock()
run= True
#imatges


#screen
sw= 1000
sh= 1000




wind = pygame.display.set_mode((sw,sh))
pygame.display.set_caption('PYgeon')

#sounds


####################################################################################################################
#                   PLAYER
####################################################################################################################
#Prot
class prot (object):
    def __init__(self,x,y,width,height):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.vel = 10

####################################################################################################################
#                   ENEMY
####################################################################################################################
#Enemy
class enem (object):
    def __init__(self,x,y,width,height):
        self.x = x
        self.y = y
        self.width = width
        self. height = height
        self.vel = 5
        self.cem = 0
    def mov (self):
        self.cem += 1
        if self.cem == 6:
            self.cem = 0
            opt=[1,2,3,4,5,6,7,8]#1(+x) 2(-x) 3(+y) 4(-y) 5(+x,+y) 6(+x,-y) 7(-x,+y) 8(-x,-y)
            copt= random.choice(opt)
            dis = random.randint (1,10)
            if copt == 1:
                for asdf in range (dis):
                    self.x += self.vel
                    screenupdt()
            elif copt == 2:
                for asdf in range (dis):
                    self.x -= self.vel
                    screenupdt()
            elif copt == 3:
                for asdf in range (dis):
                    self.y += self.vel
                    screenupdt()
            elif copt == 4:
                for asdf in range (dis):
                    self.y -= self.vel
                    screenupdt()
            elif copt == 5:
                for asdf in range (dis):
                    self.x += self.vel
                    self.y += self.vel
                    screenupdt()
            elif copt == 6:
                for asdf in range (dis):
                    self.x += self.vel
                    self.y -= self.vel
                    screenupdt()
            elif copt == 7:
                for asdf in range (dis):
                    self.x -= self.vel
                    self.y += self.vel
                    screenupdt()
            elif copt == 8:
                for asdf in range (dis):
                    self.x -= self.vel
                    self.y -= self.vel
                    screenupdt()
####################################################################################################################
#                   BOSS
####################################################################################################################

class boss (object):
    def __init__(self):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.vel = 5

####################################################################################################################
#                   PROJECTILES
####################################################################################################################

class proj (object):
    def __init__(self,x,y,width,height):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.vel = 25
####################################################################################################################
#                                   SCREEN LOADING
####################################################################################################################
#screen loading
def screenupdt ():
    wind.fill(0)
    pygame.draw.rect(wind , (255,100,255) , (aris.x,aris.y,aris.width,aris.height))
    pygame.draw.circle(wind, (250,255,100), (enemy.x,enemy.y), 25)
    pygame.display.update()

####################################################################################################################
####################################################################################################################
#                   LOOP
####################################################################################################################
####################################################################################################################


#variables
aris = prot(250,250,64,64)
enemy = enem (500,500,25,25)
cem= 0 #contador per el moviment dels enemics
#while

while run:
    enemy.mov()            
                                                
    keys = pygame.key.get_pressed()
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run= False
    if keys[pygame.K_a]:
        aris.x -= aris.vel
        screenupdt()
    if keys[pygame.K_d]:
        aris.x += aris.vel
        screenupdt()
    if keys[pygame.K_w]:
        aris.y -= aris.vel
        screenupdt()
    if keys[pygame.K_s]:
        aris.y += aris.vel
        screenupdt()
pygame.quit()

Thank you :)

1 Answers

Remove the multiple calls to screenupdt from your code. It is sufficient to draw the scene and update the display once per frame. Remove it from the enem.move method and the application loop. Call it once at the end of the application loop:

while run:
    clock.tick(40)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run= False
    keys = pygame.key.get_pressed()
    if keys[pygame.K_a] and aris.x > 0:
        aris.x -= aris.vel
    if keys[pygame.K_d] and aris.x + aris.width < 1000:
        aris.x += aris.vel
    if keys[pygame.K_w] and aris.y > 0:
        aris.y -= aris.vel
    if keys[pygame.K_s] and aris.y + aris.height < 1000:
        aris.y += aris.vel

    enemy.mov()
    screenupdt() # <--- call it just here, but nowhere else

pygame.quit()

See also Why is the PyGame animation is flickering

Related