Preview keyboard input and blit text on mouse click pygame - python

I'm trying to display what the user types onto the screen as a preview and when they left click with the mouse, it blits the text onto the screen.
from pygame import *
init()
screen = display.set_mode((640, 480))
clock = time.Clock()
running = True
font = font.SysFont("comicsansms", 72) # Default font
textC = "a" # Stores user input
text = font.render(textC, True, (255,0,0)) # Render Text
while running:
mx, my = mouse.get_pos()
mb = mouse.get_pressed()
for e in event.get():
if e.type == QUIT:
running = False
if e.type == KEYDOWN:
print(textC)
if key.get_pressed()[K_BACKSPACE]:
textC = textC[:-1] # removes last letter
else:
textC += e.unicode # adds letter
screen.fill((255, 255, 255)) #fill screen white
screen.blit(text, (mx, my)) # display text
display.flip()
clock.tick(60)
quit()

First, you are not catching the mouse event correctly. You can use MOUSEBUTTONDOWN event in the same way as using KEYDOWN for key event and then use mouse.get_pressed to know which mouse button is being pressed.
Second, the problem is that each time screen.fill executes, all the surface is erased so it is necessary to somehow track the text and the position of rendered text. It can be a list.
So you're code can look something like this
from pygame import *
init()
screen = display.set_mode((640, 480))
clock = time.Clock()
running = True
font = font.SysFont("comicsansms", 72) # Default font
textC = "a" # Stores user input
text = font.render(textC, True, (255,0,0)) # Render Text
text_rendered = []
def rerender_text():
for surface, pos in text_rendered:
screen.blit(surface, pos) # display text
while running:
screen.fill((255, 255, 255)) # fill screen white
mx, my = mouse.get_pos()
for e in event.get():
if e.type == QUIT:
running = False
if e.type == KEYDOWN:
keys = list(key.get_pressed())
index = keys.index(1)
if key.get_pressed()[K_BACKSPACE]:
textC = textC[:-1] # removes last letter
else:
textC += e.unicode # adds letter
if e.type == MOUSEBUTTONDOWN:
if mouse.get_pressed()[0]: # Left click
screen.blit(text, (mx, my)) # display text
# save the text and the position for rerendering
text_rendered.append((text,(mx,my)))
text = font.render(textC, True, (255, 0, 0)) # Render Text
rerender_text()
screen.blit(text, (mx, my)) # display text
display.flip()
clock.tick(60)
quit()

I've modified your example, to put the stored text where you click. You need to update your text surface when you change your textC. I also clear the textC buffer on mouse-click.
from pygame import *
init()
screen = display.set_mode((640, 480))
clock = time.Clock()
running = True
font = font.SysFont("comicsansms", 72) # Default font
textC = "a" # Stores user input
text = font.render(textC, True, (255,0,0)) # Render Text
pos = None # store mouse click location
while running:
mx, my = mouse.get_pos()
mb = mouse.get_pressed()
for e in event.get():
if e.type == QUIT:
running = False
if e.type == KEYDOWN:
print(textC)
if key.get_pressed()[K_BACKSPACE]:
textC = textC[:-1] # removes last letter
else:
textC += e.unicode # adds letter
# need to update the text surface:
text = font.render(textC, True, (255,0,0)) # Render Text
elif e.type == MOUSEBUTTONDOWN:
pos = mouse.get_pos()
locked_text = font.render(textC, True, (0,255,0))
textC = ""
text = font.render(textC, True, (255,0,0)) # Clear text
screen.fill((255, 255, 255)) #fill screen white
if pos:
screen.blit(locked_text, pos)
screen.blit(text, (mx, my)) # display text
display.flip()
clock.tick(60)
quit()
If you want the text to persist, then you'll need to create a list of text surfaces and their positions and then iterate through them every frame. Might be worth considering Sprites in this case.

Related

Python 3.9.6 background scrolling problem

