How to let pygame text input detect the key in Pygame? [duplicate] - python

This question already has answers here:
How can I create a text input box with Pygame?
(5 answers)
Closed 5 years ago.
I'm doing a project that using Python and Pygame. I want to ask some question about the key in Pygame.
Thank you Shubhitgarg. I use his/her suggestions(use pygame_textinput), it succeed. Now I want to change the text input position with pressed an enter, but it can't detect the enter. How can I fix it? My real code:
# installing package
import pygame
from pygame import *
import pygame_textinput
pygame.init()
# colour settings
red = (255, 0, 0)
green = (0, 255, 0)
grass_green = (112, 173, 71)
blue = (0, 0, 255)
yellow = (255, 255, 0)
white = (255, 255, 255)
black = (0, 0, 0)
# screen settings
window = pygame.display.set_mode((680, 600))
window.fill(grass_green)
pygame.display.flip()
# font settings
default_font = pygame.font.get_default_font()
big_font = pygame.font.Font(default_font, 96)
font_a = pygame.font.Font(default_font, 50)
font_b = pygame.font.Font(default_font, 30)
font_c = pygame.font.Font(default_font, 18)
# text input settings
textinput = pygame_textinput.TextInput("freeansbold.ttf", 96, True, black, white, 400, 35)
# timer
start = pygame.time.get_ticks()
# text
please_guess_a_number = font_a.render("Please guess a number. ", 1, white)
text_range = font_c.render("from to", 1, white)
wrong_bigger = font_b.render("Sorry, You haven’t guess it rightly. Please try again.(The answer must be bigger.)", 1, white)
wrong_smaller = font_b.render("Sorry, You haven’t guess it rightly. Please try again.(The answer must be smaller.)", 1, white)
correct = font_b.render("Congratulations! You guess it correctly!!", 1, white)
# game
ask_you_to_set_range_1 = True
ask_you_to_set_range_2 = False
while True:
if ask_you_to_set_range_1:
window.blit(please_guess_a_number, (60, 80))
pygame.draw.rect(window, yellow, [60, 200, 230, 300])
pygame.draw.rect(window, yellow, [390, 200, 230, 300])
window.blit(text_range, (10, 550))
pygame.display.flip()
while True:
events = pygame.event.get()
textinput.update(events)
window.blit(textinput.get_surface(), (110, 300))
pygame.display.flip()
if ask_you_to_set_range_2:
while True:
events = pygame.event.get()
textinput.update(events)
window.blit(textinput.get_surface(), (440, 300))
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if ask_you_to_set_range_1 and event.key == pygame.K_KP_ENTER:
ask_you_to_set_range_1 = False
ask_you_to_set_range_2 = True
if textinput.update(event):
num1 = textinput.get_text()
text1 = big_font.render(num1, 1, black)
window.blit(text1, (110, 300))
Can anyone teach me to solve it?

You see this https://github.com/ShubhitGarg/pygame-text-input .
You can import this and use the text_input class and blit it on the same or next page
Use this
textinput = pygame_textinput.TextInput()
while True:
screen.fill((225, 225, 225))
events = pygame.event.get()
for event in events:
if event.type == pygame.QUIT:
exit()
# Feed it with events every frame
textinput.update(events)
# Blit its surface onto the screen
screen.blit(textinput.get_surface(), (10, 10))
pygame.display.update()

Related

How to check for collision between the mouse and a rect object

