How to fix flickering of objects and figures in pygame? [duplicate] - python

This question already has an answer here:
Why is the PyGame animation is flickering
(1 answer)
Closed 1 year ago.
Here I, have am tying to simply make 2 rectangles using pygame module. I have made them using 2 methods but they don't seem to work. Please suggest some that could work.
(I am using Python 3.8.3)
Here is the code:
import pygame
pygame.init()
screen = pygame.display.set_mode((100, 100))
box_color = (255, 0, 0)
color = (0, 150, 100)
ybox = 20
xbox = 20
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
ybox += 5
if (ybox >= 45):
ybox = 45
pygame.draw.rect(screen, box_color, pygame.Rect(xbox, ybox, 50, 50), 2)
pygame.display.flip()
pygame.draw.rect(screen, box_color, pygame.Rect(20, 95, 50, 50), 2)
pygame.display.flip()
screen.fill(color)
pygame.display.update()

Your game is flickering because of the multiple calls of pygame.display.flip() and pygame.display.update(). One update of the display at the end of the application loop is sufficient. Multiple calls to pygame.display.update() or pygame.display.flip() cause flickering.
Remove all calls of pygame.display.update() and pygame.display.flip() from your code, but call it once at the end of the application loop. However, clear the display before drawing the objects:
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
ybox += 5
if (ybox >= 45):
ybox = 45
# clear disaply
screen.fill(color)
# draw objects
pygame.draw.rect(screen, box_color, pygame.Rect(xbox, ybox, 50, 50), 2)
pygame.draw.rect(screen, box_color, pygame.Rect(20, 95, 50, 50), 2)
# update dispaly
pygame.display.update()
The typical PyGame application loop has to:
handle the events by either pygame.event.pump() or pygame.event.get().
update the game states and positions of objects dependent on the input events and time (respectively frames)
clear the entire display or draw the background
draw the entire scene (blit all the objects)
update the display by either pygame.display.update() or pygame.display.flip()

Related

how to remove square after 2 seconds

