Search code examples
pythonooppygamedrawshapes

How can I have multiple drawings on the screen at once without them flashing?


I am currently coding a simple computer game for a school coursework project and have encountered an issue in pygame. In my game, the player simply has to shoot at targets which fly through the air, almost a reverse space invaders. My current issue is that I can not have two shapes in the arena at once without one of them flickering and lagging. Below is my code, any help is welcomed. Cheers.

Also, does anyone know how I can add delay between each drawing being drawn. As I insinuated above, I aim to have targets fairly space out without overlaps but I do want multiple on the screen at the same time. Cheers.

import pygame

#Setting window dimensions and caption (Module 1)

pygame.init()
window = pygame.display.set_mode((800, 575))
pygame.display.set_caption("TARGET PRACTICE")

#Colour variables (Module 1)

BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (200, 0, 0)
GREEN = (0, 200, 0)
BLUE = (0, 0, 200)

#Target coordinates and dimensions (Module 3)

#target_x = 0
#target_y = 80
#target_w = 60
#target_h = 40
#target_v = 1

exec = True

class Target:
  def __init__(self, x, y, h, w, v):
    self.x = x
    self.y = y
    self.h = h
    self.w = w
    self.v = v

target_1 = Target(0, 80, 60, 40, 0.1)
target_2 = Target(0, 100, 60, 40, 0.1)
target_3 = Target(0, 50, 60, 40, 1)

clock = 0

while exec:
  pygame.time.delay(1)
  for event in pygame.event.get():
    if event.type == pygame.QUIT:
      exec = False

  #Target Movement (Module 4)

  window.fill(RED)

  #Background and target drawing (Module 2)

  target_1.x += target_1.v
  pygame.draw.rect(window, BLUE, (target_1.x, target_1.y, target_1.h, target_1.w))
  clock += 1

  if clock%2 == 0:
    target_2.x += target_2.v
    pygame.draw.rect(window, BLUE, (target_2.x, target_2.y, target_2.h, target_2.w))


  pygame.display.update()




pygame.quit()```

Solution

  • target_2 is flashing, because it is just drawn in every 2nd frame. Change the position of target_2 in every 2nd frame, but draw it in every frame:

    while exec:
        # [...]
    
        # update positions 
        target_1.x += target_1.v
        if clock%2 == 0:
            target_2.x += target_2.v
        clock += 1
    
        # clear window (fill in rED)
        window.fill(RED)
    
        # draw all the objects of the scene in every frame 
        pygame.draw.rect(window, BLUE, (target_1.x, target_1.y, target_1.h, target_1.w))
        pygame.draw.rect(window, BLUE, (target_2.x, target_2.y, target_2.h, target_2.w))   
    
        # update display
        pygame.display.update()
    

    Note, the scene has to be redrawn in every frame. First the background is cleared filled window.fill(RED), then the entire scene has to be drawn and finally the display has to be updated (pygame.display.update()).


    If you want to delay the target_2, then you have to draw and update the position after clock has reached a certain limit:

    clock = 0
    target_2_threshold = 500
    
    while exec:
        # [...]
    
        # update positions 
        clock += 1
        target_1.x += target_1.v
        if clock > target_2_threshold and clock % 2 == 0:
            target_2.x += target_2.v
    
        # clear window (fill in rED)
        window.fill(RED)
    
        # draw all the objects of the scene in every frame 
        pygame.draw.rect(window, BLUE, (target_1.x, target_1.y, target_1.h, target_1.w))
        if clock > target_2_threshold:
            pygame.draw.rect(window, BLUE, (target_2.x, target_2.y, target_2.h, target_2.w))   
    
        # update display
        pygame.display.update()