I've tried so many ways of changing a pixel in Pygame, and none of them works with me...
import pygame
import random
width = 640
height = 400
screen = pygame.display.set_mode((width, height))
clock = pygame.time.Clock()
running = True
while running:
x = random.randint(0, width-1)
y = random.randint(0, height-1)
red = random.randint(0, 255)
green = random.randint(0, 255)
blue = random.randint(0, 255)
screen.set_at((x, y), (red, green, blue))
clock.tick(10)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.display.flip()
clock.tick(240)
Nothing happens, just the black screen until I close it.
It looks like you're following this tutorial but you've indented a few essential lines in the wrong place. Remember, Python is white space sensitive; indentation matters!
The last two lines should not be inside the for loop block, they should be in the while loop block.
while running:
# code that draws pixel
pygame.display.flip()
clock.tick(240)
These lines update the display and compute the time between frames.
The way you had it, inside the if statement, the pixel would never get drawn until the pygame.QUIT event was triggered.
Related
I am creating a car game and have come across a problem. I've added a car image with a transparent background into my code but the car appears on the screen with the transparent background visible. I want to make the background to disappear. This is a link to the image: https://www.pngfind.com/mpng/bboJib_car-top-view-png-audi-transparent-png/
Here is the code:
import pygame
pygame.init()
import pygame
pygame.init()
black = (0, 0, 0)
#screen
screen_width = 600
screen_length = 800
screen = pygame.display.set_mode((screen_length, screen_width))
clock = pygame.time.Clock()
FPS = 60
#the car i am having trouble with
car2Img = pygame.image.load('car2.png')
car2_X = 0
car2_Y = 0
carX_change = 0
def car2(x, y):
screen.blit(car2Img, (x, y))
running = True
while running:
screen.fill((119, 118, 110))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
car2(car2_X, car2_Y)
clock.tick(FPS)
pygame.display.update()
pygame.quit()
In order to remove the background from a png image you must use the convert_alpha() function when loading it:
car2Img = pygame.image.load('car2.png').convert_alpha()
If your image doesn't contain alpha then you can use a color key to remove the background:
car2Img.set_colorkey(colorOfBackground)
I get this error when I try to run my pygame code pygame.error: video system not initialized. I'm using Repl.it and am attempting to create an aiming game which can track accuracy and in which you only have 3 lives.
import pygame
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False # Here we exit the Loop and execute what after
pygame.quit()
# Play Surface
width = 1080
height = 720
playSurface = pygame.display.set_mode((width, height))
pygame.display.set_caption('Aim Practice')
# Colors
red = pygame.Color(0, 0, 0)
blue = pygame.Color(255, 255, 255)
Image of most of the code
https://repl.it/join/dppwnpin-isa__paz (You can view the full code here!)
The issue is that you event loop is running before anything is initialised. As #zenofpython says in his answer, the calls to prepare the window must come before the main event loop.
Your main event loop is first, and nothing is setup to run.
Just moving the code around will fix it:
import pygame
# FIRST, HANDLE ALL THE INITIALISATION OF PYGAME, FONTS, MIXER etc.
# Play Surface
width = 1080
height = 720
playSurface = pygame.display.set_mode((width, height))
pygame.display.set_caption('Aim Practice')
# Colors
red = pygame.Color(0, 0, 0)
blue = pygame.Color(255, 255, 255)
# ... AND THE REST
# MAIN LOOP
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False # Here we exit the Loop and execute what after
playSurface.fill( blue ) # fill the screen
pygame.display.flip() # flush all the drawing operations to the window
fpsController.tick_busy_loop(60) # clamp the max-FPS
pygame.quit()
You should use pygame.display.set_mode before running your event loop. pygame.event.get won't work if you haven't created a window.
I am trying to allow resizing for this app, I put the RESIZABLE flag, but when I try to resize, it messes up! Try my code.
It is a grid program, when the window resizes I want the grid to also resize/shrink.
import pygame,math
from pygame.locals import *
# Define some colors
black = ( 0, 0, 0)
white = ( 255, 255, 255)
green = ( 0, 255, 0)
red = ( 255, 0, 0)
# This sets the width and height of each grid location
width=50
height=20
size=[500,500]
# This sets the margin between each cell
margin=1
# Initialize pygame
pygame.init()
# Set the height and width of the screen
screen=pygame.display.set_mode(size,RESIZABLE)
# Set title of screen
pygame.display.set_caption("My Game")
#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:
height+=10
# Set the screen background
screen.fill(black)
# Draw the grid
for row in range(int(math.ceil(size[1]/height))+1):
for column in range(int(math.ceil(size[0]/width))+1):
color = white
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()
# Be IDLE friendly. If you forget this line, the program will 'hang'
# on exit.
pygame.quit ()
Please tell me whats wrong, thanks.
The answer for this problem (allow the Pygame window and the surface inside it to resize) is simply to recreate the resizable window with an updated size, when the user changes its dimensions (done on pygame.VIDEORESIZE events).
>>> import pygame
>>> help(pygame.display.set_mode)
Help on built-in function set_mode in module pygame.display:
set_mode(...)
set_mode(size=(0, 0), flags=0, depth=0, display=0, vsync=0) -> Surface
Initialize a window or screen for display
>>>
This removes all previous content on the window surface, so below
there's a process to continue with the current window content.
Some example code:
import pygame, sys
pygame.init()
# Create the window, saving it to a variable.
surface = pygame.display.set_mode((350, 250), pygame.RESIZABLE)
pygame.display.set_caption("Example resizable window")
while True:
surface.fill((255,255,255))
# Draw a red rectangle that resizes with the window.
pygame.draw.rect(surface, (200,0,0), (surface.get_width()/3,
surface.get_height()/3, surface.get_width()/3,
surface.get_height()/3))
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.quit()
sys.exit()
if event.type == pygame.VIDEORESIZE:
# There's some code to add back window content here.
surface = pygame.display.set_mode((event.w, event.h),
pygame.RESIZABLE)
How to continue with the current window content:
Here's some steps to add back the previous window content:
make a second variable, set to the value of the old window surface variable.
create the new window, storing it as the old variable.
draw the second surface onto the first one (old variable) - use the blit function.
use this variable and delete the new variable (optional, use del) to not use extra memory.
Some example code for the above steps (replaces pygame.VIDEORESIZE event if statement):
if event.type == pygame.VIDEORESIZE:
old_surface_saved = surface
surface = pygame.display.set_mode((event.w, event.h),
pygame.RESIZABLE)
# On the next line, if only part of the window
# needs to be copied, there's some other options.
surface.blit(old_surface_saved, (0,0))
del old_surface_saved
You are not updating your width, height, or size when the window changes.
From the docs: http://www.pygame.org/docs/ref/display.html
If the display is set with the pygame.RESIZABLE flag,
pygame.VIDEORESIZE events will be sent when the user adjusts the
window dimensions.
You can get the new size, w, h from the event VIDEORESIZE http://www.pygame.org/docs/ref/event.html
A simple Hello World window that is resizable, plus I was playing around with classes.
Broken down into two files, one for defining the colour constants.
import pygame, sys
from pygame.locals import *
from colors import *
# Data Definition
class helloWorld:
'''Create a resizable hello world window'''
def __init__(self):
pygame.init()
self.width = 300
self.height = 300
DISPLAYSURF = pygame.display.set_mode((self.width,self.height), RESIZABLE)
DISPLAYSURF.fill(WHITE)
def run(self):
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == VIDEORESIZE:
self.CreateWindow(event.w,event.h)
pygame.display.update()
def CreateWindow(self,width,height):
'''Updates the window width and height '''
pygame.display.set_caption("Press ESC to quit")
DISPLAYSURF = pygame.display.set_mode((width,height),RESIZABLE)
DISPLAYSURF.fill(WHITE)
if __name__ == '__main__':
helloWorld().run()
colors.py:
BLACK = (0, 0,0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
YELLOW = (255, 255, 0)
BLUE = (0,0,255)
GREEN = (0,255,0)
A simple way to do which I found was the following code snippet
# Imports
from vars import *
from pygame.locals import *
# Main init
pygame.init()
# Basic vars
run = True
s_width = 1000
s_height = 600
# Making display screen. Don't forget the last tag!
screen = pygame.display.set_mode((s_width, s_height), RESIZABLE)
# Main loop
while run:
# event detection
for event in pygame.event.get():
if event.type == QUIT:
run = False
# The part which matters for our purposes
if event.type == WINDOWRESIZED:
s_width, s_height = screen.get_width(), screen.get_height()
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
run = False
# Test line to see if the window resizing works properly
pygame.draw.line(screen, (255, 255, 255), (int(0.3*s_width), int(0.25*s_height)), (int(0.8*s_width), int(0.25*s_height)))
# Final flip
pygame.display.flip()
# Quit
pygame.quit()
What this does is allows the pygame window to be resized. But since you often have the placing and sizes of a lot of elements/sprites depending on the s_width and s_height, it also detects when the window size is changed and adjusts the dimensions accordingly.
First, You don't detect the new window size before redrawing the screen.
Add the get_size() method at line 45 and it works:
#--------------------------------------------------------------
# Draw the grid
size = pygame.display.get_surface().get_size() // size update
for row in range(int(math.ceil(size[1]/height))+1):
#---------------------------------------------------------
Then you work with a fixed cell size (50, 20) and fill as many cells as possible. If You want to GROW/SHRINK the cells when resizing the window, You will have to define the NUMBER of cells per line/row, then calculate the cell size, then draw them.
I wanted to write a program that, when the user clicks anywhere on the surface of the box, it reveals another smaller box hidden behind it . The code is quite far from being finished at the moment .
Currently i wanted to do an animation that strats when the user clicks anywhere on the screen and stops when the box that covers the small box is gone.
Here is my code :
import random, pygame, sys
from pygame.locals import *
pygame.init()
done = False
clock = pygame.time.Clock()
white = (255,255,255) # COLLORS
black = (0,0,0)
red = (255,0,0)
green = (0,100,0)
display_width = 800 # SCREEN DIMMENSION
display_height = 600
game_display = pygame.display.set_mode((display_width,display_height)) # SCREEN
REVEALSPEED = 8
def draw_icon(x,y):
icon = pygame.Rect(x+10,y+10,20,20)
pygame.draw.rect(game_display,red,icon)
def draw_cover(x,y,coverage):
pygame.draw.rect(game_display,white,(x,y,40,40))
draw_icon(x,y)
if coverage > 0:
pygame.draw.rect(game_display, green, (x, y, coverage, 40))
pygame.display.update()
clock.tick(10)
def revealBoxesAnimation(x,y): # Do the "box reveal" animation.
for coverage in range(40, (-REVEALSPEED) - 1, -REVEALSPEED):
draw_cover(x, y, coverage)
def game_loop():
done = False
mouseClicked = False
while done != True:
x = (display_width - 40) / 2
y = (display_height - 40) / 2
for event in pygame.event.get(): # PRESSED KEYS EFFECTS
if event.type == pygame.QUIT:
done = True
elif event.type == MOUSEBUTTONUP:
mouseClicked = True
mousex, mousey = pygame.mouse.get_pos()
if mousex != None and mousey != None :
if mouseClicked == True :
revealBoxesAnimation(x, y)
game_display.fill(white)
pygame.display.update()
clock.tick(60)
game_loop()
In the draw_cover function I said that the program should only draw the big box if the value of 'coverage' is greater than zero.
In the revealBoxesAnimation function, I use the range function to lower the value of coverage from 40 all the way to 0 by 8 at a time (40, 32, 24, 16, 8, 0, -8). Still, when the value of coverage hits zero, the animation does not stop. It goes on in an infinite loop.
How so ?
While there was already a fix suggested in another answer, I recommend to rewrite your code entirely.
Note how all the logic is encapsulated in the Box class (especially the update method), instead of 3 different functions; and now we only have a single, non-blocking main loop.
We have a single class for both, the non-shrinking and the shrinking box, but we could also just create another class for the thing that should not shrink and skip the shrinking argument.
So basically, if the box shrinks, we shrink the rect, create a new Surface with the smaller size, and use that for drawing.
When a mouse click occurs, we just need to create two Box instances, one not shrinking, and a bigger one shrinking.
Here's a full, running example:
import random, pygame, sys
from pygame.locals import *
pygame.init()
clock = pygame.time.Clock()
display_width = 800 # SCREEN DIMMENSION
display_height = 600
game_display = pygame.display.set_mode((display_width,display_height)) # SCREEN
colors = pygame.color.THECOLORS
class Box(pygame.sprite.Sprite):
def __init__(self, group, center, size, color, shrinking=False):
pygame.sprite.Sprite.__init__(self, group)
self.image = pygame.surface.Surface((size, size))
self.image.fill(color)
self.shrinking = shrinking
self.rect = self.image.get_rect(center=center)
def update(self):
if self.shrinking:
self.rect.inflate_ip(-1, 0)
new = pygame.surface.Surface((self.rect.w, self.rect.h))
new.blit(self.image, (0, 0))
self.image = new
if self.rect.width <= 0:
self.kill()
sprites = pygame.sprite.OrderedUpdates()
def game_loop():
while True:
for event in pygame.event.get(): # PRESSED KEYS EFFECTS
if event.type == pygame.QUIT:
return
elif event.type == MOUSEBUTTONUP:
Box(sprites, event.pos, 20, colors['red'])
Box(sprites, event.pos, 40, colors['green'], True)
sprites.update()
game_display.fill(colors['white'])
sprites.draw(game_display)
pygame.display.update()
clock.tick(60)
game_loop()
The problem is simply that after setting mouseClicked to True, you never have a way to make it false again. The simplest fix in my opinion would be to replace
elif event.type == MOUSEBUTTONUP:
mouseClicked = True
with
mouseClicked = pygame.mouse.get_pressed()[0]
(Outside of the event for loop, as you only need to do so once per a frame.)
I am trying to make a game in which you have to click the apple and then it goes off to random position.You have 5 seconds (for now), and you have to click the apple image many times as you cant.My game works but i have two problems:
1)After the game ends , the program does not respond.
2)The time keeps on updating itself (it keeps on flickering) i do not want that.
How do I correct these two bugs?
Here is my code:
import pygame
import time
import random
pygame.init()
foodimg=pygame.image.load("food.png")
foodrect=foodimg.get_rect()
#Colours
white = (255,255,255)
black = (0,0,0)
red = (255,0,0)
#Game Display
display_width = 1080
display_height = 720
gameDisplay = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption('Click It! ~ Snapnel Productions')
gameDisplay.fill((white))
font=pygame.font.SysFont("Arial",30)
a=6
running=True
while running:
gameDisplay.fill((white))
time=pygame.time.get_ticks()/1000
if a==time:
print "Game over"
break
for event in pygame.event.get():
if event.type==pygame.QUIT:
running=False
pygame.quit()
quit()
if event.type == pygame.MOUSEBUTTONDOWN:
# Set the x, y postions of the mouse click
x, y = event.pos
if foodrect.collidepoint(x, y):
foodrect.center=(random.randint(5,1060),random.randint(5,700))
print "New Position: ",foodrect.center
continue
gameDisplay.blit(foodimg,foodrect)
pygame.display.flip()
showtime=font.render("Time: "+str(time),0,(0,0,0))
gameDisplay.blit(showtime,(950,10))
pygame.display.flip()
Here is my food image.
For me the program exits normally (i ran it on linux, python 2.6).
To remove flockering:
gameDisplay.blit(foodimg,foodrect)
#pygame.display.flip() < -- remove that
showtime=font.render("Time: "+str(time),0,(0,0,0))
gameDisplay.blit(showtime,(950,10))
pygame.display.flip() # because you should do it after the text is drawed
Flip is used to update surface. You need to update surface after you have everything drawed. What you do is fill everything white, update and then draw a text, update. So you have text drawed and filled white every tick