So I was testing out pygame and I wanted to draw a simple rectangle. There are no error messages when I run the code but the rectangle doesn't show up in the window. What I see is a blank white Pygame window pop up. Does anyone know why?
Currently using Python3 and Pygame 1.9.4 on my mac.
Here is my code,
import pygame
import pygame.font
pygame.init()
# Colours
BLACK = ( 0, 0, 0)
WHITE = (255,255,255)
GREEN = ( 0,255, 0)
RED = (255, 0, 0)
BLUE = ( 0, 0,255)
# Dimensions of screen
size = (400,500)
WIDTH = 500
HEIGHT = 400
screen = pygame.display.set_mode(size)
# Loop Switch
done = False
# Screen Update Speed (FPS)
clock = pygame.time.Clock()
# ------- Main Program Loop -------
while not done:
# --- Main Event Loop ---
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
pygame.draw.rect(screen,(78,203,245),(0,0,250,500),5)
screen.fill(GREEN)
pygame.display.flip()
#Setting FPS
clock.tick(60)
#Shutdown
pygame.quit()
You do not want to fill the screen with green every 60 ticks
To fix this, simply put screen.fill(GREEN) outside of the Main loop.
The only time you want screen.fill inside your while loop, is when your adding movement into your program.
I strongly suggest you make a function called draw and draw things outside of your while loop.
I have found the problem:
first of, Glitchd is correct, but you forget to update:
import pygame
import pygame.font
pygame.init()
# Colours
BLACK = ( 0, 0, 0)
WHITE = (255,255,255)
GREEN = ( 0,255, 0)
RED = (255, 0, 0)
BLUE = ( 0, 0,255)
# Dimensions of screen
size = (400,500)
WIDTH = 500
HEIGHT = 400
screen = pygame.display.set_mode(size)
# Loop Switch
done = False
# Screen Update Speed (FPS)
clock = pygame.time.Clock()
# ------- Main Program Loop -------
while not done:
# --- Main Event Loop ---
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
screen.fill(GREEN)
pygame.draw.rect(screen,(78,203,245),(0,0,250,500),5)
pygame.display.flip()
pygame.display.update()
#Setting FPS
clock.tick(60)
#Shutdown
pygame.quit()
U are drawing a shape and then covering it up with green, swap
pygame.draw.rect(screen,(78,203,245),(0,0,250,500),5)
screen.fill(GREEN)
Those 2 around
The problem is that you draw the shape and after that you 'fill' (cover) it with green, so try something like that:
screen.fill(GREEN) #first fill the screen with green
pygame.draw.rect(screen,(78,203,245),(0,0,250,500),5) #and after that draw the rectangle
The error is obvious as first you are drawing a shape then covering it with color . Your code is right but need some rearrangement.
screen.fill("your color") # First you should fill the screen with color
pygame.draw.rect(screen,(78,203,245),(0,0,250,500),5) # Then u should draw any shape
Each of the previously given answers fail to properly elaborate why this issue occurs. It is not about the order of drawing, filling operations; it is about your timing on calling the pygame.display.flip function, or shortly: updating the screen. Your code draws a rectangle, fills the screen with green, and then updates the screen. What it should have done instead is draw the rectangle, update the screen and then fill the screen with green. That way the screen is updated after you draw the rectangle before the screen is filled with green, therefore you can see it:
import pygame
import pygame.font
pygame.init()
# Colours
BLACK = ( 0, 0, 0)
WHITE = (255,255,255)
GREEN = ( 0,255, 0)
RED = (255, 0, 0)
BLUE = ( 0, 0,255)
# Dimensions of screen
size = (400,500)
WIDTH = 500
HEIGHT = 400
screen = pygame.display.set_mode(size)
# Loop Switch
done = False
# Screen Update Speed (FPS)
clock = pygame.time.Clock()
# ------- Main Program Loop -------
while not done:
# --- Main Event Loop ---
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
#In each case you draw the rectangle and then fill the screen with green
pygame.draw.rect(screen,(78,203,245),(0,0,250,500),5)
pygame.display.flip()
screen.fill(GREEN)
#Setting FPS
clock.tick(60)
#Shutdown
pygame.quit()
In a nutshell, you should update after you draw the rectangle.
you should add pygame.display.update() in the while not done loop. pygame.display.update updates the screen. You have this problem because you drew all of the drawings but did not update the screen.
You should first cover the screen with green and then draw your shape because otherwise it will get covered.
Related
I am making a program with a graph that scrolls and I just need to move a section of the screen.
If I do something like this:
import pygame
screen = pygame.display.set_mode((300, 300))
sub = screen.subsurface((0,0,20,20))
screen.blit(sub, (30,40))
pygame.display.update()
It gives the error message: pygame.error: Surfaces must not be locked during blit
I assume it means the child is locked to its parent surface or something but how else could I go about doing this?
screen.subsurface creates a surface, which reference to the original surface. From documentation:
Returns a new Surface that shares its pixels with its new parent.
To avoid undefined behaviour, the surfaces get locked. You've to .copy the surface, before you can .blit it to its source:
sub = screen.subsurface((0,0,20,20)).copy()
screen.blit(sub, (30,40))
Just don't draw to the screen surface directly. Create a Surface for each part of your game/UI, and blit each of those to the screen.
import pygame
def main():
pygame.init()
screen = pygame.display.set_mode((640, 480))
# create two parts: a left part and a right part
left_screen = pygame.Surface((400, 480))
left_screen.fill((100, 0, 0))
right_screen = pygame.Surface((240, 480))
right_screen.fill((200, 200, 0))
x = 100
while True:
events = pygame.event.get()
for e in events:
if e.type == pygame.QUIT:
return
# don't draw to the screen surface directly
# draw stuff either on the left_screen or right_screen
x += 1
left_screen.fill(((x / 10) % 255, 0, 0))
# then just blit both parts to the screen surface
screen.blit(left_screen, (0, 0))
screen.blit(right_screen, (400, 0))
pygame.display.flip()
if __name__ == '__main__':
main()
I'm writing a program in pygame in which I want to draw circles on several surfaces, so that when I erase a circle (redraw it with the transparent colorkey) I get the picture that was in the layer below back. However, I seem to be stuck at an early step and can't seem to draw a circle on a surface (as opposed to the background display). Here is a minimal example:
import pygame
pygame.init()
width = 400
height = 400
screen = pygame.display.set_mode((width, height))
surf1 = pygame.Surface((width,height))
surf1.fill((0,255,0))
pygame.draw.circle(surf1, (0,0,0), (200,2000), 5)
screen.blit(surf1, (0,0))
exit = False
while not exit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
exit = True
pygame.display.update()
pygame.quit()
I expected to get a green surface with a black circle in the middle, but I only get a green surface. What am I doing wrong?
Thanks!
You have a typo in the coordinates for the circle, it should be
pygame.draw.circle(surf1, (0,0,0), (200,200), 5)
i.e. a 200 instead of a 2000.
I am new into Python and pyGame and i have a problem with scaling an image.
I want to zoom an image in pygame.
The pygame documentation claims that
pygame.transform.scale()
should scale to a new resolution.
But in my example below it does not work - it crops the image instead of resizing it!?
What am i doing wrong?
#!/usr/bin/env python3
# coding: utf-8
import pygame
from pygame.locals import *
# Define some colors
BLACK = (0, 0, 0)
pygame.init()
# Set the width and height of the screen [width, height]
screen = pygame.display.set_mode((1920, 1080))
pic = pygame.image.load('test.jpg').convert()
pic_position_and_size = pic.get_rect()
# Loop until the user clicks the close button.
done = False
# Clear event queue
pygame.event.clear()
# -------- Main Program Loop -----------
while not done:
for event in pygame.event.get():
if event.type == QUIT:
done = True
elif event.type == KEYDOWN:
if event.key == K_ESCAPE:
done = True
# background in black
screen.fill(BLACK)
# Copy image to screen:
screen.blit(pic, pic_position_and_size)
# Update the screen with what we've drawn.
pygame.display.flip()
pygame.display.update()
pygame.time.delay(10) # stop the program for 1/100 second
# decreases size by 1 pixel in x and y axis
pic_position_and_size = pic_position_and_size.inflate(-1, -1)
# scales the image
pic = pygame.transform.scale(pic, pic_position_and_size.size)
# Close the window and quit.
pygame.quit()
pygame.transform.scale() does not work very well for your case. If you shrink a Surface by such a small amount, the algorithm just crops the last column and row of pixels. If you now repeat this process over and over again with the same Surface, you get the strange behaviour you see.
A better approach would be to keep a copy of your original Surface around, and use that for creating the scaled image. Also, using smoothscale instead of scale may also lead to a better effect; it's up to you if you want to use it.
Here's a "fixed" version of your code:
#!/usr/bin/env python3
# coding: utf-8
import pygame
from pygame.locals import *
# Define some colors
BLACK = (0, 0, 0)
pygame.init()
# Set the width and height of the screen [width, height]
screen = pygame.display.set_mode((1920, 1080))
org_pic = pygame.image.load('test.jpg').convert()
pic_position_and_size = org_pic.get_rect()
pic = pygame.transform.scale(org_pic, pic_position_and_size.size)
# Loop until the user clicks the close button.
done = False
# Clear event queue
pygame.event.clear()
# -------- Main Program Loop -----------
while not done:
for event in pygame.event.get():
if event.type == QUIT:
done = True
elif event.type == KEYDOWN:
if event.key == K_ESCAPE:
done = True
# background in black
screen.fill(BLACK)
# Copy image to screen:
screen.blit(pic, (0,0))
# Update the screen with what we've drawn.
pygame.display.flip()
pygame.display.update()
pygame.time.delay(10) # stop the program for 1/100 second
# decreases size by 1 pixel in x and y axis
pic_position_and_size = pic_position_and_size.inflate(-1, -1)
# scales the image
pic = pygame.transform.smoothscale(org_pic, pic_position_and_size.size)
# Close the window and quit.
pygame.quit()
I am just starting to learn pygame graphics. I drew a circle in pygame and was wondering how I program it to change colors.
For example: it changes colors from blue to red.
I need it to keep changing colors until I close pygame and it would be nice if the colors gradually changed from one to another instead of an instant change? Any ideas how I could do this?
import pygame
pygame.init()
RED = (255, 0, 0)
BLUE = ( 0, 0,255)
BLACK = ( 0, 0, 0)
SIZE = (1000,1000)
screen = pygame.display.set_mode(SIZE)
pygame.draw.circle(screen,RED,(500,500),200)
pygame.display.flip()
pygame.time.wait(3000)
pygame.quit()
I shall progress from simple to harder, and more complex..
Simplest: A for loop that changes the color 3 times, simplest:
import pygame
pygame.init()
RED = (255,0,0)
BLUE = (0,0,255)
BLACK = (0,0,0)
SIZE = (1000,1000)
screen = pygame.display.set_mode(SIZE)
colors = (RED, BLACK, BLUE) # tho allow you to iterate over the colors
for c in colors:
pygame.draw.circle(screen,c,(500,500),200)
pygame.display.flip()
pygame.time.wait(1000)
pygame.quit()
Medium: Now an infinite loop, that ends when you close the window..
import pygame, itertools
RED = (255,0,0)
BLUE = (0,0,255)
BLACK = (0,0,0)
colors = (RED, BLACK, BLUE) # to allow you to iterate over the colors
SIZE = (1000,1000)
screen = pygame.display.set_mode(SIZE)
# to cycle through the colors
cycle = itertools.cycle(colors) # create an infinite series..
clock = pygame.time.Clock() # regulate fps
while True:
# handling events
for event in pygame.event.get():
if event.type == pygame.QUIT: # close window event
pygame.quit()
c = cycle.next()
pygame.draw.circle(screen,c,(500,500),200)
pygame.display.flip()
clock.tick(6) # run at maximum 6 frames per second
Hardest and most complex: This is the final one, the colors fade into the next one..
import pygame, itertools
def fade_into(c1, c2, n):
""" Give the next color to draw \n"""
"Args: c1,c2 => colors, n => int"
dif = [(c1[i]-c2[i])/float(n) for i in range(3)] # calculate the per-frame difference
return [c1[i]-dif[i] for i in range(3)] # subtract that difference
RED = (255,0,0)
BLUE = (0,0,255)
BLACK = (0,0,0)
FADE_SPEED = 80 # no of frames for shifting
colors = (RED, BLACK, BLUE) # to allow you to iterate over the colors
SIZE = (1000,1000)
screen = pygame.display.set_mode(SIZE)
# to cycle through the colors
cycle = itertools.cycle(colors)
## needed for fading
c_color = cycle.next() # RED current_color
n_color = cycle.next() # BLACK next_color
frames = FADE_SPEED
## --------------
clock = pygame.time.Clock() # regulate fps
while True:
# handling events
for event in pygame.event.get():
if event.type == pygame.QUIT: # close window event
pygame.quit()
c_color = fade_into(c_color, n_color, frames) # get next color
pygame.draw.circle(screen,map(int,c_color),(500,500),200)
pygame.display.flip()
frames -= 1
if frames == 0: # translation complete
frames = FADE_SPEED
n_color = cycle.next() # get next color
clock.tick(40) # run at maximum of 40 frames per second
If you have any doubts, please comment below..
Pygame does not have scene graph, so you need to redraw your shape in a loop and call display.flip() to update.
I'm new to pygame and currently I'm working on creating a memory game where the computer displays boxes at random positions for like a second and then the user has to click on where he/she thinks those boxes are. It's kind of like this game:
However I'm not really sure how to make the computer display the boxes with like a letter or symbol e.g. 'T' or '%'. (I've already made the grid).
Could anyone please help? It would be really appreciated.
import pygame
size=[500,500]
pygame.init()
screen=pygame.display.set_mode(size)
# Colours
LIME = (0,255,0)
RED = (255, 0, 0)
BLACK = (0,0,0)
PINK = (255,102,178)
SALMON = (255,192,203)
WHITE = (255,255,255)
LIGHT_PINK = (255, 181, 197)
SKY_BLUE = (176, 226, 255)
screen.fill(BLACK)
# Width and Height of game box
width=50
height=50
# Margin between each cell
margin = 5
# Create a 2 dimensional array. A two dimesional
# array is simply a list of lists.
grid=[]
for row in range(20):
# Add an empty array that will hold each cell
# in this row
grid.append([])
for column in range(20):
grid[row].append(0) # Append a cell
# Set row 1, cell 5 to one. (Remember rows and
# column numbers start at zero.)
grid[1][5] = 1
# Set title of screen
pygame.display.set_caption("Spatial Recall")
#Loop until the user clicks the close button.
done=False
# Used to manage how fast the screen updates
clock=pygame.time.Clock()
# -------- Main Program Loop -----------
while done==False:
for event in pygame.event.get(): # User did something
if event.type == pygame.QUIT: # If user clicked close
done=True # Flag that we are done so we exit this loop
if event.type == pygame.MOUSEBUTTONDOWN:
# User clicks the mouse. Get the position
pos = pygame.mouse.get_pos()
# Change the x/y screen coordinates to grid coordinates
column=pos[0] // (width+margin)
row=pos[1] // (height+margin)
# Sete t hat location to zero
grid[row][column]=1
print("Click ",pos,"Grid coordinates: ",row,column)
# Draw the grid
for row in range(10):
for column in range(10):
color = LIGHT_PINK
if grid[row][column] == 1:
color = RED
pygame.draw.rect(screen,color,[(margin+width)*column+margin,(margin+height)*row+margin,width,height])
# Limit to 20 frames per second
clock.tick(20)
# Go ahead and update the screen with what we've drawn.
pygame.display.flip()
pygame.quit ()
In order to display text, you have to go through a series of steps. First you will want to get a font by using the command `pygame.font.Font(font name, size). For example:
arialfont=pygame.font.Font('arial', 12)
All available fonts can be gotten from the command pygame.font.get_fonts(). Remember to initialize pygame (pygame.init()) before any of this.
Next, you will have to use the Font.render(text, antialias, color, background=None). For example:
text=arialfont.render('Hello World!', True, (0, 0, 0))
This will return a surface. You can use it just like you would any other surface. Use text.get_rect() to get its rect, then reposition the rect to put it where you want it to be, and blit it to the window. If you don't know anything about surface objects, just ask me.
Here is a working code.
import pygame, sys
pygame.init()#never forget this line
window=pygame.display.set_mode((100, 100))
font=pygame.font.SysFont('arial', 40)
text=font.render('#', True, (0, 0, 0))
rect=text.get_rect()
window.fill((255, 255, 255))
window.blit(text, rect)
pygame.display.update()
while True:
for event in pygame.event.get():
if event.type==pygame.QUIT:
pygame.quit()
sys.exit()