Comparing keypressed to a char - python

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

Related

I'n creating my first game in pygame and i need help on showing up a screen when i press any key [duplicate]

This question already has answers here:
Faster version of 'pygame.event.get()'. Why are events being missed and why are the events delayed?
(1 answer)
Why is my PyGame application not running at all?
(2 answers)
Closed 1 year ago.
As i mention, i'm super new in pygame and need help with this. I'm just testing the pygame commands, and want to show up a white screen with a message whenever i initialize the game and press any key, but apparently, it's not working. Here's my code:
# pygame template
import pygame
# import random
WIDTH = 400
HEIGHT = 500
FPS = 60
TITLE = 'My Game'
FONT_NAME = 'SNAKE/DinoTopia.ttf'
# define colors
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
# initialize pygame and create window
pygame.init()
pygame.mixer.init()
SCREEN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption(TITLE)
CLOCK = pygame.time.Clock()
# classes
class Main:
def __init__(self):
self.running = False
self.game_font = pygame.font.match_font(FONT_NAME)
def show_screen(self):
if self.running is True:
SCREEN.fill(WHITE)
self.draw_text('HELLO', 50, WIDTH/2, HEIGHT/2, BLUE)
pygame.display.flip()
self.wait_for_key()
def wait_for_key(self):
for key in pygame.event.get():
if key.type == pygame.KEYUP:
self.running = True
self.show_screen()
def draw_text(self, text, size, x, y, color):
font = pygame.font.Font(self.game_font, size)
text_surface = font.render(text, True, color)
text_rect = text_surface.get_rect()
text_rect.center = (x, y)
SCREEN.blit(text_surface, text_rect)
g = Main()
# game loop
running = True
while running:
# keep loop running at the right speed
CLOCK.tick(FPS)
# process input
for event in pygame.event.get():
# check for closing window
if event.type == pygame.QUIT:
running = False
# update
# draw/ render
SCREEN.fill(BLACK)
g.wait_for_key()
# *after* drawing everything, flip the display
pygame.display.flip()
pygame.quit()
i know something may be wrong with the wait_for_key function but i can't see what it is, so a little help would be nice! thanks in advance!
show screen function is only called when a key is up. A single frame. You have to call it every frame. Also don't call pygame.event.get and pygame.display.flip more than once.
# pygame template
import pygame
# import random
WIDTH = 400
HEIGHT = 500
FPS = 60
TITLE = 'My Game'
FONT_NAME = 'SNAKE/DinoTopia.ttf'
# define colors
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
# initialize pygame and create window
pygame.init()
pygame.mixer.init()
SCREEN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption(TITLE)
CLOCK = pygame.time.Clock()
# classes
class Main:
def __init__(self):
self.running = False
self.game_font = pygame.font.match_font(FONT_NAME)
def show_screen(self):
if self.running:
SCREEN.fill(WHITE)
self.draw_text('HELLO', 50, WIDTH/2, HEIGHT/2, BLUE)
def wait_for_key(self, events):
for event in events:
if event.type == pygame.KEYUP:
self.running = True
def draw_text(self, text, size, x, y, color):
font = pygame.font.Font(self.game_font, size)
text_surface = font.render(text, True, color)
text_rect = text_surface.get_rect()
text_rect.center = (x, y)
SCREEN.blit(text_surface, text_rect)
g = Main()
# game loop
running = True
while running:
# keep loop running at the right speed
CLOCK.tick(FPS)
# process input
events = pygame.event.get()
for event in events:
# check for closing window
if event.type == pygame.QUIT:
running = False
# update
# draw/ render
SCREEN.fill(BLACK)
g.wait_for_key(events)
g.show_screen()
# *after* drawing everything, flip the display
pygame.display.flip()
pygame.quit()

Clicking recs in Pygame

