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()
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()