Pygame - TypeError: Missing 1 required positional argument
Question: I am building a game and I keep on running up against this error. I can't seem
to fix it. I believe the problem is either in the function "main" at the
bottom or in the classes "Level" and "Level01". If you find there is a way I
can improve my code can you also tell me as I am just learning how to build
games with OOP.

    
    
     File "C:/Users/fabma/Documents/PythonGames/RPG/Scroller!.py", line 148, in main
    currentLevel.drawer(display)
    TypeError: drawer() missing 1 required positional argument: 'display1'
    

Here is my code:

    
    
    import pygame
    # Colours + Global constants
    WHITE = (255, 255, 255)
    RED = (255, 0, 0)
    GREEN = (0, 255, 0)
    BLUE = (0, 0, 255)
    WIDTH = 800
    HEIGHT = 600
    SIZE = (WIDTH, HEIGHT)
    # CLASSES
    # Block is the common platform
    
    
    class Block(pygame.sprite.Sprite):
        def __init__(self, length, height, colour):
            super().__init__()
            # Making image
            self.image = pygame.Surface([length, height])
            self.image.fill(colour)
            self.rect = self.image.get_rect()
            # Setting Y coordinates
            self.rect.y = HEIGHT * 0.95
    
    
    class Player(pygame.sprite.Sprite):
        def __init__(self):
            super().__init__()
            # Is it touching the floor?
            self.velocity = 0
            self.standing = True
            # Rendering image and creating some variables
            self.height = 40
            self.length = 40
            self.sprite_x_change = 0
            self.sprite_y_change = 0
            self.image = pygame.Surface([self.height, self.length])
            self.image.fill(GREEN)
            self.rect = self.image.get_rect()
            self.rect.y = HEIGHT * 0.884
            self.level = None
        # Mobility: Left, right, up and stop
        def move_right(self):
            self.sprite_x_change = 15
    
        def move_left(self):
            self.sprite_x_change = -15
    
        def move_up(self, platform):
            # Seeing if we hit anything if so then we can jump!
            self.rect.y -= 2
            hit_list = pygame.sprite.spritecollide(self, platform, False)
            if len(hit_list) > 0 or self.rect.bottom >= HEIGHT - Block.height:
                self.change_y = -10
    
        def stop(self):
            self.sprite_x_change = 0
    
        def updater(self):
            self.gravity()
            platforms_hit = pygame.sprite.spritecollide(self, self.level.platforms, False)
            for blocks in platforms_hit:
                self.sprite_y_change = 0
                # Going down
                if self.sprite_y_change > 0:
                    self.rect.bottom = blocks.rect.top
                    self.velocity = 0
                    self.standing = True
                # Going up
                if self.sprite_y_change < 0:
                    self.rect.top = blocks.rect.bottom
                    self.standing = False
                if self.sprite_x_change > 0:
                    self.rect.right = blocks.rect.left
                if self.sprite_x_change < 0:
                    self.rect.left = blocks.rect.right
                if self.sprite_x_change == 0 and self.sprite_y_change == 0:
                    self.rect.y = HEIGHT * 0.884
    
            if self.standing == False:
                self.velocity += 1
            self.rect.x += self.sprite_x_change
            self.rect.y += self.sprite_y_change
    
        def gravity(self):
            self.sprite_y_change += 0.980665*self.velocity
    
    
    class Level:
        def __init__(self):
            # Creating groups
            self.sprites = pygame.sprite.Group()
            self.all_things = pygame.sprite.Group()
            self.platforms = pygame.sprite.Group()
    
        def drawer(self, display1):
            display1.fill(BLUE)
            self.all_things.draw(display1)
    
    
    class Level01(Level):
        def __init__(self, player1):
            # Initialise level1
            Level.__init__(self)
            # Level01 things
            block = Block(WIDTH, HEIGHT * 0.05, RED)
            Level.all_things = self.all_things
            self.sprites.add(player1)
            self.platforms.add(block)
            self.all_things.add(player1, block)
    
    
    def main():
        # Init pygame
        pygame.init()
        # Set screen
        display = pygame.display.set_mode(SIZE)
        # Creating FPS thingy
        clock = pygame.time.Clock()
        # Making levels  + Player
        player = Player()
        level_1 = Level01(player)
        # Choosing level
        levelList = []
        levelList.append(Level01)
        currentLevelNumber = 0
        currentLevel = levelList[currentLevelNumber]
        # Game loop
        loop = True
        while loop == True:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                if event.type == pygame.KEYDOWN:
                        if event.key == pygame.K_RIGHT:
                            player.move_right()
                        if event.key == pygame.K_LEFT:
                            player.move_left()
                        if event.key == pygame.K_UP:
                            player.move_up(currentLevel.platforms)
    
                if event.type == pygame.KEYUP:
                    if event.key == pygame.K_LEFT and player.sprite_x_change < 0:
                        player.stop()
                    if event.key == pygame.K_RIGHT and player.sprite_x_change > 0:
                        player.stop()
            # Update things
            currentLevel.all_things.update()
            currentLevel.drawer(display)
            # Refresh screen
            clock.tick(30)
            pygame.display.update()
        pygame.quit()
    
    if __name__ == "__main__":
        main()
    


Answer: You need to create an instance of your level rather than just appending the
class itself into your list:

    
    
    levelList.append(Level01)
    

should be...

    
    
    levelList.append(level_1)
    

* * *

As it stands, you're using the class object rather than an instance of it,
which means that the `display` you're passing is getting put into the `self`
argument (because the class object won't pass along an instance, because it's
not one). Once you're calling it on an instance of the class, the `self`
argument will be automatically passed and thus your `display` argument will
get passed to the correct spot.