I am currently starting on python3 in the past few days and started in developing minor projects, but i'm having some trouble, so sorry if i cant use top notch proffessional coders language.
How can I make a pygame.draw.rect rectangle become clickable?
I know about the pygame.mouse. ones, but there might be something wrong in the code.
I want it so that when i press the red rect it will decreese i health and will add a "burn" stat (its just text for now).
Here's the code:
import pygame
import random
import sys
pygame.init()
#Screen Size
screen_width = 600
screen_height = 600
#Screen Settings
screen = pygame.display.set_mode((screen_width, screen_height))
br_color = (0, 0, 0)
pygame.display.set_caption("Type Effect Beta 0.0.1")
#Game Over Bullian
game_over = False
#Other Defenitions
clock = pygame.time.Clock()
myFont = pygame.font.SysFont("arial", 20)
#Basic Recources
health = 50
score = 0
status = "none"
#Colors for the Text
white = (255, 255, 255)
red = (255, 0, 0)
#Mouse Things
mouse_location = pygame.mouse.get_pos()
print(mouse_location)
#Status Text Helpers
burning = "Burning"
#Cards
card_size_x = 45
card_size_y = 60
fire_car_color = (255, 0 ,0)
fire_card_posx = 300
fire_card_posy = 300
card_button_fire = pygame.Rect(fire_card_posx, fire_card_posy, card_size_x, card_size_y)
#Functions
def health_decrease_burn(health, status):
health -= 1
status = "burning"
return health and status
while not game_over:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if pygame.mouse.get_pressed()[0] and card_button_fire.collidepoint(mouse_location):
health_decrease_burn()
if health_decrease_burn(health, status) and health <= 0:
game_over = True
text = "Score:" + str(score)
lable = myFont.render(text, 1, white)
screen.blit(lable, (10, 10))
text = "Health:" + str(health)
lable = myFont.render(text, 1, red)
screen.blit(lable, (10, 30))
text = "Status:" + str(status)
lable = myFont.render(text, 1, white)
screen.blit(lable, (10, 50))
pygame.draw.rect(screen, fire_car_color, (fire_card_posx, fire_card_posy, card_size_x, card_size_y))
clock.tick(30)
pygame.display.update()
You need to grab the mouse_location every iteration of your main loop, as the mouse position/state is constantly changing. The current code is only fetching the mouse position once, on start.
while not game_over:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.MOUSEBUTTONUP: # if mouse button clicked
mouse_location = pygame.mouse.get_pos() # <-- HERE
if pygame.mouse.get_pressed()[0] and card_button_fire.collidepoint(mouse_location):
health_decrease_burn()
#[...etc ]

Python sin and cosine giving incorrect values

