Program Crashes unsure why - python-3.x

Hello i'm trying to make a simple program to change the background colour on key press but it just crashes. It's to do with my loop but i don't really understand why it crashes.
thanks
import sys, pygame, random, time
from threading import Thread
pygame.init()
black = (0, 0, 0)
white = (255, 255, 255)
green = (0, 100, 0)
red = (255, 0, 0)
Colour = (0,0,0)
size = width, height = 350, 350
screen = pygame.display.set_mode(size)
Running = True
while True:
key = pygame.key.get_pressed()
if key[pygame.K_ESCAPE]: # Escape key
Running = False
elif key[pygame.K_DOWN]: # down key
print("down")
Colour = red
elif key[pygame.K_UP]: # up key
print("h")
Colour = black
elif key[pygame.K_RIGHT]: # right key
Colour = green
print("h")
elif key[pygame.K_LEFT]: # left key
Colour = white
print("h")
pygame.draw.rect(screen, Colour, pygame.Rect(0, 0, width, height))
pygame.display.update()
pygame.display.flip()

You're missing a way for pygame to know if you want to quit the window. Instead of doing key = pygame.key.get_pressed() use:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
pygame.quit()
sys.exit
if event.key == K_UP:
Colour = black
if event.key == K_DOWN:
Colour = red
if event.key == K_LEFT:
Colour = white
if event.key == K_RIGHT:
Colour = green
You also need a way for the program to handle time e.g. not run faster than you can see. You can do this by setting this variable at the top of your code:
clock = pygame.time.Clock()
and running this at the very end of your while loop:
clock.tick(FPS)
where you set the FPS as a number equal to the desired frames per second.
You can also remove your Running = True variable from the program. That should be all you need to get it running. Good luck! Ask questions below.

Two things:
You have a bug: the while loop while go forever because you are testing while True instead of while Running. You could change to while Running or after testing for escape key, you could break to exit the while loop.
Also, all pygame examples I have looked up just now have an event checker. Without that, pygame freezes. If you add it, everything is smooth.
Here are both of those corrected:
import sys, pygame, time
pygame.init()
size = 350, 350
screen = pygame.display.set_mode(size)
Running = True
while Running: # <----- changed this from True to Running
time.sleep(0.03) # avoid blasting the CPU. I think pygame.time.Clock also exists
# this makes pygame responsive
for event in pygame.event.get():
if event.type == pygame.QUIT:
Running = False # <---- or you could just break
# from here is as you originally wrote
key = pygame.key.get_pressed()
if key[pygame.K_ESCAPE]:
print('exit')
Running = False # <---- or you could just break
pygame.quit()
sys.exit()

Related

PyGame. Second composition in modul "mixer.music. doesnt playing, but first plays normally [duplicate]

I tried to use python to display image:
import pygame
win = pygame.display.set_mode((500, 500))
DisplayImage("Prologue.jpg", win)
And when it runs, nothing happened. It also happened for
DisplayImage("Streets.jpg", win)
However, when I tried the exact same thing later on in the code, it ran perfectly.
I checked, the picture was in the same folder as the .py file, and I didn't type the name wrong.
The function is:
def DisplayImage(imageName, screen):
screen.fill((0, 0, 0))
Image = pygame.image.load(imageName).convert()
screen_rect = screen.get_rect()
Image_rect = Image.get_rect().fit(screen_rect)
Image = pygame.transform.scale(Image, Image_rect.size)
screen.blit(Image, [0, 0])
pygame.display.update()
Update:
I commented out all of the lines and copy and pasted that line out so it's the only line that runs. It runs perfectly.
Update 2:
Found the issue. The reason it doesn't work was that the pygame window was "not responding". I don't know what caused it to not respond, but in one of the test runs I didn't make it show "not responding", and the images were loaded fine. The "not responding" always shows up when I type in my player name, and the function looks like this:
def createName():
playerName = input("Enter the player name\n")
desiredName = input("Is "+playerName+" the desired name?[1]Yes/[2]No\n")
if desiredName == "1":
return playerName
elif desiredName == "2":
playerName = createName()
Sometimes when I type the player name nothing happens, and the letters only show up after a while. If this happens, the pygame window is bound to not respond.
You cannot use input in the application loop. input waits for an input. While the system is waiting for input, the application loop will halt and the game will not respond.
Use the KEYDOWN event instead of input:
run = True
while run:
event_list = pygame.event.get()
for event in event_list:
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if pygame.key == pygame.K_1:
# [...]
if pygame.key == pygame.K_2:
# [...]
Another option is to get the input in a separate thread.
Minimal example:
import pygame
import threading
pygame.init()
window = pygame.display.set_mode((400, 400))
clock = pygame.time.Clock()
color = "red"
def get_input():
global color
color = input('enter color (e.g. blue): ')
input_thread = threading.Thread(target=get_input)
input_thread.start()
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
window_center = window.get_rect().center
window.fill(0)
pygame.draw.circle(window, color, window_center, 100)
pygame.display.flip()
pygame.quit()
exit()

