How to make a button in pygame display and update images? - python

I am trying to make a button in pygame. It is supposed to display three new images everytime it is clicked. Everything works, except these 3 images only appear while the button is clicked on. The code to display the images is below, it is part of a larger while loop which continues infinitely for now. How can i make it so that the images stay until the button is pressed again and new images appear? Any help is appreciated, thanks in advance.
mouse = pygame.mouse.get_pos ()
click = pygame.mouse.get_pressed ()
element = -1
if 1120 > mouse [0] > 865 and 330 > mouse [1] > 250:
screen.blit (dice_button_light, (870, 250))
if click [0] == 1:
dice_choices = Dice.dice_choice()
print(dice_choices)
element = -1
for i in dice_choices:
element += 1
x = 750
if element == 1:
x += 100
if element == 2:
x += 200
if i == 1:
screen.blit (dice1,(x,100))
elif i == 2:
screen.blit (dice2,(x,100))
elif i == 3:
screen.blit (dice3,(x,100))
elif i == 4:
screen.blit (dice4,(x,100))
elif i == 5:
screen.blit (dice5,(x,100))
elif i == 6:
screen.blit (dice6,(x,100))
else:
screen.blit (dice_button, (870, 250))

To cycle through different images, you can put them into a list and whenever the button rect is clicked, increment an index variable that represents the current image. In your while loop just use the index to get the correct image out of the list.
import sys
import pygame as pg
# Three images.
IMG1 = pg.Surface((100, 100))
IMG1.fill((240, 240, 240))
pg.draw.circle(IMG1, (0, 0, 0), (50, 50), 10)
IMG2 = pg.Surface((100, 100))
IMG2.fill((240, 240, 240))
pg.draw.circle(IMG2, (0, 0, 0), (25, 25), 10)
pg.draw.circle(IMG2, (0, 0, 0), (75, 75), 10)
IMG3 = pg.Surface((100, 100))
IMG3.fill((240, 240, 240))
pg.draw.circle(IMG3, (0, 0, 0), (20, 20), 10)
pg.draw.circle(IMG3, (0, 0, 0), (50, 50), 10)
pg.draw.circle(IMG3, (0, 0, 0), (80, 80), 10)
# Put the images into a list or tuple.
IMAGES = [IMG1, IMG2, IMG3]
def main():
screen = pg.display.set_mode((640, 480))
clock = pg.time.Clock()
bg_color = pg.Color(30, 40, 60)
# Use this rect for the collision detection and blitting.
img_rect = IMG1.get_rect(topleft=(200, 200))
img_index = 0
done = False
while not done:
for event in pg.event.get():
if event.type == pg.QUIT:
done = True
if event.type == pg.MOUSEBUTTONDOWN:
if img_rect.collidepoint(event.pos):
img_index += 1
# Modulo to cycle between 0, 1, 2.
img_index %= len(IMAGES)
screen.fill(bg_color)
# Use the index to get the current image and blit
# it at the img_rect (topleft) position.
screen.blit(IMAGES[img_index], img_rect)
pg.display.flip()
clock.tick(30)
if __name__ == '__main__':
pg.init()
main()
pg.quit()
sys.exit()

Related

How do I get a picture to appear when I press a key?

