Aaron Nebbs
Aaron Nebbs

Reputation: 566

Python, Pygame Blitting to screen (argument 1 must be pygame.Surface)

I am creating a list of blocks that i want to loop through to print to the screen in pygame using the pygame.blit function. However an error is thrown that says (argument 1 must be pygame.Surface, not block). I have made other games in pygame printing objects to a screen but never putting them in a list first. Any help would be greatly appreciated.

    import pygame
import time



class block:
    def __init__(self, image, posX, posY, name):

        #Take passed image and assign to block#
        self.image = image

        #Create a rect for block for collisions#
#        self.rect = self.image.get_rect()

        #Create a positio from passed integers#
        self.posX = posX
        self.posY = posY

        #Set id of the block#
        self.name = name

    def draw(self, screen):
        screen.blit(self.image, (self.posX, self.posY))

    def getName(self):
        return self.name

class worldGeneration():
    def __init__(self):
        self.blocks = []

    def worldGen(self):
        grassImg = pygame.image.load("grass.png")
        dirtImg = pygame.image.load("dirt.png")


        for x in range(0, 640, 32):
            block1 = block(grassImg, 0 + x ,416, x)
            self. blocks.append(block1)
            for i in range(416, 480, 32):
                block1 = block(dirtImg, 0 + x ,448, x)
                self.blocks.append(block1)
    def getBlocks(self, x):
        return self.blocks[x]
    def draw(self, x, screen):
        screen.blit(self.blocks[x])


def gameUpdate(screen, world):

    screen.fill((147,200,250))
    for x in range (0, len(world.blocks)):
        world.draw(x, screen)
    pygame.display.flip()


def gameLoop():

    height = 480
    width = 640

    screen = pygame.display.set_mode((width, height))
    clock = pygame.time.Clock()

    world = worldGeneration()
    world.worldGen()

    running = True

    while running:
        clock.tick(60)
        pygame.display.set_caption(str(clock.get_fps()))

        for e in pygame.event.get():
            if e.type == pygame.QUIT:
                running = False

            if e.type == pygame.KEYDOWN and e.key == pygame.K_ESCAPE:
                running = False


        gameUpdate(screen, world)


gameLoop()

Upvotes: 0

Views: 861

Answers (2)

sloth
sloth

Reputation: 101142

Instead of

class worldGeneration():
    def __init__(self):
        self.blocks = []

    def worldGen(self):
        grassImg = pygame.image.load("grass.png")
        dirtImg = pygame.image.load("dirt.png")


        for x in range(0, 640, 32):
            block1 = block(grassImg, 0 + x ,416, x)
            self. blocks.append(block1)
            for i in range(416, 480, 32):
                block1 = block(dirtImg, 0 + x ,448, x)
                self.blocks.append(block1)
    def getBlocks(self, x):
        return self.blocks[x]
    def draw(self, x, screen):
        screen.blit(self.blocks[x])

you can do

class worldGeneration():
    def __init__(self):
        self.blocks = []

    def worldGen(self):
        grassImg = pygame.image.load("grass.png")
        dirtImg = pygame.image.load("dirt.png")


        for x in range(0, 640, 32):
            block1 = block(grassImg, 0 + x ,416, x)
            self. blocks.append(block1)
            for i in range(416, 480, 32):
                block1 = block(dirtImg, 0 + x ,448, x)
                self.blocks.append(block1)
    def getBlocks(self, x):
        return self.blocks[x]
    def draw(self, x, screen):
        self.blocks[x].draw(screen)

blit takes a Surface as first argument, you provided a block instance. That's what the error message tells you. But since you already implemented a draw method on block, simply use that, since it does what you want.

Also, you could go further and change

def gameUpdate(screen, world):

    screen.fill((147,200,250))
    for x in range (0, len(world.blocks)):
        world.draw(x, screen)
    pygame.display.flip()

to simply

def gameUpdate(screen, world):

    screen.fill((147,200,250))
    world.draw(screen)
    pygame.display.flip()

and change worldGeneration.draw to

def draw(self, screen):
    for block in self.blocks:
        block.draw(screen)

No need to get the len of blocks, loop through the range, and pass the index to the function when you could simply iterate over blocks with a for loop.

Upvotes: 0

Dalen
Dalen

Reputation: 4236

Do it that way:

  1. Create a surface()

  2. Blit block by block to it, changing coordinates accordingly

  3. Get the screen surface() and blit in the resulting one

  4. flip() the display!

Upvotes: 0

Related Questions