Due: , 11:59 pm
The focus on this project is to provide you with experience writing classes with inheritance. We will also be using a dictionary to make working with collisions easier.
The first task is to create a new Floor class using inheritance (the parent class is Thing). The __init__() method should have five parameters.
|win||A reference to a GraphWin object|
|x0||The anchor point x value. The anchor is in the middle of the left side.|
|y0||The anchor point y value. The anchor is in the middle of the left side.|
|length||The horizontal distance of the floor.|
|thickness||The vertical distance of the floor.|
As with the Ball class, the first action in the __init__() method is to call the parent Thing.__init__() method. Specify the type as the string "floor", and pass in [x0, y0] as the position. Next, assign the parameters length and thickness to two fields width and height. Since you have three classes (Floor, Wall, and then Block) that will be rectangular in shape, it makes sense to use width and height as the fields for that information in all three classes. However, since those fields are not created in the Thing class, you need to create and assign them here.
Next, create the Rectangle object to represent the floor, just as you did in the prior lab (copy and paste that line of code).
Finally, add two methods, getHeight() and getWidth() that return the width and height of the object.
Repeat this process with the Wall class, which will look almost identical. Use "wall" as the type of the Wall class when calling the Thing.__init__() method.
Repeat this process with a new Block class. The parameters for the
Block class should be the same as the Floor and Wall classes. When
creating the visualization for the block, put the anchor point in the
center of the block. One corner should be at
(x0-width/2, y0-height/2) and the other
corner should be at
Note, the primary difference between a Wall, a Floor, and a Block is in how they are treated with respect to collisions. A Floor is a horizontal plane that extends infinitely. A Wall is a vertical plane that extends infinitely. A Block is just a block and is finite in both directions. The Floor and Wall classes let us do collisions a little faster than a Block.
The next task is to modify the collision.py file to make it simpler to call the right collision function no matter what types of objects are involved. Note, the collision functions all work with a ball and something else. We don't yet have block-block collisions, for example.
The idea is to use a dictionary with the two types involved as the key, making use of the type field in the Thing class. For example, if we have two objects, item1 and item2, we can generate a key by writing:
key = (item1.getType(), item2.getType())
This creates a tuple that has two strings in it. Then, we can generate a dictionary entry that contains all the possible keys and stores the proper function to call in each case. For example, the following creates an entry in the dictionary collision_router with the key ('ball', 'ball') and sets its value to the function reference collision_ball_ball.
collision_router[ ('ball', 'ball') ] = collision_ball_ball
At the bottom of the collision.py file, at the top level (meaning totally unindented), create an empty dictionary called collision_router. Then add an entry to the dictionary (as above) for each possible of a ball and another type. There are four other types: floor, wall, block, and ball. There are also four collision functions, one for each combination.
Finally, create a function called collision() that takes in two Thing objects plus a time step and uses the collision_router dictionary to call the right function. For now, you can assume the first argument will be a ball. However, think about how you could code this up, possibly by creating a few additional one line functions, such that it would not matter which order the objects appeared in the collision function parameters.
Create a scene that is like a pinball table. It should have overall boundaries, then some obstacles inside the bounding box that are all stationary. Create a launch location and launch a single ball into the scene. Respawn if the ball goes out of play.
The main file should have the following structure.
# build the obstacle course def buildGame(win, x0, y0, width, height): # Create all of the obstacles in the scene and put them in a list # Draw all of the obstacles # You might want to set the obstacle elasticity to something larger than 1 # return the list of obstacles # launch the ball into the scene def launch( ball, x0, y0, dx, dy, forceMag ): d = math.sqrt(dx*dx + dy*dy) dx /= d dy /= d fx = dx * forceMag fy = dy * forceMag ball.setElasticity( 0.9 ) ball.setPosition( (x0, y0) ) ball.setForce( (fx, fy) ) for i in range(5): ball.update(0.02) ball.setForce( (0., 0.) ) ball.setAcceleration( (0., -1.) ) # main code def main(): # Create a GraphWin # Assign to obstacles the result of calling buildGame # Make a Ball object, draw it, and launch it into the scene # assign to dt the value 0.01 # assign to frame the value 0 # while win.checkMouse is equal to None: # assign to collided the value False # for item in obstacles # if the result of calling the collision function with the ball and the item is True # set collided to True # if collided is False # call the update method of the ball with dt as the time step # if frame modulo 10 is equal to 0 # call win.update() # increment frame # if the ball goes out of the window, re-launch it # wait for a mouse click, then close the window if __name__ == "__main__": main()
Create a video of your obstacle course in action and include a link to it on your wiki.
Create a new class that makes a new shape. Specify its type as either a block or a ball, depending on which shape's outline is better suited for collisions. Add an example of this shape to the obstacle course.
For example, you could make a shape like an H and specify that it is of type 'ball' for the purposes of collisions. Then you can shoot it into your obstacle course and it should act like a ball with respect to collisions. Note, things of type 'block' can't move, but things of type 'ball' can (at least with respect to collisions).
Include a picture of your new shape as part of your wiki. If you are feeling ambitious, include the shape in your video or make a second video.
The following are a few examples of potential extensions. Please do not feel that your extensions must be drawn from this list. Get creative, design extensions that interest you, and explain why they are awesome when you present the results in your writeup. Your interest in your own extensions really does make a difference.
Make a new wiki page for your assignment. Put the label
on the page. Each of you needs to make your own writeup.
In addition to making the wiki page writeup, put the python files you wrote on the Courses server in your private directory in a folder named project9.
In general, your writeup should follow the outline below.
© 2018 Caitrin Eaton.