1

I want to make a player that can shoot bullets. To do this i tried defining a shoot function that gets called when space bar is pressed. The function looks like this (p is the player object btw):

class bullet:
    def __init__(self):
        self.x = None
        self.y = None
        self.radius = 10
        self.shooting = False
        self.speed = 5

    def shoot(self):
        self.shooting = True
        if  self.shooting == True:
            self.x = (p.x + 60)
            self.y = (p.y + 25)
            self.x += self.speed
            self.y += self.speed
            pygame.draw.circle(d, (0, 0, 0), (self.x, self.y), self.radius)

        shoot()

I was hoping that the function would keep calling itself and the bullet would keep moving forward. However what actually happens is when i press space, it gives me an error

    shoot()
NameError: name 'shoot' is not defined

How i called the function:

while True:
    d.fill((98, 98, 98))
    p.draw()

    for event in pygame.event.get():
        pass

    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_SPACE:
            b.shoot()

Something i observed is that if i remove the recursion shoot() at the end of the shoot() function, it runs but the bullet stays in the same place as long as the space is being held down(as expected as recursion was removed). How can i fix this problem? Thanks

2
  • The others below have given answers as to why it's giving this error. I just want to point out that the recursive design here is probably not what you want, and will eventually run out of stack-space, since it's an infinite recursive loop. Have a look at pygame sprite objects, and the update() function. pygame.org/docs/ref/sprite.html Commented Jan 9, 2020 at 22:36
  • Python isn’t <insert JVM language name here>, this isn’t the implicit scope for instance methods. Commented Jan 9, 2020 at 22:59

2 Answers 2

1

shoot is not a function, strictly speaking. It's an instance method, and must be invoked from a bullet object. You need to use

self.shoot()

for recursion.

However, this is a poor way to keep the bullet moving. This is a job for a loop. Recursion is best used when you're calling the routine with a smaller version of the problem; this is just a continuance.

    while self.shooting == True:
        self.x = (p.x + 60)
        self.y = (p.y + 25)
        self.x += self.speed
        self.y += self.speed
        pygame.draw.circle(d, (0, 0, 0), (self.x, self.y), self.radius)

This raises the question of how you intend to quit moving the bullet. You need something like

        self.shooting = (self.x <= x_limit) and \
                        (self.y <= y_limit)

Where x/y_limit are the upper bounds in that movement direction.

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

3 Comments

Just tried doing that but still got an error: RecursionError: maximum recursion depth exceeded in comparison
@hippozhipos that's a totally different error, unrelated to your first error.
@hippozhipos: that's because you have no exit from your recursion logic -- please see the second part of this answer.
1

I think you must replace the recursive call shoot() with self.shoot() inside the shoot method. That ought to get rid of the problem and also give you the recursive function that you want.

Comments

Your Answer

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