I have this code and I don't know how to make the red cube disappear after 2 seconds.
import pygame
import sys
from pygame.locals import *
pygame.init()
a=0
#display
prozor = pygame.display.set_mode((800,800))
FPS = pygame.time.Clock()
FPS.tick(60)
#boje
green=pygame.Color(0 ,255 , 0)
red=pygame.Color(255, 0, 0)
yellow=pygame.Color(255, 255, 0)
blue=pygame.Color(0, 0, 255)
black=pygame.Color(0, 0, 0)
white=pygame.Color(255, 255, 255)
#class
class Cube:
def update(self):
self.cx, self.cy = pygame.mouse.get_pos()
self.square = pygame.Rect(self.cx, self.cy, 50, 50)
def draw(self):
pygame.draw.rect(prozor, (255, 0, 0), self.square)
cube = Cube()
drawing_cube = False
#objekt
for j in range(16):
for i in range(800):
if i%50 == 0:
pygame.draw.rect(prozor, green, ((0+i, a), (50, 50),),1)
a=a+50
#gameloop
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit
if event.type == pygame.MOUSEBUTTONDOWN:
cube.update()
drawing_cube = True
if drawing_cube:
cube.draw()
pygame.display.flip()
pygame.display.update()
Adding it to the draw class will just freeze the game and shut it.
def draw(self):
pygame.draw.rect(prozor, red, self.square)
time.sleep(3)
pygame.draw.rect(prozor, black, self.square
I tried making another class called delete which would delete the cube after 3 seconds using the time module.
def delete(self):
time.sleep(3)
pygame.draw.rect(prozor, black, self.square)
and added it here
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit
if event.type == pygame.MOUSEBUTTONDOWN:
cube.update()
drawing_cube = True
if drawing_cube:
cube.draw()
pygame.display.flip()
**cube.delete**
pygame.display.flip()
pygame.display.update()
but the cube is not disappearing.
Use pygame.time.get_ticks to measure the time in milliseconds. Calculate the time when the cube must disappear again and hide the cube if the current time is greater than the calculated time. You also need to clear the display (prozor.fill(0)) and redraw the scene in each frame:
drawing_cube = False
hide_cube_time = 0
clock = pygame.time.Clock()
run = True
while run:
clock.tick(100)
current_time = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == QUIT:
run = False
if event.type == pygame.MOUSEBUTTONDOWN:
cube.update()
drawing_cube = True
hide_cube_time = current_time + 2000 # 2000 milliseconds == 2 sconds
if current_time > hide_cube_time:
drawing_cube = False
prozor.fill(0)
a=0
for j in range(16):
for i in range(800):
if i%50 == 0:
pygame.draw.rect(prozor, green, (0+i, a, 50, 50), 1)
a=a+50
if drawing_cube:
cube.draw()
pygame.display.update()
pygame.quit()
sys.exit()
Note, the typical PyGame application loop has to:
limit the frames per second to limit CPU usage with pygame.time.Clock.tick
handle the events by calling either pygame.event.pump() or pygame.event.get().
update the game states and positions of objects dependent on the input events and time (respectively frames)
clear the entire display or draw the background
draw the entire scene (blit all the objects)
update the display by calling either pygame.display.update() or pygame.display.flip()

How do i change the color of my rectangles live?

So, i have this code:
import pygame
pygame.init()
surface = pygame.display.set_mode((400,1000))
surface.fill((0,0,0))
color = (255,0,255)
pygame.draw.rect(surface, color, pygame.Rect(100, 100, 50, 50))
pygame.draw.rect(surface, color, pygame.Rect(200, 200, 50, 50))
pygame.draw.rect(surface, color, pygame.Rect(100, 200, 50, 50))
pygame.draw.rect(surface, color, pygame.Rect(200, 100, 50, 50))
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.display.update()
And i was wondering how to change the rectangle's colors live (like in real time i guess), i have tried using the time module but im new to it so i don't understand it all that well.
You have to redraw the entire scene in each frame. he typical PyGame application loop has to:
limit the frames per second to limit CPU usage with pygame.time.Clock.tick
handle the events by calling either pygame.event.pump() or pygame.event.get().
update the game states and positions of objects dependent on the input events and time (respectively frames)
clear the entire display or draw the background
draw the entire scene (blit all the objects)
update the display by calling either pygame.display.update() or pygame.display.flip()
In pygame exists a timer event. Use pygame.time.set_timer() to repeatedly create a USEREVENT in the event queue. The time has to be set in milliseconds.
For a timer event you need to define a unique user events id. The ids for the user events have to be between pygame.USEREVENT (24) and pygame.NUMEVENTS (32). See also Is there a way to have different tick rates for differents parts of my code in pygame?.
Define a list of colors and use random.shuffle to change the colors when the timer event occurs.
import pygame, random
pygame.init()
surface = pygame.display.set_mode((400,1000))
clock = pygame.time.Clock()
timer_interval = 500 # 0.5 seconds
timer_event_id = pygame.USEREVENT + 1
pygame.time.set_timer(timer_event_id, timer_interval)
colors = [(255,0,0), (255,255,0), (0,255,0), (0,0,255)]
running = True
while running:
clock.tick(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == timer_event_id:
random.shuffle(colors)
surface.fill((0,0,0))
pygame.draw.rect(surface, colors[0], pygame.Rect(100, 100, 50, 50))
pygame.draw.rect(surface, colors[1], pygame.Rect(200, 200, 50, 50))
pygame.draw.rect(surface, colors[2], pygame.Rect(100, 200, 50, 50))
pygame.draw.rect(surface, colors[3], pygame.Rect(200, 100, 50, 50))
pygame.display.update()
pygame.quit()

How to fix pygame menu (space invaders)?

This is my first game so excuse the messy code. I am making a space invaders game and everything i implemented is working fine (sprites, function of the game, music, pause screen, etc). I wanted to implement a really simple menu screen where, if you press C, the game starts. However, the problem with this is that no matter where i call the menu function, there is always a problem, here is the code (im just going to post the menu function and main loop since everything else i believe is not needed).
import pygame
import random
import math
from pygame import mixer
# Start pygame
pygame.init()
# Create Screen
screen = pygame.display.set_mode((1000, 710))
# Background Image
background = pygame.image.load('background.png').convert_alpha()
# Menu Variables
menu_font = pygame.font.Font('freesansbold.ttf', 65)
menuX = 380
menuY = 250
# Menu Function
def game_intro(x, y):
menu = True
while menu:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_c:
menu = False
if event.key == pygame.K_q:
pygame.quit()
quit()
# Menu Text
menu_text = menu_font.render("Space Invaders", True, (255, 255, 255))
screen.blit(menu_text, (x, y))
pygame.display.update()
# Game Loop
running = True
while running:
# RGB - Red, Green, Blue
screen.fill((0, 0, 0))
# Background Image
screen.blit(background, (0, 0))
----game_intro(menuX,menuY)---IF I PUT IT HERE, THE ACTUAL GAME APPEARS FOR ONE SECOND AND IT GOES BACK TO MAIN MENU-----------
# Making the screen stay still
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
--------game_intro(menuX,menuY)--- IF I PUT IT HERE, THE GAME APPEARS ONLY WHEN 'c' IS BEING HELD DOWN-----------------
*more code*
# Updating
pygame.display.update()
if i put it above pygame.display.update(), then the same thing happens: the game appears for one second and then it goes back to the menu screen. I have tried to search everywhere but the videos either are from 2014, and the websites with some similar problem don't explain how to fix it. Please help.
First of all you should throw the while loop out of your function.
def game_intro(x, y):
# Menu Text
menu_text = menu_font.render("Space Invaders", True, (255, 255, 255))
screen.blit(menu_text, (x, y))
the missing code gets put in the mainloop like this
...
# Making the screen stay still
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_c:
menu = False
if event.key == pygame.K_q:
pygame.quit()
...
now in your mainloop you need to decide whether to draw the menu or the game
if menu:
game_intro(x, y)
else:
#CODE THAT DRAWS THE GAME
all together:
import pygame
import random
import math
from pygame import mixer
# Start pygame
pygame.init()
# Create Screen
screen = pygame.display.set_mode((1000, 710))
# Background Image
background = pygame.image.load('background.png').convert_alpha()
# Menu Variables
menu_font = pygame.font.Font('freesansbold.ttf', 65)
menuX = 380
menuY = 250
# Menu Function
def game_intro(x, y):
# Menu Text
menu_text = menu_font.render("Space Invaders", True, (255, 255, 255))
screen.blit(menu_text, (x, y))
# Game Loop
running = True
while running:
# RGB - Red, Green, Blue
screen.fill((0, 0, 0))
# Background Image
screen.blit(background, (0, 0))
# Making the screen stay still
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_c:
menu = False
if event.key == pygame.K_q:
pygame.quit()
if menu:
game_intro(x, y)
else:
# CODE THAT DRAWS THE GAME
# Updating
pygame.display.update()
this should work
note that you need to set menu to True somewhere to get into the menu

Updating the position of a rectangle

I am trying to get familiar with pygame so am starting with a simple program that draws a rectangle and moves it around with the mouse. The rectangle draws fine however it does not move with the mouse position and I cannot think why.
I found one other with this problem however this fix didnt work for me and was much more long winded than I felt it needed to be.
pygame.init()
screen = pygame.display.set_mode((500,300))
# --- mainloop / event loop ---
running = True
playerstartposX = 100
playerstartposY = 100
playerwidth = 50
playerheight = 50
screen.fill((30,30,30))
newrect = pygame.draw.rect(screen, (255,0,0) , ( playerstartposX ,
playerstartposY ,
playerwidth ,
playerheight))
pygame.display.update()
while running:
pygame.time.delay(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == 4: #if event is mouse motion
newrect.move(event.pos) #move the rectangle to mouse pos
pygame.display.update()
pygame.quit()
4 is not an event type. An event type is MOUSEMOTION (see pygame.event).
Create a pygame.Rect object:
newrect = pygame.Rect(playerstartposX, playerstartposY, playerwidth, playerheight)
Change its position when the event occurs:
if event.type == pygame.MOUSEMOTION:
newrect.center = event.pos
In the main application loop you've to continuously
handle the events
clear the display
draw the scene respectively rectangle
update the display
If you want to control the frames per second, then you can pass a parameter to the method .tick() of pygame.time.Clock rather than pygame.time.delay:
import pygame
pygame.init()
screen = pygame.display.set_mode((500,300))
clock = pygame.time.Clock()
running = True
playerstartposX = 100
playerstartposY = 100
playerwidth = 50
playerheight = 50
newrect = pygame.Rect(playerstartposX, playerstartposY, playerwidth, playerheight)
while running:
clock.tick(60)
# handle the events
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.MOUSEMOTION:
newrect.center = event.pos
# clear the display
screen.fill((30,30,30))
# draw the rectangle
pygame.draw.rect(screen, (255,0,0), newrect)
# update the display
pygame.display.update()
pygame.quit()
First, the event type you need to check against is pygame.MOUSEMOTION (I believe it's 1024?) and you are checking with 4.
Then you have to redraw the rect on every iteration of the main loop to reflect the updated position

How to draw a square wherever you click in the pygame window

You probably know what I want to do from the title but here's a simple example:
#User clicks somewhere in the pygame window
pos = cursorPosition()
#Function/Class that creates a square where the user clicked.
I have tried this:
import pygame
import sys
running = True
pygame.init()
screen = pygame.display.set_mode((800, 500))
pos = pygame.mouse.get_pos()
class Create():
cx, cy = pygame.mouse.get_pos()
square = pygame.Rect(cx, cy, 50, 50)
def cube(self):
self.square = pygame.Rect(self.cx, self.cy, 50, 50)
pygame.draw.rect(screen, (255, 0, 0), self.square)
pygame.display.flip()
create = Create()
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN:
pos = pygame.mouse.get_pos()
create.cube()
screen.fill((0, 255, 0))
pygame.display.flip()
pygame.quit()
sys.exit()
But it just gives me a Blue screen and when I click anywhere it doesn't do anything, so if you can help me it would be much appreciated. Thanks!
EDIT: I've managed to do it but now I face another problem:
The square would appear only if I hold down the mouse button.
This is the code
import pygame
import sys
running = True
pygame.init()
screen = pygame.display.set_mode((800, 500))
pos = pygame.mouse.get_pos()
class Create():
cx, cy = pygame.mouse.get_pos()
square = pygame.Rect(cx, cy, 50, 50)
def cube(self):
self.cx, self.cy = pygame.mouse.get_pos()
self.square = pygame.Rect(self.cx, self.cy, 50, 50)
pygame.draw.rect(screen, (255, 0, 0), self.square)
pygame.display.flip()
create = Create()
while running:
screen.fill((0, 255, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN:
create.cube()
pygame.display.flip()
pygame.quit()
sys.exit()
It's great to see that you are making a good effort to solve the by yourself, and that you are editing the question with the work you've done so far!
What I added to the code basically allows the user to change where the cube is being drawn. If you would like to draw multiple cubes, with their positions based on the mouse clicks from the user, edit your question to add those details, and leave a comment below.
First, I wrote a new class called Cube, which essentially has the same code as Create. I won't go into it in detail, but generally in object-oriented programming, objects are nouns, and their methods are actions. Your class is the opposite, which isn't how object-oriented code is generally written.
I added the update() method which simply updates some of the object's fields with the position of the mouse. Your original code was defining class fields or static variables. I won't go into to too much detail here, but if we were to make 100 instances of cube, we would want to have the positions for all the cubes, right? In cases like these, you are operating on the objects, not the class.
Then, there is one variable which gets set to true after the first mouse click, and, as a result, the cube starts being drawn to the screen.
Here is the fixed code:
import pygame
running = True
pygame.init()
screen = pygame.display.set_mode((800, 500))
class Cube:
def update(self):
self.cx, self.cy = pygame.mouse.get_pos()
self.square = pygame.Rect(self.cx, self.cy, 50, 50)
def draw(self):
pygame.draw.rect(screen, (255, 0, 0), self.square)
cube = Cube()
drawing_cube = False
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN:
cube.update()
drawing_cube = True
screen.fill((0, 255, 0))
if drawing_cube:
cube.draw()
pygame.display.flip()
pygame.quit()
quit()
I hope this answer helped you, and if you have any further questions, please feel free to leave a comment below!
I have also come across this problem and after a lot of messing around and frustration came up with the following:
import sys
import pygame
import time
pygame.init()
white = (255, 255, 255)
red = (255, 0, 0)
size = (700, 500)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("OwO")
mouse_cords = []
clicked = False
def draw(cord_list, zero):
''' This is what will draw on the screen when the mouse clicks using recursion'''
pygame.draw.circle(screen, red, cord_list[zero], 100, 1)
zero += 1
if len(cord_list) > zero:
draw(cord_list, zero)
done = False
clock = pygame.time.Clock()
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
screen.fill(white)
if pygame.mouse.get_pressed()[0]:
mouse_cords.append(pygame.mouse.get_pos())
clicked = True
if clicked == True:
draw(mouse_cords, 0)
pygame.display.flip()
clock.tick(60)
pygame.quit()
As you can tell I used recursion to solve this problem. Sorry it's circles not boxes but Im sure you can figure out how to change that.
I am a beginner developer and my method is probably not the most efficient, however it does work. I know that I am writing 2 years late, but I am writing this incase anyone has the same question as I did which is to create multiple rectangles, squares or circles with a mousebutton press or in general any event.
I implemented a class to create a Cube object just like Michael O'Dwyer wrote in his explanation, and while his solution works to create one cube at a time, I needed to create multiple for myself.
In addition to his solution, I just created a list "cubeList" and with each mousebutton event I created a new cube object and appended it to that cubeList. Then, I used a for loop in order to iterate through each cube object in the cubeList and used the draw method. This way, I am able to have multiple cubes drawn at the same time, and I am sure there might be a more efficient or better method to do this, but this worked for me.
import pygame
WIDTH, HEIGHT = 900, 500
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()
WHITE = (255,255,255)
RED = (255,0,0)
GREEN = (0,255,0)
BLUE = (0,0,255)
Square1 = pygame.Rect(30,30,60,60)
Square2 = pygame.Rect(90,30,60,60)
class Cube:
def update(self):
self.cx, self.cy = pygame.mouse.get_pos()
self.square = pygame.Rect(self.cx - 25, self.cy - 25, 50, 50)
def draw(self):
pygame.draw.rect(WIN, GREEN, self.square)
def main():
cubeCount = 0
run = True
cubeList = []
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
print("Ending")
run = False
if event.type == pygame.MOUSEBUTTONDOWN:
cube = Cube()
cubeList.append(cube)
cube.update()
clock.tick(60)
WIN.fill((BLUE))
pygame.draw.rect(WIN,RED, Square1)
pygame.draw.rect(WIN, GREEN, Square2)
for x in cubeList:
x.draw()
pygame.display.flip()
pygame.quit()
if __name__ == "__main__":
main()

Categories