Drand
Drand

Reputation: 9

pygame user input does not render after hitting enter

I am trying to create a wordle clone in python. I am not very experienced with pygame, and am trying to set up user input in the small grey boxes on the screen. However, the code I am using will either not correctly accept user input, or not correctly render it. (I suspect it's the latter.) I have looked at the code tutorial I am referencing many times, checked stack overflow posts, but none seem to work. I would expect that after typing and hitting return, the word would show up, as the word being rendered while you are typing has been removed for code simplicity. Any help would be appreciated.

import random
import pygame

word_options = ("birth", "happy", "nancy")
word = random.choice(word_options).upper

WIDTH = 600
HEIGHT = 700
MARGIN = 10
T_MARGIN = 100
B_MARGIN = 100
LR_MARGIN = 100

GREY = (225, 227, 229)
GREY_FILLED = (120, 124, 126)
GREEN = (6,214,160)
YELLOW = (255, 209, 102)

INPUT = ""
GUESSES = ["berry"]
ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
UNGUESSED = ALPHABET
GAME_OVER = False

pygame.init()
pygame.font.init()
pygame.display.set_caption("Nancdle")

SQ_SIZE = (WIDTH-4*MARGIN-2*LR_MARGIN) // 5
FONT = pygame.font.SysFont("free sans bold", SQ_SIZE)
FONT_SMALL = pygame.font.SysFont("free sans bold", SQ_SIZE//2)

#screen
screen = pygame.display.set_mode((WIDTH, HEIGHT))
white = (255, 255, 255)
#animation loop
animating = True
while animating:

  screen.fill(white)
  letters =FONT_SMALL.render(UNGUESSED, False, GREY_FILLED)
  surface = letters.get_rect(center = (WIDTH//2, T_MARGIN//2))
  screen.blit(letters, surface)
  
  y = T_MARGIN
  for i in range(6):
    x = LR_MARGIN
    for j in range(5):
      square = pygame.Rect(x, y, SQ_SIZE, SQ_SIZE)
      pygame.draw.rect(screen, GREY, square, 2)
      #to add past letters/words
      if i < len(GUESSES):
        color = GREY_FILLED
        pygame.draw.rect(screen, color, square)
        letter = FONT.render(GUESSES[i][j], False, (255,255,255))
        surface = letter.get_rect(center = (x+SQ_SIZE//2, y+SQ_SIZE//2))
        screen.blit(letter, surface)
      x += SQ_SIZE + MARGIN
    y += SQ_SIZE + MARGIN
  
    
  #to update screen
  pygame.display.flip()
  for event in pygame.event.get():
    #so you can close window
    if event.type == pygame.QUIT:
      animating = False
    
    elif event.type == pygame.KEYDOWN:
      if event.key == pygame.K_RETURN:
        if len(INPUT) == 5:
          GUESSES.append(INPUT)
          GAME_OVER = True if INPUT == ANSWER else false
          INPUT = ""
      
    
        elif len(INPUT) < 5 and not GAME_OVER:
          INPUT = INPUT + event.unicode.upper()

I will gladly remove this post if the question is worded poorly or asked incorrectly.

Upvotes: 1

Views: 71

Answers (1)

import random
import random

Reputation: 3245

Your code is only handling events for K_Return, not any other keys. This is caused by indenting elif len(INPUT) < 5 and not GAME_OVER: too far.

If you change your event handler code as follows, it should work:

elif event.type == pygame.KEYDOWN:
  if event.key == pygame.K_RETURN:
    if len(INPUT) == 5:
      GUESSES.append(INPUT)
      GAME_OVER = True if INPUT == word else False
      INPUT = ""

  elif len(INPUT) < 5 and not GAME_OVER:
    INPUT = INPUT + event.unicode.upper()

Note I also had to replace ANSWER with word and capitalise false.

You are using two spaces for indentation, it might have been easier to identify the scope mismatch if you'd used four.

Using event.unicode is reasonably robust, but users can still add numbers and spaces. If you want to loop through all letter keys but don't want something horrible like if event.key in [pygame.K_a, pygame.K_b, ... , you can use range, e.g.

elif event.type == pygame.KEYDOWN:
    if event.key == pygame.K_RETURN:
        if len(INPUT) == 5:
            GUESSES.append(INPUT)
            GAME_OVER = True if INPUT == ANSWER else False
            INPUT = ""
    elif event.key in range(pygame.K_a, pygame.K_z + 1):
        # any other letter keys pressed
        if len(INPUT) < 5 and not GAME_OVER:
            INPUT = INPUT + event.unicode.upper()
    elif event.key in [pygame.K_BACKSPACE, pygame.K_DELETE]:
        INPUT = INPUT[:-1]  # don't need to check length

Upvotes: 0

Related Questions