im creating code for a covid simulator but am a little stuck on the menu.
So far my code for the menu is as followed:
import pygame
pygame.init()
font_title = pygame.font.SysFont("arial", 35)
font_para = pygame.font.SysFont("monospace", 15)
BLACK = (0, 0, 0)
WHITE = (255,255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
menu = pygame.display.set_mode((999, 800))
pygame.display.set_caption('WELCOME TO COVID-19 SIMULATOR')
clock = pygame.time.Clock()
def Label(screen, text, size, font, color, x, y):
label = font.render(text, size, color)
screen.blit(label, (x, y))
Flag = True
def Menu():
while Flag == True:
title = Label(menu, "COVID-19 SIMULATOR: Main Menu", 1, font_title, WHITE, 275, 150)
own_sim = pygame.Rect(350, 290, 290, 40)
saved_sim = pygame.Rect(350, 390, 290, 40)
referrences = pygame.Rect(350, 490, 290, 40)
x_mouse, y_mouse = pygame.mouse.get_pos()
if own_sim.collidepoint((x_mouse, y_mouse)):
if click:
own_sim()
if saved_sim.colllidepoint((x_mouse, y_mouse)):
if click:
saved_sim()
if referrences.collidepoint((x_mouse, y_mouse)):
if click:
referrences()
pygame.draw.rect(menu, RED, own_sim)
pygame.draw.rect(menu, RED, saved_sim)
pygame.draw.rect(menu, RED, referrences)
pygame.display.flip()
clock.tick(60)
Menu()
I need my red boxes to have have text on, which i cant manage to do, and when they are clicked i want them to call another subprogram. I would be very grateful for any help, thanks in advance.
There is a typo in your code. collidepoint is written with ll, not with lll:
if saved_sim.colllidepoint((x_mouse, y_mouse)):
if saved_sim.collidepoint((x_mouse, y_mouse)):

Pygame Text: Instead of colour, let the text show an image, or animation

Something that looks like this but I want the image and text editable.
Instead of having something like:
title = menuFont.render("COMPUTER INFORMATION!", 1, BLACK)
screen.blit(title, Rect(50, 100, 400, 400))
Is it possible for the colour in the text to be an image instead, or an animation?
EDIT:
For those curious... when I imported the imaged, I had to change the end of the code a bit
screen.blit(texture, (50, 50))
screen.fill(BG_COLOR)
screen.blit(text_surface, (50, 170))
pg.display.update()
clock.tick(30)
The screen.fill comes after the texture... just a heads up :)
To texture your text, you can first render the text in white, then blit the texture onto it and pass pygame.BLEND_RGB_MULT as the special_flags argument to use the multiply blend mode. The texture will appear only on the opaque parts of the text surface.
Also, make sure that your texture is bigger than the text surface, otherwise some parts of the text will remain unaffected.
import pygame as pg
pg.init()
screen = pg.display.set_mode((640, 480))
clock = pg.time.Clock()
BG_COLOR = pg.Color('gray32')
FONT = pg.font.Font(None, 50)
# I create a grid texture for demonstration purposes here.
# Just load your image with pygame.image.load instead.
texture = pg.Surface((200, 100))
texture.fill((200, 100, 0))
for x in range(0, 201, 5):
pg.draw.line(texture, (0, 0, 0), (x, 0), (x, 200))
for y in range(0, 101, 5):
pg.draw.line(texture, (0, 0, 0), (0, y), (200, y))
# Render the text and use pure white as the color.
text_surface = FONT.render('Hello world!', True, (255, 255, 255))
# Now blit the texture onto the text surface and pass BLEND_RGB_MULT as
# the special_flags argument, so that only the opaque parts are affected.
text_surface.blit(texture, (0, 0), special_flags=pg.BLEND_RGB_MULT)
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
screen.fill(BG_COLOR)
screen.blit(texture, (50, 50))
screen.blit(text_surface, (50, 170))
pg.display.flip()
clock.tick(30)
pg.quit()
Here's the animated version. You have to load the separate frames of the animation and do the same as above for each frame. Put the resulting surfaces into a list and then play them back in the main loop.
import pygame as pg
pg.init()
screen = pg.display.set_mode((640, 480))
clock = pg.time.Clock()
BG_COLOR = pg.Color('gray32')
FONT = pg.font.Font(None, 50)
# I create a grid texture for demonstration purposes here.
# Just load your image with pygame.image.load instead.
texture = pg.Surface((200, 100))
texture.fill((200, 100, 0))
for x in range(0, 201, 5):
pg.draw.line(texture, (0, 0, 0), (x, 0), (x, 200))
for y in range(0, 101, 5):
pg.draw.line(texture, (0, 0, 0), (0, y), (200, y))
# Render the text and use pure white as the color.
text_surface = FONT.render('Hello world!', True, (255, 255, 255))
frames = []
for i in range(5):
surf = text_surface.copy() # We need a fresh copy of the text.
# Now blit the texture onto the text surface and pass BLEND_RGB_MULT as
# the special_flags argument, so that only the opaque parts are affected.
# The y-position is shifted by -1 each iteration.
surf.blit(texture, (0, -1*i), special_flags=pg.BLEND_RGB_MULT)
frames.append(surf)
frame_counter = 0
frame_timer = 0
dt = 0
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
frame_timer += dt # Add the passed time.
if frame_timer >= 150: # If 150 milliseconds have passed...
frame_timer = 0 # Reset the timer.
frame_counter += 1 # Increment the counter.
frame_counter %= len(frames) # Keep it in the correct range.
screen.fill(BG_COLOR)
# Now use `frame_counter` as the list index and blit the surface.
screen.blit(frames[frame_counter], (50, 170))
pg.display.flip()
dt = clock.tick(60) # `dt` is the passed time in milliseconds.
pg.quit()

