pythonpygameoutputmotionpygame-tick

inconsistent motion with pygame


I am having a problem where i am trying to get a circle to go to the same spot every time i execute the program. But each time I run the code, the dot doesn't always line up. I have a test circle in the same place to compare run to run. The Red circle should cover the white circle perfectly but it changes every time i run the program. I am reseting the kernal as i am using pygame.time.get_ticks() to time everything.

import sys, pygame, math
from pygame.locals import *

# set up a bunch of constants
BLUE       = (  0,   0, 255)
WHITE      = (255, 255, 255)
ORANGE     = (255, 165,   0)
PINK       = (255,  20, 147)
RED        = (255,   0,   0)
GREEN      = (  0, 255,   0)
LIMEGREEN  = ( 50, 205,  50)
YELLOW     = (255, 255,   0)
PURPLE     = (160,  32, 240)
BLACK      = (  0,   0,   0)

#Background Colour
BGCOLOR = BLACK

#Setting Window Size and finding window x and y centre 
WINDOWWIDTH = 1918# width of the program's window, in pixels 960x540
WINDOWHEIGHT =  1078# height in pixels
WIN_CENTERX = int(WINDOWWIDTH / 2) # the midpoint for the width of the window
WIN_CENTERY = int(WINDOWHEIGHT / 2) # the midpoint for the height of the window

# frames per second to run at
FPS = 60

#intializing Variables
AMPLITUDE = 450 

colourArray=[BLUE,WHITE,YELLOW,GREEN,RED,PINK,PURPLE,LIMEGREEN,ORANGE]
i=0
xPos = 0
step = 0 
small_step =0
stop_step=step=0
xPos=0  
yPos=0 
c=RED
timestep=0

# standard pygame setup code
pygame.init()
FPSCLOCK = pygame.time.Clock()
DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT),pygame.FULLSCREEN)
pygame.display.set_caption('Task1')
fontObj = pygame.font.Font('freesansbold.ttf', 16)

# main application loop
while True:
    # event handling loop for quit events
    for event in pygame.event.get():
        if event.type == QUIT or (event.type == KEYUP and event.key == K_ESCAPE):
            pygame.quit()
            sys.exit()       

    #setup for label and time   
    tempTime=pygame.time.get_ticks()/1000         
    time_string=str(tempTime)
    instructionsSurf = fontObj.render(time_string, True, WHITE, BGCOLOR)
    instructionsRect = instructionsSurf.get_rect()
    instructionsRect.left = 10
    instructionsRect.bottom = WINDOWHEIGHT - 10

    # fill the screen to draw from a blank state
    DISPLAYSURF.fill(BGCOLOR)
    DISPLAYSURF.blit(instructionsSurf, instructionsRect)

    tempTime=pygame.time.get_ticks()/1000
    #Color change loop
    c=RED  
    if (0<=(tempTime)<3):
        c=RED
    if (3<=(tempTime)<5):
        c=BLUE
    if (5<=(tempTime)<7):
        c=GREEN
    if (7<=(tempTime)<9):
        c=YELLOW
    if (9<=(tempTime)<11):
        c=WHITE 
    if (11<=(tempTime)<17):
        c=RED
    if (17<=(tempTime)<42):
        c=RED
    if (42<=(tempTime)<46):
        c=RED
    if (46<=(tempTime)<120):
        c=colourArray[i]



    #Setting position of x and y coordinates 
    if (0<=(tempTime)<14):
        xPos = 0
        yPos = 0 
    if (14<(tempTime)<17): 
        small_step += 5.111
        xPos = small_step 
        yPos = 0
    if (17<(tempTime)<43):
        step += 0.05001 
        step %= 2 * math.pi
        xPos = math.cos(step) * AMPLITUDE
        yPos = math.sin(step) * AMPLITUDE
    if (43<(tempTime)<46):
        stop_step=step
        xPos = math.cos(stop_step) * AMPLITUDE
        yPos = math.sin(stop_step) * AMPLITUDE
    if (46<(tempTime)<120):
        step += 0.05001
        step %= 2 * math.pi
        xPos = math.cos(step) * AMPLITUDE
        yPos = math.sin(step) * AMPLITUDE  



    #test dot
    pygame.draw.circle(DISPLAYSURF, WHITE, (WIN_CENTERX+AMPLITUDE, 0+WIN_CENTERY),12,0)
    # draw dot1 
    dot1=pygame.draw.circle(DISPLAYSURF, c, (int(xPos)+ WIN_CENTERX, int(yPos) + WIN_CENTERY), 12,0)
    # draw dot2
    dot2=pygame.draw.circle(DISPLAYSURF, BLACK, (int(xPos) + WIN_CENTERX, int(yPos) + WIN_CENTERY), 6,0)



    #refresh
    pygame.draw.rect(DISPLAYSURF, BLACK, (0, 0, WINDOWWIDTH, WINDOWHEIGHT), 1)
    pygame.display.update()
    FPSCLOCK.tick(FPS)

Solution

  • I've only scanned your code but I would guess your inconsistency is due to a high frame rate (60). FPSCLOCK.tick(FPS) will make sure you go up to 60, but does not mean you will go 60 fps. So if your computer can not handle 60 frames per second, it will go below 60 frames.

    Cristph Terasa's recommendation of using busy_loop should do the job for ya, but I personally have no experience for it and want to share a method of normalizing game speed across different FPSs.

    Rather than reinventing a wheel, here's a link to a question that explains it. I recommend the second answer, written by pmoleri. In Pygame, normalizing game-speed across different fps values

    This solution should help your game run at the same speed no matter the frame rate.