Inside while not done you shouldn't use other while which takes longer time. It stops while not done and it can't check if you pressed ESC, etc.
You should rather use pygame.time.get_ticks() to get current time and use it to control which element move or draw.
I also use state to see if I move left or right or I wait before move left or right. This way I can do different things - I can move or not, I can draw or not (ie. if I have button "Pause" I could use state_pause to draw or not this button).
This code runs while not done all time so you can always exit using ESC. You can also move second circle even when first circle is waiting.
import pygame
# --- constants ---
WHITE = (255, 255, 255)
BLACK = ( 0, 0, 0)
# --- classes ---
# empty
# --- functions ---
def moveLeft():
currentPosition[0] -= 1
def moveRight():
currentPosition[0] += 1
# --- main ---
pygame.init()
windowCalibration = pygame.display.set_mode((0,0))
pygame.display.set_caption("Eye calibration")
currentPosition = [300, 368]
state = 'move_left'
wait_to = 0
done = False
while not done:
# --- events ---
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
done = True
# --- moves ---
if state == 'move_left':
if currentPosition[0] >= 10:
moveLeft()
else:
state = 'wait_before_move_right'
wait_to = pygame.time.get_ticks() + 3000
elif state == 'move_right':
if currentPosition[0] <= 1350:
moveRight()
else:
state = 'wait_before_move_left'
wait_to = pygame.time.get_ticks() + 3000
elif state == 'wait_before_move_right':
current_time = pygame.time.get_ticks()
if current_time > wait_to:
state = 'move_right'
elif state == 'wait_before_move_left':
current_time = pygame.time.get_ticks()
if current_time > wait_to:
state = 'move_left'
# --- draws ----
windowCalibration.fill(WHITE)
pygame.draw.circle(windowCalibration, BLACK, currentPosition, 10)
pygame.display.update()
# --- end ---
pygame.quit()
EDIT: this code moves 3 circles at the same time, they wait before they change direction and it doesn't stops other circles, and you can use ESC in any moment.
import pygame
# --- constants ---
WHITE = (255, 255, 255)
BLACK = ( 0, 0, 0)
RED = (255, 0, 0)
GREEN = ( 0, 255, 0)
BLUE = ( 0, 0, 255)
# --- classes ---
# empty
# --- functions ---
# empty
# --- main ---
pygame.init()
windowCalibration = pygame.display.set_mode((0,0))
pygame.display.set_caption("Eye calibration")
circles = [
{'pos': [300, 368], 'speed': 1, 'state': 'move_left', 'wait_to': 0, 'color': RED},
{'pos': [300, 268], 'speed': 10, 'state': 'move_right', 'wait_to': 0, 'color': GREEN},
{'pos': [300, 168], 'speed': 30, 'state': 'move_right', 'wait_to': 0, 'color': BLUE},
]
done = False
while not done:
# --- events ---
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
done = True
# --- moves ---
current_time = pygame.time.get_ticks()
for circle in circles:
if circle['state'] == 'move_left':
if circle['pos'][0] >= 10:
circle['pos'][0] -= circle['speed']
else:
circle['pos'][0] = 10
circle['state'] = 'wait_before_move_right'
circle['wait_to'] = pygame.time.get_ticks() + 3000
elif circle['state'] == 'move_right':
if circle['pos'][0] <= 1350:
circle['pos'][0] += circle['speed']
else:
circle['pos'][0] = 1350
circle['state'] = 'wait_before_move_left'
circle['wait_to'] = pygame.time.get_ticks() + 3000
elif circle['state'] == 'wait_before_move_right':
if current_time > circle['wait_to']:
circle['state'] = 'move_right'
elif circle['state'] == 'wait_before_move_left':
if current_time > circle['wait_to']:
circle['state'] = 'move_left'
# --- draws ----
windowCalibration.fill(WHITE)
for circle in circles:
pygame.draw.circle(windowCalibration, circle['color'], circle['pos'], 10)
pygame.display.update()
# --- end ---
pygame.quit()