I am creating a typing racer game where it generates a random set of words and the user needs to match these words. The concept of the game is that a litte character is chased by a monster and will eventually die if the user messes up the words. So to make it as simple as possible for me (beginner) i decided to use just a scrolling background to make it look like the chase is in action. Please help. im so lost
import pygame
pygame.init()
#Setting up the screen display for the python game
screen = pygame.display.set_mode((1000, 800))
#RGB - Red, Green, Blue
screen.fill((92, 150, 150))
# Customizing and personalizing my screen
pygame.display.set_caption("Typing Racer!")
icon = pygame.image.load("exercise (1).png")
pygame.display.set_icon(icon)
#implementing an infinite background to the game in order to create the movement effect
backgroundImg = pygame.image.load("panoramic-view-field-covered-grass-trees-sunlight-cloudy-sky.jpg")
backgroundX = 0
backgroundY = -225
# Creating the player and its placement in the game
playerImg = pygame.image.load("running-man.png")
playerX = 400
playerY = 100
#Creating the monster chasing the player
objectImg = pygame.image.load("godzilla.png")
objectX = 200
objectY = 100
#implementing the data on the screen using .blit
def background():
screen.blit(backgroundImg, (backgroundX, backgroundY))
#Implementing objects into the game
def player():
screen.blit(playerImg, (playerX, playerY))
def object():
screen.blit(objectImg, (objectX, objectY))
#Setting up the typing area for the user of the program
text_font = pygame.font.Font(None, 32)
user_text = ""
#Input text box
input_rect = pygame.Rect(395, 490, 250, 40)
while True:
for event in pygame.event.get():
bg_scroll_x = backgroundX % backgroundImg.get_rect().width
screen.blit(backgroundImg, (bg_scroll_x, 0))
if bg_scroll_x < 1000:
screen.blit(backgroundImg, (bg_scroll_x - backgroundImg.get_rect().width, 0))
#KEYDOWN checks if a button was pressed on the keyboard while unicode checks which button was pressed
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_BACKSPACE:
user_text = user_text[:-1]
else:
user_text += event.unicode
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
#Typing Area for User
text_surface = text_font.render(user_text, True, (255 ,255 ,255))
screen.blit(text_surface, (input_rect.x + 5, input_rect.y + 10))
pygame.draw.rect(screen, (128, 128, 0), input_rect, 3)
#input_rect.w = max(text_surface.get_width()+10)
#Starting the background movement
backgroundX -= 0.8
#Calling the functions
background()
object()
player()
pygame.display.update()
You must draw the background in the application loop.
while True:
for event in pygame.event.get():
bg_scroll_x = backgroundX % backgroundImg.get_rect().width
#KEYDOWN checks if a button was pressed on the keyboard while unicode checks which button was pressed
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_BACKSPACE:
user_text = user_text[:-1]
else:
user_text += event.unicode
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
screen.blit(backgroundImg, (bg_scroll_x, 0))
if bg_scroll_x < 1000:
screen.blit(backgroundImg, (bg_scroll_x - backgroundImg.get_rect().width, 0))
# [...]
The event loop is only executed when an event occurs. However, the application loop is executed in every frame.
The typical PyGame application loop has to:
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()
limit the frames per second to limit CPU usage with pygame.time.Clock.tick

Why is my text not showing in Pygame window?

