0

I am writing a game where a rock falls down and you use the mouse to have your chef not get crushed. When the rock falls off the screen, two additional rocks spawn and fall. This continues until your character gets smooshed.

However I got the error:

TypeError: unbound method additonal_drop() must be called with Dropper instance as first argument (got nothing instead)

I'm not sure what I should be putting in the (). Can someone explain this error to me?

In addition, how do I get the Dropper sprite to not be visible?

Here's my code:

from livewires import games, color
import random

games.init(screen_width = 640, screen_height = 480, fps = 50)


class Chef(games.Sprite):

    image = games.load_image("chef.bmp")

    def __init__(self):
        super(Chef, self).__init__(image = Chef.image,
                                  x = games.mouse.x,
                                  bottom = games.screen.height)
    def update(self):
        """ Move to mouse x position. """
        self.x = games.mouse.x

        if self.left < 0:
            self.left = 0

        if self.right > games.screen.width:
            self.right = games.screen.width

        self.check()

    def check(self):
        """ Check if hit by rocks. """
        for rock in self.overlapping_sprites:
            rock.end_game()

class Rock(games.Sprite):
    """
    A rock which falls to the ground.
    """ 
    image = games.load_image("rock.bmp")
    speed = 1

    def __init__(self, x = 320, y = 90):
        """ Initialize a rock object. """
        super(Rock, self).__init__(image = Rock.image,
                                    x = x, y = y,
                                    dy = Rock.speed)

    def end_game(self):
        """ End the game. """
        end_message = games.Message(value = "Game Over",
                                    size = 90,
                                    color = color.red,
                                    x = games.screen.width/2,
                                    y = games.screen.height/2,
                                    lifetime = 2 * games.screen.fps,
                                    after_death = games.screen.quit)
        games.screen.add(end_message)

    def update(self):
        """ Check if bottom edge has reached screen bottom. """
        if self.bottom > games.screen.height:
            self.destroy()
            Dropper.additonal_drop()


class Dropper(games.Sprite):
    """
    A invisible sprite that drops the rocks.
    """
    image = games.load_image("rock.bmp")
    def __init__(self, y = 55, speed = 2, odds_change = 200):
        """ Initialize the dropper object. """
        super(Dropper, self).__init__(image = Dropper.image,
                                      x = games.screen.width / 2, y = y,
                                      dx = speed)

        self.odds_change = odds_change
        self.time_til_drop = 0


    def update(self):
        """ Determine if direction needs to be reversed. """
        if self.left < 0 or self.right > games.screen.width:
            self.dx = -self.dx
        elif random.randrange(self.odds_change) == 0:
           self.dx = -self.dx

    def additonal_drop(self):
        new_rock = Rock(x = self.x)
        games.screen.add(new_rock)

        new_rock = Rock(x = self.x)
        games.screen.add(new_rock)


def main():
    """ Play the game. """
    wall_image = games.load_image("wall.jpg", transparent = False)
    games.screen.background = wall_image

    the_chef = Chef()
    games.screen.add(the_chef)

    the_rock = Rock()
    games.screen.add(the_rock)

    the_dropper = Dropper()
    games.screen.add(the_dropper)

    games.mouse.is_visible = False

    games.screen.event_grab = True
    games.screen.mainloop()

# start it up!
main()
Air
  • 8,274
  • 2
  • 53
  • 88
Josh
  • 3
  • 2
  • The `Rock` class doesn't have an `additional_drop()` method. The `additional_drop()` method has to be called on a `Dropper` _instance_, not on the `Dropper` class itself. – TigerhawkT3 Apr 13 '15 at 22:45
  • 2
    You're reading Python Programming for Absolute Beginners, right? That should have a full code sample containing the Pizza Pan game. – Malik Brahimi Apr 13 '15 at 22:48

1 Answers1

1

Try defining the Rock class with an additional parameter dropper:

def __init__(self, x = 320, y = 90, dropper=Dropper()):

dropper will be the Dropper instance. Then create Rock instances from inside Dropper as follows:

Rock(x=self.x, dropper=self)

This will pass the Dropper instance itself to each Rock instance that the Dropper instance creates. In Rock's __init__(), save a reference to the Dropper instance:

self.dropper = dropper

Call additional_drop() with:

self.dropper.additional_drop()
TigerhawkT3
  • 48,464
  • 6
  • 60
  • 97
  • Thank you! I actually finally had an epiphany and got it to work a different way, but I also tried your suggestion. Thanks. – Josh Apr 13 '15 at 23:09