Reputation: 21
I'm currently working on a school project: making a game using python and pygame library. Most of what happens in this game is when something on the screen is clicked, it should write certain things on the screen for the player to read. (the game is story based and it doesn't have any special action.) My problem with it right now is the opening scene. A cloud( a single sprite) is supposed to move on the screen for some time, and while it is moving, some texts should appear on the screen, as the dialogs the main character should say. The problem is that the only movement in this scene is the clouds passing by, and because in the structure of the game is a while loop, EVERYTHING that is shown on the screen is drawn every time a loop happens, which causes a flicking, blinking effect. I searched online for a solution and I saw the term "double buffering"?. I think using it can solve this, but I'm relatively new to programming, so I couldn't understand what exactly it was and how to use it. Can someone please explain it to me? I'll also write my code here, I'd be really thankful if you can correct it or show how to correct the code. link to the project: https://mega.nz/file/kt8zFazI#r-GgcJmk8Qj0AgDTpgcSROX2Yg7Vl5qe0aklLjI3lms because I drew the sprites myself, I sent the whole project so that the sprites become visible.
# Pygame template - skeleton for a new pygame project
import pygame
import d
from os import path
img_dir = path.join(path.dirname(__file__), 'img')
# variables
WIDTH = 1300
HEIGHT = 800
FPS = 30
# define colors
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
# initialize pygame and create window
pygame.init()
pygame.mixer.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Lost In Time")
clock = pygame.time.Clock()
# load graphics
CLOUD = pygame.image.load(path.join(img_dir, 'cloud.png'))
CLOUD_rect = CLOUD.get_rect()
skyb = pygame.image.load(path.join(img_dir, 'skyb.png'))
skyb_rect = skyb.get_rect()
bubble = pygame.image.load(path.join(img_dir, 'bubble.png'))
bubble_rect = bubble.get_rect()
sky = pygame.image.load(path.join(img_dir, 'sky.png'))
sky_rect = sky.get_rect()
# introduce functions
retro = "Retro.ttf"
def draw_text(message, y, x):
newfont = pygame.font.Font(retro, 40)
newtext = newfont.render(message, 0, BLACK)
textrect = newtext.get_rect()
textrect.topleft = (x, y)
screen.blit(bubble, bubble_rect)
screen.blit(newtext, textrect)
pygame.display.update(bubble_rect)
def move():
CL.update()
screen.blit(sky, sky_rect)
CL.draw(screen)
pygame.display.update(sky_rect)
class Cloud(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = CLOUD
self.image.set_colorkey(BLACK)
self.rect = self.image.get_rect()
self.rect.bottomright = (0, 626)
def update(self):
self.rect.x += 5
if self.rect.left > WIDTH:
self.rect.right = 0
cloud = Cloud()
CL = pygame.sprite.Group()
screen.blit(skyb, skyb_rect)
CL.add(cloud)
CL.draw(screen)
draw_text(d.d3, 650, 55)
pygame.display.update()
running = True
while running:
move()
draw_text(d.d3, 650, 55)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
clock.tick(FPS)
This is the code. At first I had a problem with making the cloud move, but eventually It got fixed.But when it moved, it also left a trace of the last sprite that was drawn on my back ground and when it was done moving, the background was covered with white. So I thought that I should draw the background again every time. This method worked well when I didn't have the text on my screen, even though it was lagging and slow. Then I added the text, and the blinking started. I thought that using pygame.display.update() and restricting the area that should be updated to the only sprite that moves should fix it. But It made it worst, resulting in a blinking white page with nothing to show. Then I changed the actual sprites with the photo editor I use, so that they are no longer covering each other. That didn't work either. I really don't know what to do and the deadline for my project is really close. Can someone help?
Upvotes: 2
Views: 89
Reputation: 210928
The rectangle passed to pygame.display.update()
is not intended to limit the screen update to that area, but at least to update that area in the most efficient way. Multiple calls to pygame.display.update()
or pygame.display.flip()
cause flickering. Fortunately, you can also pass in a list of rectangles. Call pygame.display.update()
only once, but with all the areas you want to update:
def draw_text(message, y, x):
newfont = pygame.font.Font(retro, 40)
newtext = newfont.render(message, 0, BLACK)
textrect = newtext.get_rect()
textrect.topleft = (x, y)
screen.blit(bubble, bubble_rect)
screen.blit(newtext, textrect)
return bubble_rect
def move():
CL.update()
screen.blit(sky, sky_rect)
CL.draw(screen)
return sky_rect
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
rect1 = move()
rect2 = draw_text(d.d3, 650, 55)
pygame.display.update([rect1, rect2])
clock.tick(FPS)
Upvotes: 2