Как бороться со временем в Python при использовании Pygame - PullRequest
2 голосов
/ 09 октября 2019

Я работаю над моделированием, которое представляет производственную линию с движущимися продуктами.

Мои расчеты времени поступления продуктов с определенной (x, y) на бумаге не совпадают с расчетами моего моделирования.

Мое время итерации цикла pygame while занимает 0,01 секунды с очень небольшой неопределенностью.

Таким образом, мое движение пикселей составляет 0,5, а длина составляет, например, 645 пикселей. Таким образом, я думал, что каждый шаг составляет 0,5 пикселя, и это будет в общей сложности 1290 шагов. Время итерации 0,01 секунды должно составлять 12,9 секунды.

Однако моему моделированию нужно 16 секунд для длины 645 пикселей.

Может кто-нибудь объяснить разницу?

Я сделал фрагмент кода только с одним RECT, так чтоВремя итерации быстрее, но разница все равно есть

ПРИМЕР:

import pygame, sys, time, random
init_time = time.time()
from pygame.locals import *



pygame.init()

w_x = 1550
w_y = 800

DISPLAYSURF = pygame.display.set_mode((w_x,w_y))
pygame.display.set_caption('COPAL')

## COLORS USED (SIZE CORRESPONDS TO COLOR)
# background
BLACK = (0,0,0)

# boxes
GREEN = (0,100,0)
PINK = (255,0,255)
BLUE = (0,0,128)

xx = 0
yy = 400

but_on = True
sum_duration = 0
total_iteration = 0

total = []



box = [[xx,yy]]

## Filling background
DISPLAYSURF.fill(BLACK)
start = time.time()

start2 = time.time()


while True:


    init_end = time.time()


    if but_on == True:
        print(init_end-init_time)
        but_on = False    


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



    DISPLAYSURF.fill(BLACK)

    pygame.draw.rect(DISPLAYSURF,BLUE,(xx,yy,30,30))


    pygame.draw.line(DISPLAYSURF,PINK,(645,0),(645,800))

    xx += 0.5

    if xx == 645:

        timex = time.time()
        print(timex - start2)

        print(time_iteration_avg)


    stop = time.time()

    duration = stop - init_end

    total.append(duration)

    sum_duration += duration

    time_iteration_avg = sum_duration / len ( total )




   pygame.display.update()

ИЗМЕРЕННЫЙ ПРИМЕР

import pygame, sys, time, random
init_time = time.time()
from pygame.locals import *



pygame.init()

# window aize
w_x = 1550
w_y = 800

# time for each step
ite = 0.00387

DISPLAYSURF = pygame.display.set_mode((w_x,w_y))
pygame.display.set_caption('COPAL')


# background
BLACK = (0,0,0)

# boxes
GREEN = (0,100,0)
PINK = (255,0,255)
BLUE = (0,0,128)

# start position
xx = 0
yy = 400

but_on = True
sum_duration = 0
total_iteration = 0

total = []

oo= 0

step = 0.5

duration = ite

box = [[xx,yy]]

## Filling background
DISPLAYSURF.fill(BLACK)
start = time.time()

start2 = time.time()


while True:


    init_end = time.time()


    if but_on == True:
        init_t = (init_end - init_time)

        print(init_t)
        but_on = False    


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



    DISPLAYSURF.fill(BLACK)

    pygame.draw.rect(DISPLAYSURF,BLUE,(xx,yy,30,30))


    pygame.draw.line(DISPLAYSURF,PINK,(645,0),(645,800))

    xx += step

    if round(xx) == 645:

        timex = time.time()
        print("elapsed time ")
        print(timex - start2)

        print(time_iteration_avg)




    if duration == ite:

        step = 0.5



    if duration < ite:
        dif_ite = ite - duration
        time.sleep(dif_ite)

        print("Smaller")

        step = 0.5

    if duration > ite:
        dif_pix = duration - ite

        pix_ex = 5 / duration

        step = 645 / pix_ex

        print("Bigger")

    total.append(duration)

    sum_duration += duration

    time_iteration_avg = sum_duration / len ( total )


    print(step)


    stop = time.time()
    duration = stop - init_end


    pygame.display.update()

1 Ответ

2 голосов
/ 09 октября 2019

Джемми Доджер уже указал на основную проблему, но я попытаюсь объяснить более подробно.
Когда вы пишете код игры (или любой другой симулятор физики), вы не можете полагаться на тот факт, что ваш фрагмент кода всегда будет заниматьстолько же времени, чтобы выполнить. Возможно, что:
1 - вы пытались приостановить ваше приложение (через спящий режим), но ОС может не возобновить выполнение вашей программы в указанное вами время. Я бы сказал, что это основная причина.
2 - Вы пытались нарисовать что-то для экрана / GPU / RAM-буфера, скорость работы устройства может быть не одинаковой для каждого из ваших запросов.
3 - Возможно, десятки другихпричина, по которой я не могу придумать прямо сейчас.

Правильная вещь, которую нужно сделать, это измерить количество прошедшего времени между кадрами и соответственно скорректировать физическую симуляцию (например, скорость вашего блока в вашем коде). Прочитайте комментарии рядом с хх + = ... часть. (Некоторые люди могут критиковать код из-за использования time.sleep вместо pygame's clock.tick, но я просто пытаюсь облегчить его понимание):

import pygame, sys, time, random
init_time = time.time()
from pygame.locals import *


#  frame per second you want
FPS = 100

#  speed at each frame
SPEED = 0.5

#  use a pygame clock object to control FPS
#clock = pygame.time.Clock()





pygame.init()

w_x = 1550
w_y = 800

DISPLAYSURF = pygame.display.set_mode((w_x,w_y))
pygame.display.set_caption('COPAL')

## COLORS USED (SIZE CORRESPONDS TO COLOR)
# background
BLACK = (0,0,0)

# boxes
GREEN = (0,100,0)
PINK = (255,0,255)
BLUE = (0,0,128)

xx = 0
yy = 400

but_on = True
sum_duration = 0
total_iteration = 0

total = []



box = [[xx,yy]]

## Filling background
DISPLAYSURF.fill(BLACK)
start = time.time()

start2 = time.time()


#  initial value
time_spend_py = 1 / FPS

elapsed_step = 0
while True:
    init_end = time.time()
    loop_start_time = time.time()

    if but_on == True:
        print(init_end-init_time)
        but_on = False    

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

    DISPLAYSURF.fill(BLACK)

    pygame.draw.rect(DISPLAYSURF,BLUE,(xx,yy,30,30))


    pygame.draw.line(DISPLAYSURF,PINK,(645,0),(645,800))


    #  amount of change depends on elapsed time since last frame!
    #  Example:
    #  FPS: 100, time_spend=0.012 s
    #  your loop took more time at last iteration
    #  because of that we need to adjust speed
    #  xx += SPEED * (0.012 / (1/100))
    #  xx += SPEED * (0.012 / 0.010)
    #  xx += SPEED * 1.2
    #  so object moves faster
    xx += SPEED * (time_spend_py / (1 / FPS))    

    if xx >= 645:

        timex = time.time()
        print(timex - start2)

        print(time_iteration_avg)
        print("Elapsed step:{}".format(elapsed_step))
        exit(0)


    pygame.display.update()

    stop = time.time()
    duration = stop - init_end
    total.append(duration)
    sum_duration += duration
    time_iteration_avg = sum_duration / len ( total )

    #time_spend = clock.tick(FPS)
    time.sleep(0.01)
    elapsed_step += 1
    loop_end_time = time.time()
    time_spend_py = loop_end_time - loop_start_time
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...