I'm trying to make Tic-Tac-Toe in Python, but I've run into a problem. I can't figure out how to let the players make a selection on the board. I have been trying to get an "X" in the top left square of the board. The "X" and "O" are both images, not text. The background is also an image. Every time I run my code, The window opens, the board and title are both their, but when I press the "1" key, nothing happens. Does anyone know what to do about this? I'm not sure which parts of my code are wrong so here's all of it:
import pygame
import os
import sys
from pygame.locals import *
pygame.init()
WIDTH, HEIGHT = 500, 500
P_WIDTH, P_HEIGHT = 100, 130
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
main_font = pygame.font.SysFont("Comic sans", 40)
#color = (255, 255, 255)
#light_color = (170, 170, 170)
#dark_color = (100, 100, 100)
def redraw_window():
BG = pygame.transform.scale(pygame.image.load(os.path.join("Board.jpg")).convert_alpha(), (WIDTH, HEIGHT))
title_label1 = main_font.render("Tic", True, (0, 0, 0))
title_label2 = main_font.render("Tac", True, (0, 0, 0))
title_label3 = main_font.render("Toe", True, (0, 0, 0))
Player_1 = pygame.transform.scale(pygame.image.load(os.path.join("X.jpg")).convert_alpha(), (P_WIDTH, P_HEIGHT))
WIN.blit(BG, (0, 0))
WIN.blit(title_label1, (10, 10))
WIN.blit(title_label2, (10, 40))
WIN.blit(title_label3, (10, 70))
pygame.display.update()
def main():
while True:
redraw_window()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit(0)
elif event.type == pygame.locals.KEYDOWN:
if event.key == K_1:
WIN.blit(Player_1, (72, 35))
main()
Also, if anyone sees something that could be improved, could you point that as well?
So you're getting an error, it's best if you include this detail in your question.
pygame 2.0.1 (SDL 2.0.14, Python 3.6.9)
Hello from the pygame community. https://www.pygame.org/contribute.html
Traceback (most recent call last):
File "./bad_noughts.py", line 47, in <module>
main()
File "./bad_noughts.py", line 44, in main
WIN.blit(Player_1, (72, 35))
NameError: name 'Player_1' is not defined
Inside the main() function, Python doesn't know about Player_1 because it's "local" to the function redraw_window() - that means that only the redraw_window() function knows about Player_1.
So how do you fix this?
The quickest and simplest way is to move the definition of Player_1 to the main program, giving it a "global" scope.
This fixes the error, but the 'X' still doesn't appear... why? The next problem is that you're only drawing the 'X' when the 1 event is received. Then (almost immediately) the background is re-painted again, covering it up. It's only on-screen for a split-second.
One way to fix this is to separate the state of the board with the drawing of the board.
Let's introduce a new list-of-lists board_state, which has 3 rows of 3 cells, one for each area of your nought-and-crosses board:
board_state = [ [ None, None, None ],
[ None, None, None ],
[ None, None, None ] ]
Using this, we can set and check the layout of the moves on the board by saying something like: board[0][0] (top-left) and board[2][2] (bottom-right). One important thing you just realised, is that lists are "zero-indexed", meaning the very first element is at number-0 (not 1)
So now when the player makes a move, we can just set the board state:
elif event.type == pygame.locals.KEYDOWN:
if event.key == K_1:
board_state[0][0] = 'x' # top-left
Now we need to adjust the window drawing function to look at the board-state, and draw what's needed:
def redraw_window():
global board_state
WIN.blit(BG, (0, 0))
WIN.blit(title_label1, (10, 10))
WIN.blit(title_label2, (10, 40))
WIN.blit(title_label3, (10, 70))
x_cursor = 0 # position on the board
y_cursor = 0
for row in ( 0, 1, 2 ):
x_cursor = 0
for col in ( 0, 1, 2 ):
# if there's a move on the board, draw it
if ( board_state[row][col] == 'x' ):
WIN.blit( Player_1, ( x_cursor, y_cursor ) )
elif ( board_state[row][col] == 'o' ):
WIN.blit( Player_2, ( x_cursor, y_cursor ) )
x_cursor += WIDTH//3 # move the cursor across
y_cursor += HEIGHT//3 # move the cursor down
pygame.display.update()
So the loops iterate through the rows and columns of the board_state. Using the (0, 1, 2) in the loop isn't best-practice, but I'm trying to keep it simple. As the loops move through the board, across then down, we also maintain a cursor-position where any player-move should be drawn.
If the board contains an 'x' or 'o', the correct bitmap is drawn. Except this code is a bit rough, so the co-ordinates will probably be a bit off, but I don't have your bitmaps, so that's the best we can do.
Reference Code:
import pygame
import os
import sys
from pygame.locals import *
pygame.init()
WIDTH, HEIGHT = 500, 500
P_WIDTH, P_HEIGHT = 100, 130
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
main_font = pygame.font.SysFont("Comic sans", 40)
#color = (255, 255, 255)
#light_color = (170, 170, 170)
#dark_color = (100, 100, 100)
BG = pygame.transform.scale(pygame.image.load(os.path.join("ox_board.png")).convert_alpha(), (WIDTH, HEIGHT))
Player_1 = pygame.transform.scale(pygame.image.load(os.path.join("ox_x.png")).convert_alpha(), (P_WIDTH, P_HEIGHT))
Player_2 = pygame.transform.scale(pygame.image.load(os.path.join("ox_o.png")).convert_alpha(), (P_WIDTH, P_HEIGHT))
title_label1 = main_font.render("Tic", True, (0, 0, 0))
title_label2 = main_font.render("Tac", True, (0, 0, 0))
title_label3 = main_font.render("Toe", True, (0, 0, 0))
# moves (or not) placed on the board
# None -> no move yet
# Or 'x', 'o'
board_state = [ [ None, None, None ],
[ None, None, None ],
[ None, None, None ] ]
def redraw_window():
global board_state
WIN.blit(BG, (0, 0))
WIN.blit(title_label1, (10, 10))
WIN.blit(title_label2, (10, 40))
WIN.blit(title_label3, (10, 70))
x_cursor = 0 # position on the board
y_cursor = 0
for row in ( 0, 1, 2 ):
x_cursor = 0
for col in ( 0, 1, 2 ):
# if there's a move on the board, draw it
if ( board_state[row][col] == 'x' ):
WIN.blit( Player_1, ( x_cursor, y_cursor ) )
elif ( board_state[row][col] == 'o' ):
WIN.blit( Player_2, ( x_cursor, y_cursor ) )
x_cursor += WIDTH//3 # move the cursor across
y_cursor += HEIGHT//3 # move the cursor down
pygame.display.update()
def main():
while True:
redraw_window()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit(0)
elif event.type == pygame.locals.KEYDOWN:
if event.key == K_1:
board_state[0][0] = 'x'
main()
The board_state also allows you to check whether a move has been made in the cell already. Assume the player pushes 5 (centre cell), you can just check board_state[1][1] != None to test if a move was already placed in that cell.

