Typing Tutor Game
The Fun
Now to make the game actually fun and challenging, we need to introduce some levelling up, or increased difficulty as we play.
There are multitude of ways to achieve this, we can:-
- increase the difficulty of words dropping.
- speed up the words
Level up
First let's set a level object member to keep track of how man words have dropped. Levelling up every four or five words is pretty good rate:
            class GamePlay():
    def __init__(self, screen):
        self.screen = screen
        pygame.init()
        self.disp_surf = pygame.Surface(self.screen.get_size()).convert()
        self.width, self.height = screen.get_size()
        self.font =  pygame.font.Font('Consolas Bold.ttf', 16)
        self.playing = True
        self.game_objects = GameObjects(self.width, self.height)
        self.last_add = 0 # time of adding word
        self.add_timeout = 2000 # 2 seconds
        self.fps = 25
        self.fps_clock = pygame.time.Clock()
        self.y_delta = 1
        self.typing_flag = False
        self.key_hit = None
        self.score = 0
        self.level = 1
        self.typed_count = 0
          
        And add counter for number of typed words:
                def add_score(self, score):
        self.score += score
        self.typed_count += 1
        # Level up
        if self.typed_count >= 4:
            self.level += 1
            self.typed_count = 0
          
        Let's now put the Level onto our status bar:
Also change draw_score to draw_status.
                def draw_score(self):
        # draw status bar background
        pygame.draw.rect(self.disp_surf, BLACK, (0,0,self.width,20), 0)
        # draw score text
        text = 'Score: %s' % self.score
        self.draw_word(text, YELLOW, (self.width - 150, 2))
        # draw level text
        text = 'Level: %s' % self.level
        self.draw_word(text, YELLOW, (MARGINX, 2))
        return
          
        The words
We have a large collection of words to choose from, so we want to narrow it down.
            # play.py
    def add_word(self, level):
        '''Add new word to drop from top'''
        if self.game_objects.is_gameover():
            return
        # Check if valid to add
        if not self.game_objects.game_words or (
            (pygame.time.get_ticks() - self.last_add) > self.add_timeout):
            if self.game_objects.add_word(self.level):
                self.last_add = pygame.time.get_ticks()
        return
          
        
            # objects
    def add_word(self, level):
        '''Add word to game play'''
        # Check that word doesn't duplicate first character in list
        word = self.get_word(level)
        firstchar = [word.text[0] for word in self.game_words]
        while word[0] in firstchar:
            word = self.get_word(level)
        # Get the list of city blocks still standing
        avail_blocks = []
        for idx, block in enumerate(self.city_line):
            if block.get_flag() == True:
                avail_blocks.append(idx)
        x_avail = random.choice(avail_blocks) * 10 + MARGINX
        
        # Calculate the max of x position of word
        max_x = (self.screen_width - MARGINX) - (FONTWIDTH * len(word))
        
        # Some randomised fun
        x = random.randint(MARGINX,max_x)
        x = random.choice([x_avail, x])
        x = min(x, max_x)
        
        self.game_words.append(Word(word, x))
        return True
    
    def get_word(self, level):
        '''Randomly select word from word list for game play'''
        return random.choice(self.word_list[:min(len(self.word_list), 50 * level)])
          
        Speed
To increase the speed, we can:-
- Increase the fps
- Increase y_delta
- Decrease add word timeout
          # play.py
    def add_score(self, score):
        self.score += score
        self.typed_count += 1
        
        # Level up
        if self.typed_count >= 4:
            self.level += 1
            self.typed_count = 0
            # Increase difficulty when leveling up
            if self.level % 5 == 0 and self.y_delta < 3:
                self.y_delta += 1
            elif self.level % 2 == 0 and  self.add_timeout > 1000:
                self.add_timeout -= 100
            elif self.fps < 60:
                self.fps += 3
        return
          
        