How to debug "pygame.Surface' object is not callable"?

Question
I'm pretty new at Python and Pygame so I figured I'd jump right it head first and work on making a little rpg style game. I keep getting the error message below. I keep checking the code and re-watching the tutorial I'm following and I can't seem to find the problem.
I'm sure it's pretty obvious but I don't see the problem. I'm pretty sure I formatted the code in this post right but I don't know.
Error Message
Traceback (most recent call last):
File "C:\Users\Clayton\PycharmProjects\newgame\main.py", line 42, in <module>
gameDisplay.blit(Tiles.grass(x, y))
TypeError: 'pygame.Surface' object is not callable
Main.py
import pygame
from gamescripts.textures import *
# initialize PyGame
pygame.init()
# display information
# int defines number a an integer (ex1)
display_width = int(800)
display_height = int(600)
tile_size = 32
# color definitions
black = (0, 0, 0)
white = (255, 255, 255)
red = (255, 0, 0)
green = (0, 255, 0)
blue = (0, 0, 255)
skyblue = (135, 206, 235)
yellow = (255, 255, 0)
# window
gameDisplay = pygame.display.set_mode((display_width, display_height),
pygame.HWSURFACE | pygame.DOUBLEBUF)
pygame.display.set_caption('test game')
clock = pygame.time.Clock()
crashed = False
while not crashed:
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
print(event)
# render graphics
gameDisplay.fill(skyblue)
for x in range(0, 620, tile_size):
for y in range(0, 480, tile_size):
gameDisplay.blit(Tiles.grass(x, y))
# draws everything to window
pygame.display.update()
# num entered is game fps
clock.tick(60)
# quit PyGame
pygame.quit()
# quit python
quit()
Textures.py
import pygame
pygame.init()
class Tiles:
Size = 32
def load_texture(file, Size):
bitmap1 = pygame.image.load(file)
bitmap2 = pygame.transform.scale(bitmap1, (Size, Size))
surface = pygame.Surface((Size, Size), pygame.HWSURFACE | pygame.SRCALPHA)
surface.blit(bitmap2, (0, 0))
return surface
grass = load_texture('graphics\\grass.png', Size)
You have to create an instance of your Tiles class.
Your Tiles class cannot be directly blitted without creating an instance first.
#create a instance of `Tiles`
tile=Tiles()
tile.load_texture('graphics\\grass.png',32)
Implemented into your code:
import pygame
from gamescripts.textures import *
# initialize PyGame
pygame.init()
# display information
# int defines number a an integer (ex1)
display_width = int(800)
display_height = int(600)
tile_size = 32
# color definitions
black = (0, 0, 0)
white = (255, 255, 255)
red = (255, 0, 0)
green = (0, 255, 0)
blue = (0, 0, 255)
skyblue = (135, 206, 235)
yellow = (255, 255, 0)
# window
gameDisplay = pygame.display.set_mode((display_width, display_height),
pygame.HWSURFACE | pygame.DOUBLEBUF)
pygame.display.set_caption('test game')
clock = pygame.time.Clock()
#create an instance of your `Tile` class
tile=Tile()
tile.load_texture('graphics\\grass.png',32)
crashed = False
while not crashed:
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
print(event)
# render graphics
gameDisplay.fill(skyblue)
for x in range(0, 620, tile_size):
for y in range(0, 480, tile_size):
#choose example coordinates for x and y
gameDisplay.blit(tile,(x,y))
# draws everything to window
pygame.display.update()
# num entered is game fps
clock.tick(60)
# quit PyGame
pygame.quit()
# quit python
quit()
import pygame
pygame.init()
You should change your Tile class as well.
class Tiles:
#initialize your class
def__init__(self):
pass
#ALWAYS use self as the first parameter
def load_texture(self,file, Size):
bitmap1 = pygame.image.load(file)
bitmap2 = pygame.transform.scale(bitmap1, (Size, Size))
surface = pygame.Surface((Size, Size), pygame.HWSURFACE | pygame.SRCALPHA)
surface.blit(bitmap2, (0, 0))
return surface
I suggest you really take a look at the the pygame documentation and the python documentation.
You should also look at SO if your question was already posted. For example, I found this example.