Pygame not responding when I press the T key

I am making a program that is supposed to print 'travel' when the T key is pressed. But when I press T, nothing is printed out, unlike it is supposed to.
My detection code:
elif keep_doing_current_event and event.type == draw_intro_text_line_1_event:
typewrite("今天是2121年5月22日。一百年前的今天,天问一号任务火星车“祝融号”")
text = font.render("(按空格键继续)", True, (255, 255, 255))
screen.blit(text, (550, 500))
key = pygame.key.get_pressed()
if key[K_SPACE]:
screen.fill((0, 0, 0))
keep_doing_current_event = False
screen.blit(city_bg, (0, 0))
if key[K_t]:
print("travel")
I have two questions:
Can the code ever make it to the if key[K_t] statement?
If so, is it the keep_doing_current_event = False line that is causing it?
(Extra info: First, some text is typwrited out. Then, when the space key is pressed, the background switches to a mars city background. Finally, when the T key is pressed, the program should print travel)
Your code you need to press space and t at once, to print "travel".
You need to draw the background in the application loop. Use KEYDOWN event to change the state of keep_doing_current_event. Draw the scene depending on keep_doing_current_event:
current_background = .... # what ever
# application loop
while True:
# event loop
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == K_SPACE:
keep_doing_current_event = False
if keep_doing_current_event:
# draw keep_doing_current_event scene
# [...]
typewrite("今天是2121年5月22日。一百年前的今天,天问一号任务火星车“祝融号”")
text = font.render("(按空格键继续)", True, (255, 255, 255))
screen.blit(text, (550, 500))
# [...]
else:
# draw game scene
screen.blit(city_bg, (0, 0))
key = pygame.key.get_pressed()
if key[K_t]:
print("travel")

How to do a PyGame countdown without overlaps? [duplicate]