this is my first time trying to code in general so I brought upon myself to learn how to make a pygame.
I decided to go for a simple cookie clicker
I couldn't get the text to render with the cookie counted value can someone please help me?
The zip with image and font file
# 1 - Import packages
import pygame
# 2 - Define constants
width=700
height=700
FRAMES_PER_SECOND = 30
x = 20; # x coordnate of image
y = 30; # y coordinate of image
WHITE = (255, 255, 255)
BLACK = (0,0,0)
score = 0
X = 400 #x coord for text
Y = 400 # coord for text
# 3 - Initialize the world
pygame.init()
screen = pygame.display.set_mode( (width, height ) )
screen.fill(WHITE)
clock = pygame.time.Clock()
pygame.display.set_caption('Cookie Clicker simplified')
cookie = pygame.image.load("CookieBig.png")
# 4 - Load assets: image(s), sounds, etc.
cookie = pygame.image.load("CookieBig.png")
screen.blit(cookie , ( x,y)) # paint to screen
pygame.display.flip() # paint screen one time
# 5 - Initialize variables
# Text Display
font = pygame.font.Font('arial.ttf', 32)
text = font.render('COOKIES : ', True, BLACK, WHITE)
textRect = text.get_rect()
textRect.center = (X // 2, Y // 2)
# 6 - Loop forever
running = True
while (running):
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.MOUSEBUTTONDOWN:
# Set the x, y postions of the mouse click
x, y = event.pos
if cookie.get_rect().collidepoint(x, y):
score += 1
print("Cookie:",score)
pygame.display.update()
text is a pygame.Surface object. You have to blit the text Surface on the Surface which is associated to the window, in the main application loop.
screen.blit(text, textRect)
Recreate the text surface, when the score changes
text = font.render('COOKIES : ' + str(score), True, BLACK, WHITE)
A pygame.Surface object has not position. Thus the position which is returned by .get_rect() is (0, 0). Set the position by a keyword argument, when you retrieve the pygame.Rect from the Surface:
cookie_pos = (x, y)
x, y = event.pos
if cookie.get_rect(topleft = cookie_pos).collidepoint(x, y):
# [...]
I recommend to clear the display, draw the text and update the display in the main application loop rather than the event loop:
cookie_pos = (x, y)
# 6 - Loop forever
running = True
while running:
# handle the events
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.MOUSEBUTTONDOWN:
# Set the x, y postions of the mouse click
x, y = event.pos
if cookie.get_rect(topleft = cookie_pos).collidepoint(x, y):
score += 1
text = font.render('COOKIES : ' + str(score), True, BLACK, WHITE)
# <--|
# clear display
screen.fill(WHITE)
# draw scene
screen.blit(cookie, cookie_pos)
screen.blit(text, textRect)
# update display
pygame.display.update()
Note, the main 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()
The problem is your not putting it on the screen. Like the cookie image, you need to do screen.blit(text,textRect). I would also recommend putting them in the loop so it gets put on the screen every frame. This means if you change x or y, it will move. So something like this
running = True
while (running):
screen.fill(WHITE) #reset the screen
screen.blit(cookie , ( x,y)) # paint to screen
text = font.render('COOKIES : ', True, BLACK)
screen.blit(text,textRect)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.MOUSEBUTTONDOWN:
# Set the x, y postions of the mouse click
x, y = event.pos
if cookie.get_rect().collidepoint(x, y):
score += 1
print("Cookie:",score)
pygame.display.update()

Why won't my button change color when i hover over it pygame?

I'm new to pygame and have been attempting to create a simple interface with some buttons. I can't get the button to change color when the mouse hovers over it.
I've managed to create the button, but cannot get it to interact with my mouse.
The code create an button object with one instance of a green button.
It should change the button from green to red when mouse hovers over.
import pygame
pygame.init()
display_width = 1200
display_height = 600
black = (0, 0, 0)
white = (255, 255, 255)
red = (255, 0, 0)
green = (0, 255, 0)
StartScreen = pygame.display.set_mode((display_width, display_height))
pygame.display.set_caption('Log In')
clock = pygame.time.Clock()
StartScreen.fill(white)
class Buttons():
def __init__(self, color, x, y, width, height, text=''):
self.color = color
self.x = int(x)
self.y = int(y)
self.w = int(width)
self.h = int(height)
self.text = text
def Draw(self, StartScreen, outline=None):
if outline:
pygame.draw.rect(StartScreen, outline, (float(self.x-2), float(self.y-2), float(self.w+4), float(self.h+4)), 0)
pygame.draw.rect(StartScreen, self.color, (self.x, self.y, self.w, self.h), 0)
if self.text != '':
font = pygame.font.SysFont('comicsans', 20)
text = font.render(self.text, 1, black)
StartScreen.blit(text, (self.x + (self.w/2 - text.get_width()/2), self.y + (self.h/2 - text.get_height()/2)))
def MouseOver(self, pos):
if pos[0] > self.x and pos[0] < self.x + self.w:
if pos[1] > self.y and pos[1] < self.y + self.h:
return True
return False
def redrawWindow():
StartScreen.fill(white)
GrnBut.Draw(StartScreen, black)
run = True
GrnBut = Buttons(green, 150, 200, 90, 100, 'Press')
while run:
redrawWindow()
pygame.display.update()
for event in pygame.event.get():
pos = pygame.mouse.get_pos()
Exit = False
while not Exit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
print(event)
pygame.quit()
quit()
if event.type == pygame.MOUSEBUTTONDOWN:
if GrnBut.MouseOver(pos):
print("Clicked")
if event.type == pygame.MOUSEMOTION:
if GrnBut.MouseOver(pos):
GrnBut.color = red
else:
GrnBut.color = green
Your main problem is that you have a nested event loop inside your event loop:
while run: # outer loop
redrawWindow()
pygame.display.update()
for event in pygame.event.get():
pos = pygame.mouse.get_pos()
Exit = False
while not Exit: # inner loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
print(event)
pygame.quit()
quit()
When execution reaches this inner loop, neither redrawWindow() or GrnBut.MouseOver(pos) is ever called again.
Just get rid of it:
while run:
redrawWindow()
pygame.display.update()
for event in pygame.event.get():
pos = pygame.mouse.get_pos()
if event.type == pygame.QUIT:
print(event)
pygame.quit()
quit()
Your code can be improved by using some of pygame's features, such as the Sprite and Rect classes.
Here's an example of how you could create a more "pygamy" version of your Button class that supports multiple, different buttons:
import pygame
pygame.init()
display_width = 1200
display_height = 600
# use python style variable names (lowercase)
screen = pygame.display.set_mode((display_width, display_height))
pygame.display.set_caption('Log In')
clock = pygame.time.Clock()
# load the font only once instead of every frame
font = pygame.font.SysFont('comicsans', 20)
# class name should be singular
class Button(pygame.sprite.Sprite):
# 1) no need to have 4 parameters for position and size, use pygame.Rect instead
# 2) let the Button itself handle which color it is
# 3) give a callback function to the button so it can handle the click itself
def __init__(self, color, color_hover, rect, callback, text='', outline=None):
super().__init__()
self.text = text
# a temporary Rect to store the size of the button
tmp_rect = pygame.Rect(0, 0, *rect.size)
# create two Surfaces here, one the normal state, and one for the hovering state
# we create the Surfaces here once, so we can simple blit them and dont have
# to render the text and outline again every frame
self.org = self._create_image(color, outline, text, tmp_rect)
self.hov = self._create_image(color_hover, outline, text, tmp_rect)
# in Sprites, the image attribute holds the Surface to be displayed...
self.image = self.org
# ...and the rect holds the Rect that defines it position
self.rect = rect
self.callback = callback
def _create_image(self, color, outline, text, rect):
# function to create the actual surface
# see how we can make use of Rect's virtual attributes like 'size'
img = pygame.Surface(rect.size)
if outline:
# here we can make good use of Rect's functions again
# first, fill the Surface in the outline color
# then fill a rectangular area in the actual color
# 'inflate' is used to 'shrink' the rect
img.fill(outline)
img.fill(color, rect.inflate(-4, -4))
else:
img.fill(color)
# render the text once here instead of every frame
if text != '':
text_surf = font.render(text, 1, pygame.Color('black'))
# again, see how easy it is to center stuff using Rect's attributes like 'center'
text_rect = text_surf.get_rect(center=rect.center)
img.blit(text_surf, text_rect)
return img
def update(self, events):
# here we handle all the logic of the Button
pos = pygame.mouse.get_pos()
hit = self.rect.collidepoint(pos)
# if the mouse in inside the Rect (again, see how the Rect class
# does all the calculation for use), use the 'hov' image instead of 'org'
self.image = self.hov if hit else self.org
for event in events:
# the Button checks for events itself.
# if this Button is clicked, it runs the callback function
if event.type == pygame.MOUSEBUTTONDOWN and hit:
self.callback(self)
run = True
# we store all Sprites in a Group, so we can easily
# call the 'update' and 'draw' functions of the Buttons
# in the main loop
sprites = pygame.sprite.Group()
sprites.add(Button(pygame.Color('green'),
pygame.Color('red'),
pygame.Rect(150, 200, 90, 100),
lambda b: print(f"Button '{b.text}' was clicked"),
'Press',
pygame.Color('black')))
sprites.add(Button(pygame.Color('dodgerblue'),
pygame.Color('lightgreen'),
pygame.Rect(300, 200, 90, 100),
lambda b: print(f"Click me again!"),
'Another'))
while run:
events = pygame.event.get()
for event in events:
if event.type == pygame.QUIT:
pygame.quit()
quit()
# update all sprites
# it now doesn't matter if we have one or 200 Buttons
sprites.update(events)
# clear the screen
screen.fill(pygame.Color('white'))
# draw all sprites/Buttons
sprites.draw(screen)
pygame.display.update()
# limit framerate to 60 FPS
clock.tick(60)
There are a lot of problems with your code, and would like to suggest a less verbose way to code this using pygame.Rect instead of pygame.Sprite, as it does not require as much understanding of game design and is an inheritance-free approach.
Firstly we create the button class:
import pygame
import sys
class Button:
def __init__(self, rect, default_colour=(0,255,0), hovered_colour=(255,0,0), text="", font=None): #using default arguments
self.rect = pygame.Rect(rect)
self.default_colour = default_colour
self.hovered_colour = hovered_colour
self.font = font if font else pygame.font.Font(None, 20) #initialise/import font
self.text = self.font.render(text, True, (0,0,0)) #render text
def draw(self, surf, mouse_coords):
if self.hover(mouse_coords):
pygame.draw.rect(surf, self.hovered_colour, self.rect, 0)
else:
pygame.draw.rect(surf, self.default_colour, self.rect, 0)
surf.blit(self.text, self.text.get_rect(center=self.rect.center)) #rect has a centre attribute
def hover(self, mouse):
mouse_rect = pygame.Rect(mouse, [1,1]) #using inbuilt collision function
return mouse_rect.colliderect(self.rect) #returns a boolean, no need to do this: if mouse_rect.colliderect(self.rect): return True, else: return False
then we write the main program loop (continues on from previous block of code)
pygame.init()
screen = pygame.display.set_mode([500,500])
def response1(): #callback function when button 1 is pressed
print("Button 1 pressed")
def response2(): #callback function when button 2 is pressed
print("Button 2 pressed")
def main(buttons):
while True: #setting a variable to True is unnecessary as you can just use "break" to exit the loop.
#this is only not the case in rare cases
screen.fill((255,255,255)) #unneccessary to put in another function
for event in pygame.event.get(): #only 1 event loop required
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN:
for button in buttons:
if button["button"].hover(pygame.mouse.get_pos()):
button["func"]() #calls function if clicked on
for button in buttons: #draws all buttons in array, can be optimised to not occur when user clicks
button["button"].draw(screen, pygame.mouse.get_pos())
pygame.display.flip() #update the surface at the end of the loop instead of the beginning
#only use pygame.display.update(rect=None) to update a specific portion of the display, otherwise stick to flip()
if __name__ == "__main__": #if file is not a module
button1 = Button([130, 200, 90, 100], text="Press")
button2 = Button([280, 200, 90, 100], text="Me", default_colour=(255,255,0))
buttons = [ #array of dicts to store buttons and callback functions, for multiple buttons
{
"button": button1,
"func": response1
},
{
"button": button2,
"func": response2
}
]
main(buttons)

Collide Images in Pygame

im trying to check if two images collide but im just getting back an error saying
"'pygame.Surface' object has no attribute 'colliderect'". The images are battery and playerPic and i did a define to see if they collide. It should return a black screen if they collide.
Note: i removed the drawScene from my code on here
#initialize pygame
from pygame import *
import os
import random
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d, %d" %(0, 0)
init()
#set screen size
size = width, height = 800, 600
screen = display.set_mode(size)
#set fonts
fontGame=font.SysFont("Times New Roman", 30)
fontBack=font.SysFont("Ariel", 30)
fontTitle=font.SysFont("Ariel", 100)
fontResearch=font.SysFont ("Times New Roman", 18)
#set button and page to 0
button = 0
page=0
#setting colours
BLACK = (0, 0, 0)
RED = (255,0,0)
GREEN = (0, 255, 0)
BLUE = (106,186,232)
#loading image
backgroundPic=image.load("Background.jpg")
backgroundGame=image.load("gameBackground.jpg")
backgroundGame=transform.scale(backgroundGame,(800,600))
battery=image.load("Battery.png")
battery=transform.scale(battery,(100,100))
backgroundx=0
playerPic=image.load("player.png")
playerPic=transform.scale(playerPic,(70,70))
batteryx=[]
#defining what is going to be shown on the screen
def drawScene(screen, button,page,locationx,locationy):
global batteryx
mx, my = mouse.get_pos() #will get where the mouse is
#if the user does nothing
if page==0:
draw.rect(screen, BLACK, (0,0, width, height))
screen.fill(BLACK)
rel_backgroundx= backgroundx % backgroundGame.get_rect().width
screen.blit(backgroundGame, (rel_backgroundx - backgroundGame.get_rect().width,0))
if rel_backgroundx < width:
screen.blit (backgroundGame, (rel_backgroundx,0))
screen.blit(playerPic,(locationx,locationy))
screen.blit(battery,(batteryx,420))
batteryx-=1
display.flip()
return page
def collision (battery, playerPic):
if battery.colliderect(playerPic):
return True
return False
running = True
myClock = time.Clock()
KEY_LEFT= False
KEY_RIGHT= False
KEY_UP= False
KEY_DOWN= False
locationx=0
jumping=False
accel=20
onGround= height-150
locationy=onGround
batteryx=random.randrange(50,width,10)
# Game Loop
while running:
button=0
print (KEY_LEFT, KEY_RIGHT)
for evnt in event.get(): # checks all events that happen
if evnt.type == QUIT:
running=False
if evnt.type == MOUSEBUTTONDOWN:
mx,my=evnt.pos
button = evnt.button
if evnt.type== KEYDOWN:
if evnt.key==K_LEFT:
KEY_LEFT= True
KEY_RIGHT= False
if evnt.key==K_RIGHT:
KEY_RIGHT= True
KEY_LEFT= False
if evnt.key==K_UP and jumping==False:
jumping=True
accel=20
if evnt.key== K_DOWN:
KEY_DOWN= True
KEY_UP= False
if evnt.type==KEYUP:
if evnt.key==K_LEFT:
KEY_LEFT= False
if evnt.key==K_RIGHT:
KEY_RIGHT= False
if evnt.key==K_DOWN:
KEY_DOWN=False
if KEY_LEFT== True:
locationx-=10
backgroundx+=10
if KEY_RIGHT== True:
locationx+=10
backgroundx-=10
if jumping==True:
locationy-=accel
accel-=1
if locationy>=onGround:
jumping=False
locationy=onGround
#player cannot move off screen
if locationx<0:
locationx=0
if locationx>400:
locationx=400
if collision(battery, playerPic)==True:
screen.fill(BLACK)
page=drawScene(screen,button,page,locationx,locationy)
myClock.tick(60) # waits long enough to have 60 fps
if page==6: #if last button is clicked program closes
running=False
quit()
Images/pygame.Surfaces can't be used for collision detection. You have to create pygame.Rect objects for the battery and the player and then use their colliderect method. You can use the get_rect method of the surfaces to get rects with their size and then update the positions of the rects every time you move the player or the battery.
# Create a rect with the size of the playerPic with
# the topleft coordinates (0, 0).
player_rect = playerPic.get_rect()
In the while loop:
# Adjust the position of the rect.
player_rect.x = locationx
player_rect.y = locationy
# You can also assign the location variables to the topleft attribute.
player_rect.topleft = (locationx, locationy)
# Then pass the battery_rect and player_rect to the collision function.
if collision(battery_rect, player_rect):
You can also shorten the collision function:
def collision(battery_rect, player_rect):
return battery_rect.colliderect(player_rect)
Or just call battery_rect.colliderect(player_rect) in the while loop.
Here's a minimal, complete example:
import pygame as pg
pg.init()
screen = pg.display.set_mode((640, 480))
clock = pg.time.Clock()
BG_COLOR = pg.Color('gray12')
player_image = pg.Surface((30, 50))
player_image.fill(pg.Color('dodgerblue1'))
battery_image = pg.Surface((30, 50))
battery_image.fill(pg.Color('sienna1'))
speed_x = 0
location_x = 100
# Define the rects.
# You can pass the topleft position to `get_rect` as well.
player_rect = player_image.get_rect(topleft=(location_x, 100))
battery_rect = battery_image.get_rect(topleft=(200, 100))
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
elif event.type == pg.KEYDOWN:
if event.key == pg.K_a:
speed_x = -4
elif event.key == pg.K_d:
speed_x = 4
# Update the location and the player_rect.
location_x += speed_x
player_rect.x = location_x
if player_rect.colliderect(battery_rect):
print('collision')
# Blit everything.
screen.fill(BG_COLOR)
screen.blit(player_image, player_rect)
screen.blit(battery_image, battery_rect)
pg.display.flip()
clock.tick(30)
pg.quit()

Comparing keypressed to a char

I want to make some sort of typing game in python using pygame. So, if the key pressed character is the same as the character in the word, it should return true... Is there any way to do this in python?
For example:
the word is "cat", if the user presses the key 'c', then it returns true... and so on for the rest of the characters.
here's my main.py file
from time import sleep
import pygame
import random
import winsound
from words import Words
BLACK = ( 0, 0, 0)
WHITE = (255, 255, 255)
BLUE = ( 0, 0, 255)
GREEN = ( 0, 255, 0)
RED = (255, 0, 0)
pygame.init()
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
done = False
clock = pygame.time.Clock()
screen = pygame.display.set_mode((SCREEN_WIDTH,SCREEN_HEIGHT))
w1 = Words(screen) #making a single word (for now) to see if typing works
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
screen.fill(WHITE)
w1.draw()
#attempting to write code here to compare word and user input
pygame.display.flip()
clock.tick(60)
pygame.init()
exit()
here's my words.py file
from random_words import RandomWords
import pygame
import random
from queue import *
rw = RandomWords()
class Words():
def __init__(self, screen):
self.screen = screen
self.x_point = 400
self.y_point = 400
self.word = rw.random_word() #generates a random word
self.queue = Queue() #was hoping to use the queue so that if the user types the char correctly in the right order, then the letter would change color or something (but that's further down the line)
for c in self.word: #iterate through randomized word..
self.queue.put(c) #add each char in randomized word to queue, for typing reasons
def getY(self):
return self.y_point
def draw(self):
#creates a new object
myfont = pygame.font.SysFont('Comic Sans MS' ,30)
#creates a new surface with text drawn on it
textsurface = myfont.render(self.word, False, (0,0,0))
self.screen.blit(textsurface,(self.x_point,self.y_point))
Event KEYDOWN has event.unicode, event.key, event.mod
You can compare
if event.type == pygame.KEYDOWN:
if event.unicode == "a":
or even
if event.type == pygame.KEYDOWN:
if event.unicode.lower() == "a":
to check "a" and "A"
To check char in word
if event.type == pygame.KEYDOWN:
if event.unicode.lower() in your_word.lower():
Example code use event.unicode to render text with pressed keys.
BTW: It is not some Entry widget so it doesn't delete char when you press backspace.
import pygame
# --- constants ---
BLACK = ( 0, 0, 0)
WHITE = (255, 255, 255)
BLUE = ( 0, 0, 255)
GREEN = ( 0, 255, 0)
RED = (255, 0, 0)
SCREEN_WIDTH = 300
SCREEN_HEIGHT = 200
FPS = 5 # `FPS = 25` is enough for human eye to see animation.
# If your program don't use animation
# then `FPS = 5` or even `FPS = 1` can be enough
# --- main ---
# - init -
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH,SCREEN_HEIGHT))
screen_rect = screen.get_rect()
# - objects -
font = pygame.font.SysFont(None, 30)
text = ""
text_image = font.render(text, True, GREEN)
text_rect = text_image.get_rect() # get current size
text_rect.center = screen_rect.center # center on screen
# - mainloop -
clock = pygame.time.Clock()
done = False
while not done:
# - events -
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.KEYDOWN:
text += event.unicode
text_image = font.render(text, True, GREEN)
text_rect = text_image.get_rect() # get current size
text_rect.center = screen_rect.center # center on screen
# - draws -
screen.fill(BLACK)
screen.blit(text_image, text_rect)
pygame.display.flip()
clock.tick(FPS)
# - end -
pygame.quit() # <-- quit(), not init()

Categories