Screenfilling not working

So I fell against this weird problem where I can't fill the screen. My code is
#Import all modules
import pygame
import random
import math
import time
#Colors
BLACK = ( 0, 0, 0)
WHITE = ( 255, 255, 255)
GREEN = ( 0, 255, 0)
RED = ( 255, 0, 0)
ORANGe = (255, 115, 0)
YELLOW = (242, 255, 0)
BROWN = (115, 87, 39)
PURPLE = ( 298, 0, 246)
GRAY = ( 168, 168, 168)
BLUE = ( 0, 0, 255)
pygame.init()
# Clock
clock = pygame.time.Clock()
#Screen
screenx = 1000
screeny = 700
screen = pygame.display.set_mode([screenx,screeny])
#Title
pygame.display.set_caption("OUCH Version 0.1")
#Classes (if any)
#Variables
sound = True
password = False
titlescreen = True
#Booleans
#Sounds
#The graphics
#Positions
#Time management
fps = 60
#Other Things
#Main Loop__________________________________________________
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if titlescreen:
screen.fill(WHITE)
#Flip the Display
pygame.display.flip
clock.tick(fps)
#If done
pygame.quit()
I just updated to python 3.4, may that be the problem. Or am I overlooking something. I'm trying to fill the screen white but every time I run it the screen always turns out to be black. Thank you for any help. :)
What I have tried__________
I tried looking if theirs something with the color WHITE, but when I try any other color it does not work. I also tried just screen filling with ought the Boolean yet that doesn't work either. I have also tried not doing if titlescreen:, but if titlescreen == True: then bla bla
You forgot to put brakets:
pygame.display.flip()

Pygame- "Pygbuttons"- How to change button color and sound play simultaneously

