Asteroid Class and Subclasses [60 pts] [autograded]
Write the Asteroid, ShrinkingAsteroid, and SplittingAsteroid classes so that
they pass testAsteroidClasses, and uses the OOP constructs we learned
as appropriate.
On hw4-2, you will use these classes in your animation!
def getLocalMethods(clss):
import types
# This is a helper function for the test function below.
# It returns a sorted list of the names of the methods
# defined in a class. It's okay if you don't fully understand it!
result = [ ]
for var in clss.__dict__:
val = clss.__dict__[var]
if (isinstance(val, types.FunctionType)):
result.append(var)
return sorted(result)
def testAsteroidClasses():
print("Testing Asteroids classes...", end="")
# A basic Asteroid takes in cx, cy, radius, speed, and optional direction.
# It's default direction (dx, dy) is (0, 1), or moving down
asteroid1 = Asteroid(25, 50, 20, 5)
assert(type(asteroid1) == Asteroid)
assert(isinstance(asteroid1, Asteroid))
asteroid1.setDirection((-1, 0))
assert(asteroid1.getDirection() == (-1,0))
assert(str(asteroid1) ==
"Asteroid at (25, 50) with radius=20 and direction (-1, 0)")
assert(str([asteroid1]) ==
"[Asteroid at (25, 50) with radius=20 and direction (-1, 0)]")
# isCollisionWithWall takes in the canvasWidth and canvasHeight
# Asteroids collide with walls if any part of them is touching any side
# of the canvas
assert(asteroid1.isCollisionWithWall(400, 400) == False)
asteroid1.moveAsteroid()
assert(str(asteroid1) ==
"Asteroid at (20, 50) with radius=20 and direction (-1, 0)")
assert(asteroid1.getPositionAndRadius() == (20, 50, 20))
assert(asteroid1.isCollisionWithWall(400, 400) == True)
# A normal asteroid is stunned when it is hit by a bullet, and it freezes
asteroid1.reactToBulletHit()
assert(asteroid1.getDirection() == (0, 0))
localMethods = ['__init__', '__repr__',
'getDirection', 'getPositionAndRadius',
'isCollisionWithWall', 'moveAsteroid',
'reactToBulletHit', 'setDirection']
methodsFound = getLocalMethods(Asteroid)
for method in localMethods:
assert(method in methodsFound)
# A Shrinking Asteroid takes in cx, cy, radius, speed,
# an optional direction (that is (0, 1) by default),
# and an optional shrinkAmount set to 5 pixels by default.
# ShrinkAmount is how much the radius of the asteroid decreases when it is
# hit by a bullet. A Shrinking Asteroid can also bounce off the walls.
asteroid2 = ShrinkingAsteroid(200, 200, 50, 20)
assert(type(asteroid2) == ShrinkingAsteroid)
assert(isinstance(asteroid2, ShrinkingAsteroid))
assert(isinstance(asteroid2, Asteroid))
asteroid2.reactToBulletHit()
assert(asteroid2.getPositionAndRadius() == (200, 200, 45))
assert(str(asteroid2) ==
"ShrinkingAsteroid at (200, 200) with radius=45 and direction (0, 1)")
asteroid2.setDirection((1, -1))
asteroid2.bounce()
assert(asteroid2.getDirection() == (-1, 1))
asteroid3 = ShrinkingAsteroid(100, 100, 40, 10,
direction=(0, -1), shrinkAmount=20)
# The asteroid's radius will decrease by the shrinkAmount
asteroid3.reactToBulletHit()
assert(asteroid3.getPositionAndRadius() == (100, 100, 20))
assert(getLocalMethods(ShrinkingAsteroid) == ['__init__','bounce',
'reactToBulletHit'])
# A Splitting Asteroid takes in cx, cy, radius, speed, and an optional
# direction (set to (0, 1) by default). It splits into two smaller
# Splitting Asteroids when hit by a bullet.
# The each smaller Splitting Asteroid has radius that is half of
# the original Splitting Asteroid's and has the original speed and direction
asteroid4 = SplittingAsteroid(300, 300, 20, 15)
assert(type(asteroid4) == SplittingAsteroid)
assert(isinstance(asteroid4, SplittingAsteroid))
assert(isinstance(asteroid4, Asteroid))
assert(not isinstance(asteroid4, ShrinkingAsteroid))
# reactToBulletHit returns 2 new instances of the SplittingAsteroid class
asteroid5, asteroid6 = asteroid4.reactToBulletHit()
# The new Splitting Asteroid centers are at the top-left and bottom-right
# corners of the bounding box surrounding the original asteroid
# See the test cases below for an example:
assert(asteroid5.getPositionAndRadius() == (280, 280, 10))
assert(asteroid6.getPositionAndRadius() == (320, 320, 10))
assert(str(asteroid6) ==
"SplittingAsteroid at (320, 320) with radius=10 and direction (0, 1)")
assert(getLocalMethods(SplittingAsteroid) == ['__init__',
'reactToBulletHit'])
print("Done!")