简体   繁体   中英

TypeError: 'pygame.Surface' object is not callable [Pygame module]

I have been designing a game recently as I'm starting a course at school and thought it would be helpful to get ahead.

I encountered the error

Traceback (most recent call last):
  File "C:\Users\Jake\Documents\Dungeon Crawler 2.1\Main.py", line 100, in <module>
    town()    
  File "C:\Users\Jake\Documents\Dungeon Crawler 2.1\Main.py", line 85, in town
    houseSpr1(0,250)
TypeError: 'pygame.Surface' object is not callable

While executing this code.

def town ():
    global outTown
    while not outTown:
            for event in pygame.event.get():
                    if event.type == pygame.MOUSEBUTTONDOWN:
                            print (event)
                            mx, my = pygame.mouse.get_pos()
                            mx = mx + my
                            if 375 <= mx <= 448:
                                    outTown = True
                                    print ("OK!")
                    if event.type == pygame.QUIT:
                            pygame.quit()
                            quit()

            houseSpr1 = pygame.image.load ('houseD.png') # default house img
            houseSpr1(0,250)
            gameDisplay.fill(green) # background
            pygame.draw.rect(gameDisplay,grey,(0,400,1280,50)) # main path
            pygame.draw.rect(gameDisplay,grey,(200,125,50,280)) # branch path
            player(x,y)
            pygame.display.update()
            clock.tick(60)

def houseSpr1(a,b):
    gameDisplay.blit(houseSpr1, (0,250))

def house1():
    global outHouse
    while not outHouse:
            gameDisplay.fill(black)
town()
houseSpr1()
gameIntro()
house1()
pygame.quit()
quit()

I understand this code may be inefficient in some ways, and I would be happy to know how I can improve it as well if you wish to provide insight in that light.


Any help with this error would be appreciated. And yes, I have read the rest of the questions before mine and I saw it was mostly down to typographical errors, but I can not see any of those here.

You used the name houseSpr1 for two things:

  • A global function, def houseSpr1(a,b): ...
  • A local variable for an image you load: houseSpr1 = pygame.image.load ('houseD.png') .

The two names are not independent . Functions are just another type of object in Python, and they are just stored like any other variable.

The moment you use the expression houseSpr1(0,250) , Python sees this as:

  1. Load the object named houseSpr1
  2. Take the results from 0 and 250 (two integer objects)
  3. Call the object loaded in step 1, passing in the results of step 2.

Because you assigned something to the name houseSpr1 in your town() function, it is that object , the image loaded, that Python tries to call. PyGame uses an object type named Surface to load images, and the error tells you you tried to call that object, but that object doesn't support being called.

The solution is to not use the same name:

houseSpr1Image = pygame.image.load('houseD.png')
houseSpr1(0, 250)

You'll have to adjust your houseSpr1 function too:

def houseSpr1(a,b):
    gameDisplay.blit(houseSpr1Image, (0,250))

You still have other problems here; houseSpr1Image is not a global, so the houseSpr1() function won't find it, giving you a NameError exception. You are also ignoring the a and b arguments to the function, hardcoding the 0,250 there. You'll have to solve those issues to for the code to work. Perhaps you can take a 3rd parameter, image :

def houseSpr1(image, a, b):
    gameDisplay.blit(image, (a, b))

and pass in the image surface:

houseSpr1Image = pygame.image.load('houseD.png')
houseSpr1(houseSpr1Image, 0, 250)

Martijn Pieters has already explained thoroughly why your code doesn't work. Here's a working, simplified version of your program to show you how it should look like.

Actually, the blit_houseSpr1 function is not necessary, since you could as well call gameDisplay.blit(houseSpr1, (80, 250)) in the main loop, but I just wanted to demonstrate how you can use a function and pass some arguments to it.

import pygame

pygame.init()
gameDisplay = pygame.display.set_mode((640, 480))
clock = pygame.time.Clock()

green = pygame.Color('green4')
grey = pygame.Color('grey50')
# Load the images once, because loading them from the hard disk is slow.
# And use the convert or convert_alpha methods to improve the performance.
houseSpr1 = pygame.image.load('houseD.png').convert()


def town():
    outTown = False
    while not outTown:
        for event in pygame.event.get():
            if event.type == pygame.MOUSEBUTTONDOWN:
                mx, my = pygame.mouse.get_pos()
                mx = mx + my
                if 375 <= mx <= 448:
                    outTown = True
            elif event.type == pygame.QUIT:
                outTown = True

        gameDisplay.fill(green) # background
        pygame.draw.rect(gameDisplay,grey,(0,400,1280,50)) # main path
        pygame.draw.rect(gameDisplay,grey,(200,125,50,280)) # branch path
        # Pass the image and the coordinates to the function.
        blit_houseSpr1(houseSpr1, 80, 250)

        pygame.display.update()
        clock.tick(60)


def blit_houseSpr1(image, a, b):
    # Now use the passed image and coordinates.
    gameDisplay.blit(image, (a, b))


town()
pygame.quit()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM