How to speed up smoothness in pygame?

I am wondering how to speed up the smoothness of my Python code using pygam. I'm guessing I need to make this more efficient? When this is done, some balls move randomly in a given area, however, the new position of each ball is not smooth at all, there is a jump between each movement, since the cycle is very slow. How to fix it? Or are there any suggestions for improving it? This is my code:

import pygame
from pygame import *
import random
pygame.init()
size = width, height = 800, 600
screen = display.set_mode(size)
pygame.display.set_caption("Year 12: Ideal Gas Simulation")


BLACK = (0, 0, 0)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
WHITE=(255,255,255)
GREEN = (0, 255, 0)
BALLX = 0
BALLY = 1
BALLSPEEDX = 2
BALLSPEEDY = 3
List=[]
radius=5

running=True
myClock=time.Clock()


myClock.tick(60)
def initBall():


        for n in range(40):
            ballx = random.randint(0, 800) # randomly setting the x position
            bally = random.randint(0, 600) # randomly setting the y position
            dirx = random.randint(-5,5)    # randomly setting the x speed
            diry = random.randint(-5,5)    # randomly setting the y speed

            data=[ballx, bally, dirx, diry]
            List.append(data)
            # returning a list with all the data the ball needs
        return List # returning the list


def drawScreen(List):
    draw.rect(screen, WHITE, (0, 0, 800, 600))
    for x in range(40):
        BALLX=List[x][0]
        BALLY=List[x][1]
        draw.circle(screen, GREEN, (BALLX,BALLY),radius)
        display.flip()
        pygame.draw.rect(screen, BLACK, (100-radius,100-radius,600+(2*radius),400+(2*radius)), 1)

        f=pygame.font.SysFont(None,60)
        text=f.render("PV=nRT",True,(0,0,0))
        screen.blit(text,(300,height/20))


def moveBall(List):
    for x in range(40):
        BALLX=List[x][0]
        BALLY=List[x][1]
        SPEEDX=List[x][2]#####data[BALLX]== the first index of each list [x][0]
        SPEEDY=List[x][3]##data[BALLSPEEDX]= List[x][2]
        age=SPEEDX+BALLX
        List[x][0]=age
         # increases the position of the ball
        plus=SPEEDY+BALLY
        List[x][1]=plus
    # checks to see if the ball is hitting the walls in the x direction
        if BALLX > 700:
            List[x][0] = 700#NORMALLY 800
            third=List[x][2]
            answer=third*-1
            List[x][2]=answer
        elif BALLX < 100:#NORMALLY 0
            List[x][0] = 100
            third=List[x][2]
            answer=third*-1
            List[x][2]=answer

    # checks to see if the ball is hitting the walls in the y direction
        if BALLY < 100:
            List[x][1] = 100#NORMALLY 0
            third=List[x][3]
            answer=third*-1
            List[x][3]=answer
        elif BALLY > 500:
            List[x][1] = 500#NORMALLY 600
            third=List[x][3]
            answer=third*-1
            List[x][3]=answer
    return List#return updated list


List=initBall()
while running==True:
    for evnt in event.get():
        if evnt.type==QUIT:
            running=False
            quit()
        if evnt.type==MOUSEBUTTONDOWN:
            mx,my=evnt.pos
            button=evnt.button

    drawScreen(List)
    List=moveBall(List)

      

+3


source to share


2 answers


In addition to skrx's answer, you can also refactor your code and avoid a lot of repetitive calls. Also, indexing the array BALLS

can improve performance slightly.

In general, avoid renaming variables inside functions with uppercase letters. These names are usually assigned the constants defined at the top of the file.



The version I ran into is below:

import array
import pygame
pygame.init()
import random

from pygame import *

size = WIDTH, HEIGHT = 800, 600
screen = display.set_mode(size)
pygame.display.set_caption("Year 12: Ideal Gas Simulation")


BLACK = (0, 0, 0)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
WHITE = (255,255,255)
GREEN = (0, 255, 0)
BALLX = 0
BALLY = 1
BALLSPEEDX = 2
BALLSPEEDY = 3
RADIUS = 5

BALLS = []

myClock = time.Clock()

myClock.tick(60)
def initBalls():
    for n in range(40):
        props = array.array('i', [
            random.randint(0, WIDTH),
            random.randint(0, HEIGHT),
            random.randint(-5, 5),
            random.randint(-5, 5),
        ])
        BALLS.append(props)


def drawScreen():
    draw.rect(screen, WHITE, (0, 0, 800, 600))
    props = (100-RADIUS, 100-RADIUS, 600+(2*RADIUS), 400+(2*RADIUS))
    pygame.draw.rect(screen, BLACK, props, 1)
    f = pygame.font.SysFont(None, 60)
    text = f.render("PV=nRT", True,(0, 0, 0))
    screen.blit(text,(300, HEIGHT / 20))
    for i in range(len(BALLS)):
        draw.circle(screen, GREEN, BALLS[i][:2],RADIUS)
    display.flip()


def moveBalls():
    for i in range(len(BALLS)):

        if BALLS[i][0] > 700:
            BALLS[i][0] = 700
            BALLS[i][2] *= -1
        elif BALLS[i][0] < 100:
            BALLS[i][0] = 100
            BALLS[i][2] *= -1
        else:
            BALLS[i][0] += BALLS[i][2]

        if BALLS[i][1] < 100:
            BALLS[i][1] = 100
            BALLS[i][3] *= -1
        elif BALLS[i][1] > 500:
            BALLS[i][1] = 500
            BALLS[i][3] *= -1
        else:
            BALLS[i][1] += BALLS[i][3]


def main():
    initBalls()
    while True:
        for evnt in event.get():
            if evnt.type == QUIT:
                pygame.quit()
                return
            elif evnt.type == MOUSEBUTTONDOWN:
                mx, my = evnt.pos
                button = evnt.button

        drawScreen()
        moveBalls()


if __name__ == "__main__":
    main()

      

+1


source


Call pygame.display.flip()

only once for each frame.

def drawScreen(List):
    draw.rect(screen, WHITE, (0, 0, 800, 600))
    for x in range(40):
        BALLX=List[x][0]
        BALLY=List[x][1]
        draw.circle(screen, GREEN, (BALLX,BALLY),radius)
        # display.flip()  # Don't call `display.flip()` here.
        pygame.draw.rect(screen, BLACK, (100-radius,100-radius,600+(2*radius),400+(2*radius)), 1)

        screen.blit(text,(300,height/20))

    pygame.display.flip()  # Call it here.

      




I also recommend using pygame.time.Clock

for frame rate limiting.

# Define the font object as a global constant.
FONT = pygame.font.SysFont(None, 60)
# If the text doesn't change you can also define it here.
TEXT = FONT.render("PV=nRT", True, (0,0,0))
# Instantiate a clock to limit the frame rate.
clock = pygame.time.Clock()
running = True

while running:  # `== True` is not needed.
    for evnt in event.get():
        if evnt.type == QUIT:
            running = False
            # Better use `pygame.quit` and `sys.exit` to quit.
            pygame.quit()
            sys.exit()

    drawScreen(List)
    List = moveBall(List)

    clock.tick(30)  # Limit frame rate to 30 fps.

      

+1


source







All Articles