I have code that draws a line from 2 points; One on the middle bottom of the screen, and the other to the mouse pointer. I am trying to constrain the point by not exceeding a length parameter that I set. Heres the code:
import pygame
import Resources as r
import math as m
pygame.init()
class Segment():
def __init__(self, _screen, _id, _start_pos, _length):
self.screen = _screen
self.id = _id
self.start_pos = _start_pos
self.length = _length
def update(self):
if self.id == 1:
mouse_pos = pygame.mouse.get_pos()
self.angle = m.atan2(mouse_pos[1]-self.start_pos[1],mouse_pos[0]-self.start_pos[0])
self.a = self.start_pos
self.b = (m.cos(self.angle)*self.length, m.sin(self.angle)*self.length)
self.draw_line(self.a, self.b, r.black, 4)
def draw_line(self, start, end, color, width):
if self.id == 1:
pygame.draw.line(self.screen, color, start, end, width)
def get_data(self):
return (self.start_pos, self.end_)
I am seeing very different results when I run this that I would expect, it doesnt line up with my mouse and often just oscillates back and forth when the mouse is moved.
self.b is calculated based on origin 0, 0, not self.start_pos.
Add coordinates in self.a to self.b.
EDIT: as skrx pointed out in comment: mouse position doesn't have to be converted to Vector2 because tuple-Vector2 gives Vector2.
You can do the same with python.math.Vector2
Your start point on the middle bottom of the screen
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
screen_rect = screen.get_rect()
start = pygame.math.Vector2(screen_rect.centerx, screen_rect.bottom)
And end point using mouse positon and length
#mouse = pygame.math.Vector2(pygame.mouse.get_pos()) # edited
mouse = pygame.mouse.get_pos()
end = start + (mouse - start).normalize() * length
And now you can draw
pygame.draw.line(screen, (255,0,0), start, end)
Working example
import pygame
# === CONSTANS === (UPPER_CASE names)
BLACK = ( 0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = ( 0, 255, 0)
BLUE = ( 0, 0, 255)
SCREEN_WIDTH = 600
SCREEN_HEIGHT = 400
# === MAIN === (lower_case names)
# --- init ---
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
screen_rect = screen.get_rect()
# --- objects ---
start = pygame.math.Vector2(screen_rect.centerx, screen_rect.bottom)
end = start
length = 150
# --- mainloop ---
clock = pygame.time.Clock()
is_running = True
while is_running:
# --- events ---
for event in pygame.event.get():
# --- global events ---
if event.type == pygame.QUIT:
is_running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
is_running = False
elif event.type == pygame.MOUSEMOTION:
#mouse = pygame.math.Vector2(pygame.mouse.get_pos()) # edited
mouse = pygame.mouse.get_pos()
end = start + (mouse - start).normalize() * length
# --- objects events ---
# empty
# --- updates ---
# empty
# --- draws ---
screen.fill(BLACK)
pygame.draw.line(screen, RED, start, end)
pygame.display.update()
# --- FPS ---
clock.tick(25)
# --- the end ---
pygame.quit()
Red line has always the same length and it shows direction to cursor.

Hide part after 5 seconds after mousedown action

I'm new to python. I programmed with vb2010, but it's time to try something new. I want to hide a action after 5 seconds after mouse down event(like in start()).
import pygame
import sys
from pygame.locals import *
from time import gmtime, strftime
import threading
import time
white = (255,255,255)
black = (0,0,0)
blue = (0,0,255)
width = 600
height = 400
channel = '0001'
name = 'Channel 3'
class screen(object):
def __init__(self):
pygame.init()
self.font = pygame.font.SysFont('Arial', 25)
pygame.display.set_caption('PyTV')
self.screen = pygame.display.set_mode((width,height), 0, 32)
self.screen.fill((black))
pygame.display.update()
def printData(self):
self.rect = pygame.draw.rect(self.screen, (blue), (0, 0, width, height - 350), 0)
self.screen.blit(self.font.render(channel, True, white), (width - 590, 0))
self.screen.blit(self.font.render(name, True, white), (height - 335, 0))
self.screen.blit(self.font.render(strftime("%H:%M %d/%m/%Y", gmtime()), True, white), (width - 590, height - 377))
pygame.display.update()
def clean(self):
self.screen.fill((black))
pygame.display.update()
if __name__ == '__main__':
def start():
Pan3.printData()
time.sleep(5)
Pan3.clean()
Pan3 = screen()
threading.Thread(target=start).start()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit(); sys.exit();
if event.type == pygame.MOUSEBUTTONDOWN:
print 'Event! Mouse Down! Code here....'
A timer may suit your needs, given that you also use threading.
EDIT: Addressing your needs for a more detailed explanation as to how to get it to work, here's some pseudo-code.
if event.type == pygame.MOUSEBUTTONDOWN:
if active_timer:
timer.cancel()
timer = Timer(5.0, show_info_things)
timer.start()
I hope this gets you going well enough.
When you click left mouse first time then it shows date, when you click second time then it hides date. If you don't click second time then it hides automatically after 5 seconds.
The same with key SPACE - first press shows, second hides. If you don't press second time then it hides automatically after 5 seconds.
Key ESC and right click hides too.
import pygame
import sys
import time
# --- constants --- (UPPER_CASE names)
WHITE = (255,255,255)
BLACK = ( 0, 0, 0)
BLUE = ( 0, 0,255)
WIDTH = 600
HEIGHT = 400
# --- classes --- (CamelCase names)
class Screen(object):
def __init__(self):
pygame.init()
self.screen = pygame.display.set_mode((WIDTH, HEIGHT), 0, 32)
pygame.display.set_caption('PyTV')
self.font = pygame.font.SysFont('Arial', 25)
self.channel = '0001'
self.name = 'Channel 3'
self.show_data = None
self.current_time = pygame.time.get_ticks()
def draw_data(self):
self.rect = pygame.draw.rect(self.screen, BLUE, (0, 0, WIDTH, HEIGHT-350), 0)
self.screen.blit(self.font.render(self.channel, True, WHITE), (WIDTH-590, 0))
self.screen.blit(self.font.render(self.name, True, WHITE), (HEIGHT-335, 0))
self.screen.blit(self.font.render(time.strftime("%H:%M:%S %d/%m/%Y", time.gmtime()), True, WHITE), (WIDTH-590, HEIGHT-377))
def events(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
return False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
self.show_data = None
elif event.key == pygame.K_SPACE:
if self.show_data:
self.show_data = None
else:
self.show_data = self.current_time + 5000
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1:
if self.show_data:
self.show_data = None
else:
self.show_data = self.current_time + 5000
elif event.button == 3:
# hide on right click
self.show_data = None
def update(self):
# if displayed
if self.show_data:
# check time
if self.current_time >= self.show_data:
# hide after time
self.show_data = None
def draw(self):
self.screen.fill(BLACK)
if self.show_data:
self.draw_data()
pygame.display.update()
def run(self): # mainloop
while True:
self.current_time = pygame.time.get_ticks()
if self.events() is False:
break
self.update()
self.draw()
#sys.exit()
# --- fucntions --- (lower_case names)
# empty
# --- main ---
if __name__ == '__main__':
Screen().run()

Pygame: Text Won't Appear Only Background

I have just added in some code I had tried out into my game as a scoreboard and I have encountered an error. Only my background will display. No text or anything will appear. Here is the code I am using:
class MenuScores(MenuClass):
def __init__(self, surface, engine):
MenuClass.__init__(self, surface)
self.MoonSurvival = engine
self.text = "Name"
def name():
size = 36
screen = pygame.display.set_mode((1280, 720))
name = ""
font = pygame.font.SysFont('data/fonts/score.ttf', size)
background = pygame.image.load('data/images/bg.jpg')
while True:
# readlines returns a list; having this in
# loop allows pygame to draw recently added
# string; no need to close and open a window
namefile = open('score.txt', 'r')
names = namefile.readlines()
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.unicode.isalpha():
if len(name) < 4:
if event.unicode == 3:
name += 0
else:
name += event.unicode
elif event.key == K_BACKSPACE:
name = name[:-1]
elif event.key == K_RETURN:
f = open("data/scores/score.txt", "a")
f.write(str(name) + " " + str(self.MoonSurvival.total_score) + "\n")
f.close()
name = ""
self.text = ""
elif event.type == QUIT:
return
# create a Rectangle container, where yours
# text variable will be drawn
# Rect(left, top, width, height)
textrect = Rect(0, 0, 100, size)
screen.fill((0, 0, 0))
for i in names:
# iterate through lines from text file (it is stored
# in names variable and it is a list)
# create text variable and draw it to textrect
text = font.render(i[:-1], True, (255,0,0), (0,0,0))
screen.blit(text, textrect)
# change y coordinate of textrect; in next iteration
# next line will appear below the previous line
textrect.centery += size
block = font.render(name, True, (255, 255, 255))
rect = block.get_rect()
rect.center = screen.get_rect().center
screen.blit(background, (0, 0))
screen.blit(block, rect)
pygame.display.update()
pygame.display.flip()
def draw(self):
self.renderText()
self.drawHint()
self.surface.blit(self.background, (0, 0))
# update surface
pygame.display.update()
def _handleEvents(self, event):
def pressed(key):
keys = pygame.key.get_pressed()
if keys[key]:
return True
else:
return False
if pressed(pygame.K_SPACE):
self.MoonSurvival.game_state = STATE_MENU
self.MoonSurvival.level = 1
def renderText(self):
# split texts at \n (newline)
texts = self.text.split('\n')
for i in range(len(texts)):
textSurface = self.menufont.render(texts[i], 0, (255, 0, 0))
textRect = textSurface.get_rect()
textRect.centerx = SCREEN_WIDTH / 2
textRect.centery = SCREEN_HEIGHT / 2 + i * self.menufont.size(texts[i])[1]
self.surface.blit(textSurface, textRect)
def drawHint(self):
textSurface = self.menufont.render('(Press SPACE to return to menu)', 0, (255, 0, 0))
textRect = textSurface.get_rect()
textRect.centerx = SCREEN_WIDTH / 2
textRect.centery = SCREEN_HEIGHT - 50
self.surface.blit(textSurface, textRect)
I really don't know how to fix this. The text appeared fine when it was on its own (the def name()) So why does it not work here?
self.renderText()
self.drawHint()
self.surface.blit(self.background, (0, 0))
Here, you are drawing the text on self.surface, then drawing the hint on self.surface, and then painting the background image on self.surface, over top everything else.
Instead, you should draw the background first, and everything else after it.
self.surface.blit(self.background, (0, 0))
self.renderText()
self.drawHint()

Categories