10

I'm a bit new to python, but familiar with OOP. I'm trying to write a game using PyGame. Basically, my aim is to render trees every few seconds and move the tree rects across the screen.

So here is my code:

from collections import deque
import pygame,random,sys

pygame.init()
size = 800,600
screen = pygame.display.set_mode(size)

class tree:
    def __init__(self):
            self.img = pygame.image.load("tree.png")
            self.rect = self.img.get_rect()
    def render(self):
            screen.blit(self.img,self.rect)
    def move(self,x,y):
            self.rect = self.rect.move(x,y)

#creating a queue of trees
trees = deque()

#appending the first tree on to the queue 
trees.append(tree())


while 1:


    for event in pygame.event.get():
            if event.type == pygame.QUIT: sys.exit()

    #appending tree() to trees queue every 300 ms
    if pygame.time.get_ticks() % 300 == 0:
            trees.append(tree())

    #rendering and moving all the tree rects of trees in the queue
    for tree in trees:
            tree.render()
            tree.move(20,2)
    pygame.display.flip()

But when I execute this the first few trees are generated successfully but then the PyGame window closed off and I get this error:

Traceback (most recent call last):
File "error.py", line 25, in <module>
trees.append(tree())
AttributeError: tree instance has no __call__ method

3 Answers 3

22

I guess it's because you have a variable name tree (used in tree.render()) which conflicts with your class name. Calling it Tree would be better (and more pythonic ^^).

Sign up to request clarification or add additional context in comments.

Comments

4

You might want to call the tree variable in the for loop something other than tree. It's shadowing the class name.

Comments

1

your context are polluted

while 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT: sys.exit()

    #appending tree() to trees queue every 300 ms
    if pygame.time.get_ticks() % 300 == 0:
        trees.append(tree()) <----------------------- second time, this tree is not your class, but the last instance of tree

    #rendering and moving all the tree rects of trees in the queue
    for tree in trees: <-------------------- here, the last tree will get name with tree
        tree.render()
        tree.move(20,2) 
    pygame.display.flip()

the compiler may thinks you are not init the class, but calls its call function.

1 Comment

In Python you can create callable types (types that implement the 'call' operator thru a __call__ method), and instantiation is actually performed by calling the class, which does implement the call operator. IOW, all the compiler sees is a 'call' operation, whatever it is performed on (and even the fact that the object being called does or not implement the call operator) being determined at runtime.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.