I started using pygame and I want to do simple game. One of the elements which I need is countdown timer.
How can I do the countdown time (eg 10 seconds) in PyGame?
Another easy way is to simply use pygame's event system.
Here's a simple example:
import pygame
pygame.init()
screen = pygame.display.set_mode((128, 128))
clock = pygame.time.Clock()
counter, text = 10, '10'.rjust(3)
pygame.time.set_timer(pygame.USEREVENT, 1000)
font = pygame.font.SysFont('Consolas', 30)
run = True
while run:
for e in pygame.event.get():
if e.type == pygame.USEREVENT:
counter -= 1
text = str(counter).rjust(3) if counter > 0 else 'boom!'
if e.type == pygame.QUIT:
run = False
screen.fill((255, 255, 255))
screen.blit(font.render(text, True, (0, 0, 0)), (32, 48))
pygame.display.flip()
clock.tick(60)
On this page you will find what you are looking for http://www.pygame.org/docs/ref/time.html#pygame.time.get_ticks
You download ticks once before beginning the countdown (which can be a trigger in the game - the key event, whatever).
For example:
start_ticks=pygame.time.get_ticks() #starter tick
while mainloop: # mainloop
seconds=(pygame.time.get_ticks()-start_ticks)/1000 #calculate how many seconds
if seconds>10: # if more than 10 seconds close the game
break
print (seconds) #print how many seconds
In pygame exists a timer event. Use pygame.time.set_timer() to repeatedly create an USEREVENT. e.g.:
timer_interval = 500 # 0.5 seconds
timer_event = pygame.USEREVENT + 1
pygame.time.set_timer(timer_event , timer_interval)
Note, in pygame customer events can be defined. Each event needs a unique id. The ids for the user events have to be between pygame.USEREVENT (24) and pygame.NUMEVENTS (32). In this case pygame.USEREVENT+1 is the event id for the timer event.
To disable the timer for an event, set the milliseconds argument to 0.
Receive the event in the event loop:
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == timer_event:
# [...]
The timer event can be stopped by passing 0 to the time parameter.
See the example:
import pygame
pygame.init()
window = pygame.display.set_mode((200, 200))
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 100)
counter = 10
text = font.render(str(counter), True, (0, 128, 0))
timer_event = pygame.USEREVENT+1
pygame.time.set_timer(timer_event, 1000)
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
elif event.type == timer_event:
counter -= 1
text = font.render(str(counter), True, (0, 128, 0))
if counter == 0:
pygame.time.set_timer(timer_event, 0)
window.fill((255, 255, 255))
text_rect = text.get_rect(center = window.get_rect().center)
window.blit(text, text_rect)
pygame.display.flip()
pygame.time.Clock.tick returns the time in milliseconds since the last clock.tick call (delta time, dt), so you can use it to increase or decrease a timer variable.
import pygame as pg
def main():
pg.init()
screen = pg.display.set_mode((640, 480))
font = pg.font.Font(None, 40)
gray = pg.Color('gray19')
blue = pg.Color('dodgerblue')
# The clock is used to limit the frame rate
# and returns the time since last tick.
clock = pg.time.Clock()
timer = 10 # Decrease this to count down.
dt = 0 # Delta time (time since last tick).
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
timer -= dt
if timer <= 0:
timer = 10 # Reset it to 10 or do something else.
screen.fill(gray)
txt = font.render(str(round(timer, 2)), True, blue)
screen.blit(txt, (70, 70))
pg.display.flip()
dt = clock.tick(30) / 1000 # / 1000 to convert to seconds.
if __name__ == '__main__':
main()
pg.quit()
There are several ways you can do this- here's one. Python doesn't have a mechanism for interrupts as far as I know.
import time, datetime
timer_stop = datetime.datetime.utcnow() +datetime.timedelta(seconds=10)
while True:
if datetime.datetime.utcnow() > timer_stop:
print "timer complete"
break
There are many ways to do this and it is one of them
import pygame,time, sys
from pygame.locals import*
pygame.init()
screen_size = (400,400)
screen = pygame.display.set_mode(screen_size)
pygame.display.set_caption("timer")
time_left = 90 #duration of the timer in seconds
crashed = False
font = pygame.font.SysFont("Somic Sans MS", 30)
color = (255, 255, 255)
while not crashed:
for event in pygame.event.get():
if event.type == QUIT:
crashed = True
total_mins = time_left//60 # minutes left
total_sec = time_left-(60*(total_mins)) #seconds left
time_left -= 1
if time_left > -1:
text = font.render(("Time left: "+str(total_mins)+":"+str(total_sec)), True, color)
screen.blit(text, (200, 200))
pygame.display.flip()
screen.fill((20,20,20))
time.sleep(1)#making the time interval of the loop 1sec
else:
text = font.render("Time Over!!", True, color)
screen.blit(text, (200, 200))
pygame.display.flip()
screen.fill((20,20,20))
pygame.quit()
sys.exit()
This is actually quite simple. Thank Pygame for creating a simple library!
import pygame
x=0
while x < 10:
x+=1
pygame.time.delay(1000)
That's all there is to it! Have fun with pygame!
Another way to do it is to set up a new USEREVENT for a tick, set the time interval for it, then put the event into your game loop
'''
import pygame
from pygame.locals import *
import sys
pygame.init()
#just making a window to be easy to kill the program here
display = pygame.display.set_mode((300, 300))
pygame.display.set_caption("tick tock")
#set tick timer
tick = pygame.USEREVENT
pygame.time.set_timer(tick,1000)
while 1:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.USEREVENT:
if event.type == tick:
## do whatever you want when the tick happens
print('My tick happened')

PyGame - while loop not running as expected - text not printing to the screen, and other while loop still running

I've been following tutorials for PyGame, but for some reason my gameOver while loop never shows. I've tried to look around for some syntax errors and such, but everything seems fine.
Here's the code, the while gameOver == True: loop is the problem;
# Imports the pygame module.
import pygame
# Initialises all the pygame methods.
pygame.init()
# This will be the width and height of our window.
display_width = 800
display_height = 600
# Sets the caption, or title bar to 'Slither'.
pygame.display.set_caption("Slither")
# Sets the pygame window too whatever display_width and display_height is, so we can change the variable easily - a touple because it only accepts one argument.
gameDisplay = pygame.display.set_mode((display_width,display_height))
# Sets some basic colours using rgb (red,blue,green).
white = (255,255,255)
red = (255,0,0)
green = (0,255,0)
blue = (0,0,255)
black = (0,0,0)
# This variable will decide how many pixels the object will be moving.
block_size = 25
# Returns a font object to the variable font, with the font of Sys, with a size of 25.
font = pygame.font.SysFont(None, 25)
# Sets the frames per second of the game.
FPS = 30
# Returns a clock object to the clock variable.
clock = pygame.time.Clock()
# Defines a function called message_to_screen that takes in 2 arguments, the message itself and it's colour.
def message_to_screen(msg,colour):
# Sets the variable screen_text by using the font method.
screen_text = font.render(msg,True,colour)
# Actually prints the text to the screen.
gameDisplay.blit(screen_text,[display_width/2, display_height/2])
# Creates a function so we can call it again later.
def gameLoop():
# Sets the gameExit variable to False, so we can set it to true later to get out of the loop below -- for QUITTING THE GAME.
gameExit = False
# Game over will be true when the user fails the objective.
gameOver = False
# These will be the coordinates of the head of the snake - we will change them in the while loop.
lead_x = display_width/2 # Divides the resolution of the display by 2, so whatever the resolution is, it'll be in the middle.
lead_y = display_height/2
lead_x_change = 0
lead_y_change = 0
# If the user does fail the objective, then this while loop will run.
while gameOver == True:
# Sets the background colour to black.
gameDisplay.fill(black)
# It sends a message to the screen using the functon we defined -- asks the user for input.
message_to_screen("You lose! Press R to try again and Q to quit.", red)
# Updates the display.
pygame.display.update()
# A loop that checks for events.
for event.type in pygame.event.get():
# If the the user presses a key down, then this will run.
if event.type == pygame.KEYDOWN:
# If that key that is being pressed down is Q, then this if statement will run.
if event.key == pygame.K_q:
# Sets the appropirate variables to be able to exit the gameOver while loop, and then sets gameExit to true to exit the while loop below.
gameExit = True
gameOver = False
if event.key == pygame.K_r:
gameLoop()
# This while loop runs when gameExit is equal to false.
while gameExit == False:
# A for loop -- all the events that are happening on the screen are being sent to pygame.event.get(), so we're going through those events and then doing different things according to those events.
for event in pygame.event.get():
# If the event in pygame.event.get() is QUIT, then this if statement runs.
if event.type == pygame.QUIT:
# Afterwards, it sets gameExit to true, therefore exiting the loop and running the exit functions outside the loop.
gameExit = True
# If the event type is pressing a key down, then this statement will run.
if event.type == pygame.KEYDOWN:
# If the key that is pressed down is the left key, then lead_x will change, depending on the size of the rectangle.
if event.key == pygame.K_LEFT:
# The lead_x variable changing by -25, this will be the coordinate that the rectangle will follow.
lead_x_change = -block_size
# Sets lead_y_change back to zero, so the rectangle doesn't move diagonally.
lead_y_change = 0
# If the key that is pressed down is the left key, then lead_x will change, depending on the size of the rectangle.
elif event.key == pygame.K_RIGHT:
# The lead_x_change variable changing by +25, this will be the coordinate that the rectangle will follow.
lead_x_change = block_size
# Sets lead_y_change back to zero, so the rectangle doesn't move diagonally.
lead_y_change = 0
# If the event is pressing the up key, then this will run.
elif event.key == pygame.K_UP:
# And therefore change the lead_y_change variable by -25.
lead_y_change = -block_size
# Sets lead_x_change back to zero, so the rectangle doesn't move diagonally.
lead_x_change = 0
# If the event is pressing the down key, then this will run.
elif event.key == pygame.K_DOWN:
# And therefore change the lead_y_change variable by -25.
lead_y_change = block_size
# Sets lead_x_change back to zero, so the rectangle doesn't move diagonally.
lead_x_change = 0
# Because it's in a loop, lead_x_change will constantly keep summing lead_x, and that controlls the coordinates of the snake. Same with lead_y_change.
lead_x += lead_x_change
lead_y += lead_y_change
# If the rectangle, which coordinates are outside the bounderies of the window, which is 800x600, then gameExit will equal to true and therefore escape from the loop.
if lead_x >= display_width or lead_x < 0 or lead_y >= display_height or lead_y < 0:
gameOver = True
# Sets the background colour.
gameDisplay.fill(black)
# Draws a rectangle - the arguments go as follows: where, colour, co-ordinates+width_height.
pygame.draw.rect(gameDisplay,green,[lead_x,lead_y,block_size,block_size])
# A way to create a rectangle - colour and then co-ordinates+width_height.
# gameDisplay.fill(blue, rect=[200,150,25,25])
# Updates the display.
pygame.display.update()
# Uses the clock object and sets the fps to the variable FPS.
clock.tick(FPS)
# Calling the function so the game runs.
gameLoop()
# De-initliaises the pygame methods.
pygame.quit()
# Quits out of the window.
quit()
Any help is appreciated.
The problem are your loops. Here's the essential structure of your game:
def gameLoop():
while gameOver == True:
// Show game over screen
while gameExit == False:
// Runs the game
// Can set gameOver variable to true
Now the gameExit loop works as expected and sets gameOver to true when you leave the screen. But you remain inside the gameExit loop. The code never reaches the top of the gameLoop function and thus your game over screen never shows.
One solution could be to move the while gameOver == True inside your gameExit loop, which would result in the following structure:
def gameLoop():
while gameExit == False:
while gameOver == True:
// Show game over screen
// Runs the game
// Can set gameOver to true
But a more elegant solution might be to put the entire game over loop into its seperate function and then call that. Then you could also get rid of the gameOver variable. Here's what I mean:
def gameOverLoop():
while True:
// Show game over screen until player makes selection. Then break the loop.
def gameLoop():
while gameExit == False:
// Run game
// ...
// If game ends, call game over screen
gameOverLoop()
Hope this helps.

Python /Pygame blitting multiple image to list coordinates

So i'm making a space game where you have a open world to explore (A black Screen)
and i wanna create planets(Blit images to screen) around the universe(from a list).
This is my code currently
star = pygame.image.load("star.png")
planets = random.randrange(100,500) #<------#####NOT IMPORTANT#######
positions = [(300,50),(400,27),(900,55)] #<------
position = ()
positions has coorinates where images should be blitted
but when i blit them
for position in positions:
ikkuna.blit(star, position)
it blits the first one or nothing and does not crash
why?
################################################-
Here is the full code if it helps (there is bits of the finish language in there hope it does not bother)
"ikkuna = screen (leveys,korkeus) = (width,hight) toiminnassa = in action"
import pygame
import random
import time
import sys
import math
pygame.init()
White = (255,255,255)
red = (255,0,0)
kello = pygame.time.Clock()
star = pygame.image.load("star.png")
planets = random.randrange(100,500)
positions = [(300,50)]
position = ()
tausta_vari = (255,255,255)
(leveys, korkeus) = (1000, 1000)
ikkuna = pygame.display.set_mode((leveys, korkeus))
pygame.display.set_caption("SpaceGenerationTest")
######################################################################
toiminnassa = True
while toiminnassa:
for event in pygame.event.get():
if event.type == pygame.QUIT:
toiminnassa = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_g:
print("Generating World....")
print(planets)
for position in positions:
ikkuna.blit(star, position)
print("hello")
There's some problems with your code:
Your not updating the display, which means that all your changes won't be visible. Use pygame.display.update() or pygame.display.flip() at the end of the game loop to update the screen.
When you're mixing English and Finnish it becomes very inconsistent and hard to follow, especially for people who don't speak Finnish. Try to use English, even when you're just practicing.
Your full example only contain one position in the list, thus it's only creating one star at one position.
Pressing the 'g'-key won't generate any planets. You might want to introduce a boolean variable like in the example below.
I changed your code to english and made some adjustment so it's more consistent.
import pygame
import random
pygame.init()
WHITE = (255, 255, 255)
RED = (255, 0, 0)
# I changed the background color to black, because I understood it as that is what you want.
BACKGROUND_COLOR = (0, 0, 0) # tausta_vari
clock = pygame.time.Clock() # kello
star = pygame.Surface((32, 32))
star.fill((255, 255, 255))
planets = random.randrange(100, 500)
positions = [(300, 50), (400, 27), (900, 55)]
WIDTH, HEIGHT = (1000, 1000) # (leveys, korkeus)
screen = pygame.display.set_mode((WIDTH, HEIGHT)) # ikkuna
pygame.display.set_caption("SpaceGenerationTest")
display_stars = False
running = True # toiminnassa
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_g:
print("Generating World....")
print(planets)
display_stars = True
screen.fill(BACKGROUND_COLOR)
if display_stars:
for position in positions:
# This will create 3 stars because there're 3 elements in the list positions.
# To create more stars you'll need to add more in the list positions.
screen.blit(star, position)
pygame.display.update()
Your blitting all your images to the exact same position: positions = [(300, 50)], so the last image covers all the other images up. Also, you may not know this, but to display anything in pygame you have to either call pygame.display.flip() or pygame.display.update() after you finish drawing. I made a few revisions to your code, so the stars should show-up:
import pygame
import random
import time
import sys
import math
def main():
pygame.init()
White = (255,255,255)
red = (255,0,0)
kello = pygame.time.Clock()
star = pygame.image.load("star.png")
planets = random.randrange(100,500)
positions = [(300,50), (310, 60), (320, 80), (607, 451), (345, 231)]
tausta_vari = (255,255,255)
(leveys, korkeus) = (1000, 1000)
ikkuna = pygame.display.set_mode((leveys, korkeus))
pygame.display.set_caption("SpaceGenerationTest")
######################################################################
toiminnassa = True
while toiminnassa:
for event in pygame.event.get():
if event.type == pygame.QUIT:
toiminnassa = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_g:
print("Generating World....")
print(planets)
ikkuna.fill((0, 0, 0)) # fill the screen with black
for position in positions:
ikkuna.blit(star, position)
print("Hello")
pygame.display.flip() # updating the screen
if __name__ == '__main__': # are we running this .py file as the main program?
try:
main()
finally:
pg.quit()
quit()
~Mr.Python

Resources