Have you played a typing speed game? It’s a very useful game to track your typing speed and improve it with regular practice. You can now create your own typing game in Python by just following a few simple steps.
About the Python Project
This Python project idea aims to create a fun project that allows you to assess and even enhance your typing speed. We're going to use the pygame library, which is used for working with graphics, to create a GUI.
Prerequisites
To install the pygame library, type the following code in your terminal.
pip install pygame
Let us understand the file structure of the Python project with source code that we are going to build:
Background.jpg – A background image we will use in our program
Icon.png – An icon image that we will use as a reset button.
Sentences.txt – This text file will contain a list of sentences separated by a new line.
typingSpeedTest.py – The main program file that contains all the code
load.png – The image to display when starting game
Steps to Build the Python Project on Typing Speed Test
You can download the resources and full source code of the project from Here
We can build this project using 7 steps:
Import the libraries
Create the game class
draw_text() method
get_sentence() method
show_results() method
run() method
reset_game() method
1. Import the libraries
For this project, we are using the pygame library. So we need to import the library along with some built-in modules of Python like time and random library.
import pygame
from pygame.locals import *
import sys
import time
import random
2. Create the game class
Now we create the game class which will involve many functions responsible for starting the game, reset the game and few helper functions to perform calculations that are required for our project in Python.
Let’s go ahead and create the constructor for our class where we define all the variables we will use in our project.
class Game:
def __init__(self):
self.w=750
self.h=500
self.reset=True
self.active = False
self.input_text=''
self.word = ''
self.time_start = 0
self.total_time = 0
self.accuracy = '0%'
self.results = 'Time:0 Accuracy:0 % Wpm:0 '
self.wpm = 0
self.end = False
self.HEAD_C = (255,213,102)
self.TEXT_C = (240,240,240)
self.RESULT_C = (255,70,70)
pygame.init()
self.open_img = pygame.image.load('resource/load.jpg')
self.open_img = pygame.transform.scale(self.open_img,(self.w,self.h))
self.bg = pygame.image.load('resource/background-gradient.jpg')
self.bg = pygame.transform.scale(self.bg, (750,500))
self.screen = pygame.display.set_mode((self.w,self.h))
pygame.display.set_caption('Type Speed test')
In this constructor, we have initialized the width and height of the window, variables that are needed for calculation and then we initialized the pygame and loaded the images.The most crucial variable on which we will draw everything is the screen variable.
3. draw_text() method
The draw_text() method of Game class is a helper function that will draw the text on the screen. The argument it takes is the screen, the message we want to draw, the y coordinate of the screen to position our text, the size of the font and color of the font. Everything will be drawn in the center of the screen. After drawing anything on the screen, pygame requires you to update the screen.
def draw_text(self, screen, msg, y ,fsize, color):
font = pygame.font.Font(None, fsize)
text = font.render(msg, 1,color)
text_rect = text.get_rect(center=(self.w/2, y))
screen.blit(text, text_rect)
pygame.display.update()
4. get_sentence() method
Remember that we have a list of sentences in our sentences.txt file? The file will be opened by the get_sentence() method, which will then select a random sentence from the list. We split the whole string with a newline character.
def get_sentence(self):
f = open('resource/sentences.txt').read()
sentences = f.split('\n')
sentence = random.choice(sentences)
return sentence
5. show_results() method
We determine the user's typing speed in the show_results() method. The user's time begins when they click the input box, and it ends when they press the return key, or "Enter." We then compute the difference and the time in seconds.
To calculate accuracy, we did a little bit of math. By comparing the input text with the display text that the user had to type, we were able to count the correct characters that were entered.
The formula for accuracy is:
(correct characters)x100/ (total characters in sentence)
The WPM is the words per minute. A typical word consists of around 5 characters, so we calculate the words per minute by dividing the total number of words with five and then the result is again divided that with the total time it took in minutes. Since our total time was in seconds, we had to convert it into minutes by dividing total time with 60.
The WPM is the words per minute.. A word typically has five characters, therefore we divide the entire number of words by five to get the words per minute, which is then divided by the whole amount of time in minutes. We had to divide the total amount of time, which was in seconds, by 60 to convert it to minutes.
Finally, we have drawn the typing icon image at the bottom of the screen which we will use as a reset button Our game would reset if the user clicked it. We will see the reset_game() method later in this article.
def show_results(self, screen):
if (not self.end):
# Calculate time
self.total_time = time.time() - self.time_start
# Calculate accuracy
count = 0
for i, c in enumerate(self.word):
try:
if self.input_text[i] == c:
count += 1
except:
pass
self.accuracy = count/len(self.word)*100
# Calculate words per minute
self.wpm = len(self.input_text)*60/(5*self.total_time)
self.end = True
print(self.total_time)
self.results = 'Time:'+str(round(self.total_time)) + " secs Accuracy:" + str(
round(self.accuracy)) + "%" + ' Wpm: ' + str(round(self.wpm))
# draw icon image
self.time_img = pygame.image.load('resource/icon.png')
self.time_img = pygame.transform.scale(self.time_img, (150, 150))
# screen.blit(self.time_img, (80,320))
screen.blit(self.time_img, (self.w/2-75, self.h-140))
self.draw_text(screen, "Reset", self.h - 70, 26, (100, 100, 100))
print(self.results)
pygame.display.update()
6. run() method
This is the main method of our class that will handle all the events.. At the starting of this method, we call the reset game() method, which resets all the variables. The next step is to execute an infinite loop that will record every mouse and keyboard event. The heading and input box are then drawn on the screen.
We then use another loop that will look for the mouse and keyboard events. When the mouse button is pressed, we check the position of the mouse if it is on the input box then we start the time and set the active to True. If it is on the reset button, then we reset the game.
We search for keyboard events when the active is True and typing has not yet stopped. If the user presses any key then we need to update the message on our input box. Once the enter key has been pressed, the score will be calculated and displayed. Backspaces can also be used to trim input text by erasing the final character.
def run(self):
self.reset_game()
self.running=True
while(self.running):
clock = pygame.time.Clock()
self.screen.fill((0,0,0), (50,250,650,50))
pygame.draw.rect(self.screen,self.HEAD_C, (50,250,650,50), 2)
# update the text of user input
self.draw_text(self.screen, self.input_text, 274, 26,(250,250,250))
pygame.display.update()
for event in pygame.event.get():
if event.type == QUIT:
self.running = False
sys.exit()
elif event.type == pygame.MOUSEBUTTONUP:
x,y = pygame.mouse.get_pos()
# position of input box
if(x>=50 and x<=650 and y>=250 and y<=300):
self.active = True
self.input_text = ''
self.time_start = time.time()
# position of reset box
if(x>=310 and x<=510 and y>=390 and self.end):
self.reset_game()
x,y = pygame.mouse.get_pos()
elif event.type == pygame.KEYDOWN:
if self.active and not self.end:
if event.key == pygame.K_RETURN:
print(self.input_text)
self.show_results(self.screen)
print(self.results)
self.draw_text(self.screen, self.results,350, 28, self.RESULT_C)
self.end = True
elif event.key == pygame.K_BACKSPACE:
self.input_text = self.input_text[:-1]
else:
try:
self.input_text += event.unicode
except:
pass
pygame.display.update()
clock.tick(60)
7. reset_game() method
The reset_game() method resets all variables so that we can start testing our typing speed again. We also select a random sentence by calling the get_sentence() method. In the end, we have closed the class definition and created the object of Game class to run the program.
def reset_game(self):
self.screen.blit(self.open_img, (0,0))
pygame.display.update()
time.sleep(1)
self.reset=False
self.end = False
self.input_text=''
self.word = ''
self.time_start = 0
self.total_time = 0
self.wpm = 0
# Get random sentence
self.word = self.get_sentence()
if (not self.word): self.reset_game()
#drawing heading
self.screen.fill((0,0,0))
self.screen.blit(self.bg,(0,0))
msg = "Typing Speed Test"
self.draw_text(self.screen, msg,80, 80,self.HEAD_C)
# draw the rectangle for input box
pygame.draw.rect(self.screen,(255,192,25), (50,250,650,50), 2)
# draw the sentence string
self.draw_text(self.screen, self.word,200, 28,self.TEXT_C)
pygame.display.update()
Game().run()
NOTE:
i. Game().run() is not inside the reset_game(self).
ii. methods draw_text(), get_sentence(), show_results(), run(), reset_game() should be inside class Game. In the end, closed the class definition and created an instance of the Game class i.e. Game().run() which is outside the class Game.
Our App on running
At startup
Result
Summary
In this article, you worked on the Python project to build your own game of typing speed testing with the help of pygame library.
I hope you got to learn new things and enjoyed building this interesting Python project. Do share the article on social media with your friends and colleagues.