Blitting certain images to the screen is painfully slow in pygame [duplicate]

This question already has answers here:
Why my pygame game with a tiled map is lagging?
(1 answer)
How could I optimise this simple python pygame code
(1 answer)
Closed 2 years ago.
I am trying to make a game, but when I try to blit a few flowers onto the screen it slows down from 60 FPS to 12 FPS.
At first, I tried to .convert() all my images, but then they turned pink. So I used .convert_alpha() instead. using .convert_alpha() made the images not pink, but it only made the FPS go up a teeny bit.
the relevant parts of my code are
### Creates a random assortment of Flora ###
def createFlora(screenSize, cellSize):
flower1 = pygame.transform.scale(pygame.image.load("Flower1.PNG"), (64, 64))
flower1 = flower1.convert_alpha()
flower2 = pygame.transform.scale(pygame.image.load("Flower2.PNG"), (64, 64))
flower2 = flower2.convert_alpha()
flowers = [flower1, flower2]
flower1ds = pygame.transform.scale(pygame.image.load("Flower1DropShadow.PNG"), (64, 64))
flower1ds = flower1ds.convert_alpha()
flower2ds = pygame.transform.scale(pygame.image.load("Flower2DropShadow.PNG"), (64, 64))
flower2ds = flower2ds.convert_alpha()
flowersds = [flower1ds, flower2ds]
flora = []
for i in range(screenSize[0] // cellSize + 1):
floraRow = []
for j in range(screenSize[1] // cellSize + 1):
if randint(0, len(flowers) * 4) < len(flowers):
choice = randint(0, len(flowers) - 1)
floraRow.append((flowers[choice],
(i * cellSize, j * cellSize),
randint(0, 3) * 90, choice))
else: floraRow.append(False)
flora.append(floraRow)
floraFinal = []
for i in range(len(flora)):
for j in range(len(flora[0])):
if flora[i][j] != False:
if flora[i][j][3] == 0:
if flora[i][j][2] == 0: #depending on the rotation of parent plant, the shadow will be changed.
floraFinal.append((pygame.transform.rotate(flowersds[flora[i][j][3]], flora[i][j][2]), flora[i][j][1]))
elif flora[i][j][2] == 90:
floraFinal.append((pygame.transform.rotate(flowersds[flora[i][j][3]], flora[i][j][2]), (flora[i][j][1][0], flora[i][j][1][1] + 8)))
elif flora[i][j][2] == 180:
floraFinal.append((pygame.transform.rotate(flowersds[flora[i][j][3]], flora[i][j][2]), (flora[i][j][1][0] + 8, flora[i][j][1][1] + 8)))
elif flora[i][j][2] == 270:
floraFinal.append((pygame.transform.rotate(flowersds[flora[i][j][3]], flora[i][j][2]), (flora[i][j][1][0] + 8, flora[i][j][1][1])))
elif flora[i][j][3] == 1:
if flora[i][j][2] == 0:
floraFinal.append((flowersds[flora[i][j][3]], flora[i][j][1]))
elif flora[i][j][2] == 90:
floraFinal.append((flowersds[flora[i][j][3]], (flora[i][j][1][0], flora[i][j][1][1] + 4)))
elif flora[i][j][2] == 180:
floraFinal.append((flowersds[flora[i][j][3]], (flora[i][j][1][0] + 4, flora[i][j][1][1] + 4)))
elif flora[i][j][2] == 270:
floraFinal.append((flowersds[flora[i][j][3]], (flora[i][j][1][0] + 4, flora[i][j][1][1])))
floraFinal.append((pygame.transform.rotate(flora[i][j][0], flora[i][j][2]), flora[i][j][1]))
return floraFinal
def renderFlora(flora, screen):
for i in range(len(flora)):
screen.blit(flora[i][0], flora[i][1])
def main():
os.environ['SDL_VIDEO_CENTERED'] = '1' #center the screen
pygame.init()
screenSize = (1856, 960) #24 x 14 cells
onTop(pygame.display.get_wm_info()['window']) #move pygame window to the front
screen = pygame.display.set_mode(screenSize)
screen.fill((25, 25, 25))
""" VARS """
cellSize = 64
pygame.font.init()
myfont = pygame.font.SysFont('Comic Sans MS', 30)
path = createPath()
flora = createFlora(screenSize, cellSize)
tileMap = createTileMap(screenSize, cellSize)
tileGridOn = False
currentButton = 0
buttons = []
gridButtonImg = pygame.transform.scale(pygame.image.load("GridButton.PNG").convert_alpha(), (48, 48))
#Grid Button Toggles a grid so you can see where Tiles are easier
buttons.append(Button((20, screenSize[1] - 64), False, gridButtonImg, screen, 48))
pathSds = pygame.transform.scale(pygame.image.load("StraightPathDropShadow.PNG").convert_alpha(), (64, 64))
pathCds = pygame.transform.scale(pygame.image.load("CornerPathDropShadow.PNG").convert_alpha(), (64, 64))
#==# MAIN LOOP #==#
clock = pygame.time.Clock()
while True:
screen.fill((25, 25, 25))
for evt in pygame.event.get():
if evt.type == pygame.QUIT:
pygame.quit()
quit()
#Draw Background Tiles
renderBackground(tileMap, screen)
#Draw Midground Items/Tiles
renderFlora(flora, screen)
#Draw Foreground Items/Tiles
renderPath(path, screen, pathSds, pathCds)
textsurface = myfont.render(str(round(clock.get_fps() * 10) / 10), False, (0, 0, 0))
screen.blit(textsurface,(15, 15))
### Buttons ###
for i in range(len(buttons)):
buttons[i].update(screen)
if buttons[i].getCTF():
currentButton = i
#Toggle Grid
tileGridOn = buttons[0].getValue()
if tileGridOn: drawGrid(screenSize, cellSize, screen)
pygame.display.flip()
clock.tick(60)
main()
The flora is created before the main loop, so I'm not creating images every cycle, I'm just passing a list through the render function, which only blits the images onto the screen.
If I comment out the renderFlora() method it goes to 60 FPS, but if I leave it in it drops significantly, I don't know why, because I already blit a lot more images for the tiled background. method.
Improve performance by pre-treating the flora. Render on a surface before the application loop and blit the surface in the application loop:
def main():
# [...]
flora_surf = pygame.Surface(screen.get_size())
renderFlora(flora, flora_surf)
while True:
# [...]
#Draw Midground Items/Tiles
# renderFlora(flora, screen) <-- DELETE
screen.blit(flora_surf, (0, 0))
# [...]

Pygame - locking the scroll of a surface area to a limited amount

I'm playing with pygame and I'm making a memory game.
In my memory game I need to have a small Menu on the middle-bottom of the screen and the player list on top of the screen. The game manager will output the message in the upper left corner of the screen.
The playable board where the cards will be situated should be in the center of the screen with a small margin on the right and the left and about 200px from the top and the bottom.(e.g. if the screen width and height are 1200 x 800, the playable board should be from 2 to 1998 width and 200 to 600 height.
I've made a screenshot of the idea I have:
I've put up the idea of the scrollable board with the cards, although it's hardcoded for now, I mostly need the idea not the code since I just have a hard time figuring out how it should work.
The playable board (game board on the screenshot), should be moved through the keyboard(so up, right, down, left arrows). The thing I want to do is to allow more cards than 4 in each column and 12 in each row, in a way that when there are more cards than the 12 x 4, the gameboard could be moved, but without exiting the red square marked on the screenshot(so it's a scrollable surface). I want to limit the scrollable area to a width of 1200 and height of 400 px's, but in a way that the area is scrollable only inside the red area.
If that can't work or is planned otherwise, is there any way to register clicks differently? Let's say when I move the keys in a way that the Menu area is above the game board and the menu is clicked, I don't want the card under the Menu to be clicked as well. Is there any way to lock the content under the Menu?
Adding the code sample below:
from pygame import *
import sys
init()
screen_width = 1200
screen_height = 800
screen = display.set_mode((screen_width, screen_height))
board_width = 2000
board_height = 1000
playable_board = Surface((board_width, board_height))
playable_board = playable_board.convert()
screen.fill((255, 255, 255))
#draw.rect(playable_board, (125, 125, 125), (2, 200, board_width, board_height))
for x in range(0, 50):
draw.rect(playable_board, (100, 100, 100), (x * 100 + 5, 200, 90, 90))
draw.rect(playable_board, (100, 100, 100), (x * 100 + 5, 310, 90, 90))
draw.rect(playable_board, (100, 100, 100), (x * 100 + 5, 420, 90, 90))
draw.rect(playable_board, (100, 100, 100), (x * 100 + 5, 530, 90, 90))
# draw.rect(playable_board, (100, 100, 100), (x * 100 + 5, 640, 90, 90))
point_x = 0
point_y = 0
point_change = -30
animationTimer = time.Clock()
endProgram = False
while not endProgram:
for e in event.get():
pass
key_pressed = key.get_pressed()
if e.type == QUIT:
endProgram = True
if e.type == MOUSEBUTTONUP:
mouse_x, mouse_y = e.pos
display.set_caption(('Coordinates: ' + str(mouse_x + abs(point_x)) + 'x' + str(mouse_y + abs(point_y))))
draw.rect(playable_board, (50, 200, 50), (mouse_x + abs(point_x), mouse_y + abs(point_y), 10, 10))
if key_pressed[K_LEFT]:
point_x -= point_change
if key_pressed[K_RIGHT]:
point_x += point_change
if key_pressed[K_UP]:
point_y -= point_change
if key_pressed[K_DOWN]:
point_y += point_change
if point_x > 0:
point_x = 0
if point_x < -(board_width - screen_width):
point_x = -(board_width - screen_width)
if point_y > 0:
point_y = 0
if point_y < -(board_height - screen_height):
point_y = -(board_height - screen_height)
screen.blit(playable_board, (point_x, point_y, screen_width, screen_height))
draw.rect(screen, (100, 255, 100), (500, 650, 200, 150))
draw.rect(screen, (100, 255, 100), (100, 0, 1000, 50))
draw.rect(screen, (100, 255, 100), (0, 70, 250, 100))
animationTimer.tick(60)
display.update()
I'd create a subsurface of the playable_board and then blit it at the desired coordinates. You need to define a rect (called area here) with the desired size of the subsurface and scroll it by incrementing the x and y attributes. To keep the area rect inside of the board_rect (to prevent ValueErrors), you can call the pygame.Rect.clamp or clamp_ip methods.
import pygame as pg
pg.init()
screen = pg.display.set_mode((1200, 800))
board = pg.Surface((2000, 1000))
board.fill((20, 70, 110))
board_rect = board.get_rect()
# Append the rects to a list if you want to use
# them for collision detection.
rects = []
for y in range(11):
for x in range(22):
rect = pg.draw.rect(board, (100, 100, 100), (x*95, y*95, 90, 90))
rects.append(rect)
# The blit position of the subsurface.
pos = (20, 200)
point_change = -10
# This rect is needed to create a subsurface with the size (1160, 400).
area = pg.Rect(0, 0, 1160, 400)
# Use the area rect to create a subsurface of the board.
board_subsurface = board.subsurface(area)
clock = pg.time.Clock()
endProgram = False
while not endProgram:
for e in pg.event.get():
if e.type == pg.QUIT:
endProgram = True
key_pressed = pg.key.get_pressed()
# Scroll by changing the x and y coordinates of the area rect.
if key_pressed[pg.K_LEFT]:
area.x += point_change
elif key_pressed[pg.K_RIGHT]:
area.x -= point_change
if key_pressed[pg.K_UP]:
area.y += point_change
elif key_pressed[pg.K_DOWN]:
area.y -= point_change
# Check if one of the movement keys was pressed.
if any(key_pressed[key] for key in (pg.K_LEFT, pg.K_RIGHT, pg.K_UP, pg.K_DOWN)):
# Clamp the area rect to the board_rect, otherwise calling
# `board.subsurface` could raise a ValueError.
area.clamp_ip(board_rect)
# Create a new subsurface with the size of the area rect.
board_subsurface = board.subsurface(area)
screen.fill((30, 30, 30))
screen.blit(board_subsurface, pos)
pg.draw.rect(screen, (100, 255, 100), (500, 650, 200, 150))
pg.draw.rect(screen, (100, 255, 100), (100, 0, 1000, 50))
pg.draw.rect(screen, (100, 255, 100), (0, 70, 250, 100))
clock.tick(60)
pg.display.update()

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 let pygame text input detect the key in Pygame? [duplicate]

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

Categories

Resources