Pygame not responding when I press the T key - python-3.x

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")

Related

Hi, I'm looking for a fix to having multiple buttons in Pygame

For context, I've just gotten into Pygame, and I'm trying to learn how to use buttons. Of course, there's making the classes or functions and likewise calling them to work. However, when I open a new screen, I'd like there to be a new button, which then only works there.
My issue comes in after the second scene, where I'm unsure how to call a second button, or a third etc. If I put a return in a function where my button is, and check whether that function has collided with a point, the whole screen becomes a button which isn't ideal. So I'm looking for a fix.
Here's the chunk causing issues, and I'd love any advice on optimising it. My guess is that HeroCreation()[1] is causing issues, but I'm not entirely sure how else to make multiple buttons work simultaenously.
def TextCreation(font, text, coords, screen):
label = font.render(text, True, BLACK)
labelRect = label.get_rect()
labelRect.topright = coords
window.blit(label, labelRect)
return(label, labelRect)
StartButton = TextCreation(largeFont, 'Start Game', (rect_centerx+140, rect_centery - 250), window)
QuitButton = TextCreation(largeFont, 'Quit Game', (rect_centerx+140, rect_centery + 150), window)
def HeroCreation():
window.fill(WHITE)
Greeting = TextCreation(largeFont, 'Welcome, Hero!', (rect_centerx+210, rect_centery-200), window)
Intro1 = TextCreation(paraFont, "I presume you're caught up, but just in case:", (rect_centerx+250, rect_centery + 50), window)
Intro2 = TextCreation(paraFont, "The Rat King's wrecking our kingdom, and you're the only one who can find the Orb of Power.", (rect_centerx+500, rect_centery + 100), window)
Intro3 = TextCreation(paraFont, "Deal with him once and for all! Do us proud, hero.",(rect_centerx+260, rect_centery + 150), window)
pygame.draw.rect(window, LIGHT_GREEN, (rect_centerx - 170, rect_centery-80, 400, 70), 0)
ProceedtoMapButton = TextCreation(paraFont, "Are you ready?", (rect_centerx+110, rect_centery-70), window)
return (ProceedtoMapButton)
pygame.display.flip()
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
mouse = pygame.mouse.get_pos()
if QuitButton[1].collidepoint(mouse):
pygame.quit()
sys.exit()
if StartButton[1].collidepoint(mouse):
HeroCreation()
if HeroCreation()[1].collidepoint(mouse):
drawGrid(width, height, window)
if event.type == QUIT:
pygame.quit()
sys.exit()
For each screen, create new buttons, then remove them when the screen exits. In your loop, check if the button is on the screen before the collision check.
Try this code:
HeroButton = None
while run:
for event in pygame.event.get():
if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
mouse = pygame.mouse.get_pos()
if QuitButton[1].collidepoint(mouse): # quit button on every screen ?
pygame.quit()
sys.exit()
if StartButton != None and StartButton[1].collidepoint(mouse):
StartButton = None # done with this button
HeroButton = HeroCreation()
elif HeroButton != None and HeroButton[1].collidepoint(mouse):
HeroButton = None # done with this button
drawGrid(width, height, window) # start game?
if event.type == QUIT:
pygame.quit()
sys.exit()

How can I return true if my cursor is pressed while in a box and not pressed and then dragged in?

I have a box in pygame and I want to print some text to the console if the mouse button is pressed while the cursor is inside the box. The problem is I don't want the text to print if the mouse button is pressed and then dragged into the box.
I have tried:
if mousePos[0] >= 500 and mousePos[0] <= 530 and mousePos[1] >= 0 and mousePos[1] <= 100 and pygame.mouse.get_pressed()[0]:
scrollButtonColour = (25,25,25)
print(mousePos)
else:
scrollButtonColour = (50,50,50)
Cheers.
Edit:
Here is the full code for testing (I made slight changes since posting question):
import pygame
pygame.init()
white = (255,255,255)
black = (0,0,0)
red = (255,0,0)
green = (0,255,0)
blue = (0,0,255)
display_width = 800
display_height = 600
gameDisplay = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption("Scroll Bar")
clock = pygame.time.Clock()
FPS = 60
gameExit = False
scrollButtonColour = (50,50,50)
while not gameExit:
mousePos = pygame.mouse.get_pos()
scrollButtonColour = (50,50,50)
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
if mousePos[0] >= 500 and mousePos[0] <= 530 and mousePos[1] >= 0 and mousePos[1] <= 100:
if pygame.mouse.get_pressed()[0]:
scrollButtonColour = (25,25,25)
print(mousePos)
gameDisplay.fill(green)
pygame.draw.rect(gameDisplay, red, (200,200,100,100))
pygame.draw.rect(gameDisplay, scrollButtonColour, (500, 0, 30, 100))
pygame.display.update()
clock.tick(FPS)
pygame.quit()
To ensure that the event is only printed if the player clicks inside the
box and not releasing the mouse after the player dragged the mouse into the object
you can use pygame.MOUSEBUTTONDOWN.
This way you can check if the mouse is actually pressed. If you do this after
you have checked that your mouse position is inside the object, drags into the
object will not be printed, only clicks inside of the object.
This is how the code would look like :
if mousePos[0] >= 500 and mousePos[0] <= 530 and mousePos[1] >= 0 and mousePos[1] <= 100:
if event.type == pygame.MOUSEBUTTONDOWN :
scrollButtonColour = (25,25,25)
print(mousePos)
To make this code work you will have to put this code into the loop where you check for events
I'd first check if the mouse button was pressed, then if the button rect collides with the mouse pos, change the color of the button and print the text. When the button is released you can reset the color. I've got an example that also shows you how to use a pygame.Rect and its collidepoint method. Since mouse events have a pos attribute, you can use this instead of calling pygame.mouse.get_pos().
import sys
import pygame
pygame.init()
gameDisplay = pygame.display.set_mode((800, 600))
clock = pygame.time.Clock()
# Rect(x_pos, y_pos, width, height)
scrollButton = pygame.Rect(500, 0, 30, 100)
scrollButtonColour = (50, 50, 50)
gameExit = False
while not gameExit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.MOUSEBUTTONDOWN:
if scrollButton.collidepoint(event.pos):
scrollButtonColour = (25, 25, 25)
print(event.pos)
if event.type == pygame.MOUSEBUTTONUP:
scrollButtonColour = (50, 50, 50)
gameDisplay.fill((0, 255, 0))
pygame.draw.rect(gameDisplay, scrollButtonColour, scrollButton)
pygame.display.update()
clock.tick(60)
pygame.quit()
sys.exit()
If you want to make more buttons or other GUI elements, it would be a good idea to define classes for them. Put the instances into a list or sprite group and in the event loop pass the events to the instances to handle them.

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

Program Crashes unsure why

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()

Resources