I want to change the color of each button inside one by one, on every change in color I want to play one sound.
The sounds are playing perfectly, but the button color is changing only at the end when all of the sounds are played.
What should I do the make the color change and sound play for each button at the same time?
Here is my code:
import pygame, pygbutton, sys
from pygame.locals import *
import time
import threading
from threading import Thread
FPS = 30
WINDOWWIDTH = 1550
WINDOWHEIGHT = 1200
WHITE = (255, 255, 255)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
GREEN = (0, 255, 0)
BLACK = (0, 0, 0)
GREY = (211, 211, 211)
exitcode = 0
def main():
#1 constants
windowBgColor = WHITE
size=(100,30)
running = 1
#2 initialize
FPSCLOCK = pygame.time.Clock()
pygame.mixer.init(frequency=22050,size=-16,channels=13)
#3 load
zebrasound = pygame.mixer.Sound("resources/audio/zebra.wav")
zlet = pygame.mixer.Sound("resources/audio/Z.wav")
elet = pygame.mixer.Sound("resources/audio/E.wav")
blet = pygame.mixer.Sound("resources/audio/B.wav")
rlet = pygame.mixer.Sound("resources/audio/R.wav")
alet = pygame.mixer.Sound("resources/audio/A.wav")
wrong = pygame.mixer.Sound("resources/audio/fail.wav")
right = pygame.mixer.Sound("resources/audio/chime.wav")
beep = pygame.mixer.Sound("resources/audio/sensor.wav")
flip = pygame.mixer.Sound("resources/audio/flip.wav")
zebrasound.set_volume(3)
zlet.set_volume(3)
elet.set_volume(3)
blet.set_volume(3)
rlet.set_volume(3)
alet.set_volume(3)
wrong.set_volume(3)
right.set_volume(5)
#4 Display
screen = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
pygame.display.set_caption('Animal game')
#5 Buttons
buttonForward = pygbutton.PygButton((700, 900, 600,482), normal='resources/images/arrow.png')
buttonBackward = pygbutton.PygButton((600, 900, 600,482), normal='resources/images/arrowBackward.png')
buttonZebra = pygbutton.PygButton((100, 150, 640,480), normal='resources/images/zebraclip.png')
buttonZebra1 = pygbutton.PygButton((850, 200, 600, 120), 'Z E B R A')
buttonZebra2 = pygbutton.PygButton((850, 400, 600, 120), 'Z A B R A')
buttonZebra3 = pygbutton.PygButton((850, 600, 600, 120), 'Z B R E A')
buttonZebra11 = pygbutton.PygButton((855, 205, 110, 110), 'Z')
buttonZebra12 = pygbutton.PygButton((975, 205, 110, 110), 'E')
buttonZebra13 = pygbutton.PygButton((1095, 205, 110, 110), 'B')
buttonZebra14 = pygbutton.PygButton((1215, 205, 110, 110), 'R')
buttonZebra15 = pygbutton.PygButton((1335, 205, 110, 110), 'A')
buttonZebra1.font = pygame.font.Font(None,110)
buttonZebra11.font = pygame.font.Font(None,110)
buttonZebra12.font = pygame.font.Font(None,110)
buttonZebra13.font = pygame.font.Font(None,110)
buttonZebra14.font = pygame.font.Font(None,110)
buttonZebra15.font = pygame.font.Font(None,110)
buttonZebra2.font = pygame.font.Font(None,110)
buttonZebra3.font = pygame.font.Font(None,110)
button = [buttonZebra,buttonZebra1,buttonZebra2,buttonZebra3]
button_zebra = [buttonZebra11,buttonZebra12,buttonZebra13,buttonZebra14,buttonZebra15]
allButtons = button
windowBgColor = WHITE
#6 Event loop
#while True:
while running:
#pygame.display.flip()
for event in pygame.event.get(): # event handling loop
if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
pygame.quit()
sys.exit()
if 'click' in button[0].handleEvent(event):
zebrasound.play()
if 'click' in button[1].handleEvent(event):
sound_please(right)
change_color_bg(button[1], GREEN)
change_color_fg(button_zebra[0], GREEN)
change_color_bg(button_zebra[0], BLACK)
sound_please(zlet)
change_color_fg(button_zebra[1], GREEN)
change_color_bg(button_zebra[1], BLACK)
sound_please(elet)
change_color_fg(button_zebra[2], GREEN)
change_color_bg(button_zebra[2], BLACK)
sound_please(blet)
change_color_fg(button_zebra[3], GREEN)
change_color_bg(button_zebra[3], BLACK)
sound_please(rlet)
change_color_fg(button_zebra[4], GREEN)
change_color_bg(button_zebra[4], BLACK)
sound_please(alet)
if 'click' in button[2].handleEvent(event):
sound_please(wrong)
change_color_bg(button[2], RED)
if 'click' in button[3].handleEvent(event):
sound_please(wrong)
change_color_bg(button[3], RED)
pygame.display.update()
screen.fill(windowBgColor)
buttonForward.draw(screen)
for a in allButtons:
a.draw(screen)
for b in button_zebra:
b.draw(screen)
pygame.display.update()
FPSCLOCK.tick(FPS)
def change_color_fg(button,color):
button.fgcolor = color
pygame.display.update()
def change_color_bg(button,color):
button.bgcolor = color
pygame.display.update()
def sound_please(sound):
sound.play()
while pygame.mixer.get_busy():
time.sleep(1)
pygame.display.update()
if __name__ == "__main__":
main()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit(0)
Button[1] is the big button and button_zebra 1,2,3,4 are small buttons inside bigbutton.
I have 4 buttons in a bigbutton, When I click the bigbutton and color of it changes.
Since input handling (the section of code that you posted) is usually just one part of the game loop, and you haven't posted the contents of change_color_fg, I can only make an educated guess here.
My guess is that change_color_fg does not actually update the display, and only changes the color that a button is supposed to draw with. It's my guess partly because it wouldn't make sense to re-draw the display within a function that's executing multiple times within a single frame.
For starters, don't delay in the middle of your update loop. If you need to do something when a single sound ends, implement a callback, or check playing sounds for completion once every frame until they finish.
For example, with each sound you play, you could either check its length with pygame.mixer.Sound.get_length, and then schedule a function to execute after that amount of time which changes the color of your next button and plays your next sound. Or, you could get the pygame.mixer.Channel object back from pygame.mixer.Sound.play, and then check pygame.mixer.Channel.get_busy until it returns False, which would indicate that your sound has stopped playing, at which point you can play the next one.

Categories

Resources