Project 10: Collisions with Rotation
The focus on this project is to give you more experience writing child classes, working with equations and code, and integrating user input.
- Create a RotatingBlock class
The first task is to create a RotatingBlock class. You can add it to your physics_objects.py file or create a new file; the choice is yours. The class should be called RotatingBlock, and it should inherit from the Thing class, just like the Ball and Block classes.
- Define the __init__ method
The RotatingBlock.__init__ method should have at least the following parameters. The win, width, and height parameters should be required.
Parameter Purpose win A reference to a GraphWin object width The horizontal extent of the block. height The vertical extent of the block. position The x and y coordinates of the center of the block as a 2-element list. anchor The x and y coordinates of the block's center of rotation as a 2-element list, with the default value of None.
Using the same terminology as for rotating lines, the position should be the center of the block, and the anchor refers to the anchor point for the rotation of the block (i.e., the point around which the block rotates). Also, as with the RotatingLine class, if the anchor point is not given, it should use the position as the anchor point for the rotation.
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 "rotating block", and pass in any necessary parameters. Next, assign the parameters width and height to two fields width and height.
In order to rotate the block, we have to represent the points that make up the corners. You can initialize that field (e.g. self.points) to the empty list here. The values will be inserted in the render method.
The remaining unique fields should be identical to the ones you created in the RotatingLine class: angle, rvel, and anchor. The initial values of the angle and rvel fields should be 0.
- Write a render method for RotatingBlock
Make the render method. This will be similar to the RotatingLine version except that the last step will be to create a graphics Polygon instead of a Line, using the list of rotated points. After you create the polygon, set its fill color with the value in the object's color field. Then put it into a list and assign it to the object's shapes list.
Finish the init method by calling the render method.
- Write the get and set methods
Make the following methods
returns the current angle
returns a copy of the current anchor point
returns the current rotationalVelocity
returns the width of the block.
returns the height of the block.
def setAngle(self, angle):
updates the angle value, calls the render method.
def setAnchor(self, anchor):
updates the anchor value, calls the render method.
def setRotVelocity(self, vel):
updates the rotational velocity value.
def setWidth(self, w):
updates the block width, calls the render method.
def setHeight(self, h):
updates the block height, calls the render method.
def rotate(self, da):
increments the angle field by the given amount, calls the render method.
Any set method that changes the orientation or size of the RotatingBlock needs to call render after updating the object's field.
When complete, run the first test function. You may need to modify the test code, depending on where you wrote your RotatingBlock class. The block should spin around its center.
- Write an update method for RotatingBlock
Create an update method in the RotatingBlock class, since the Thing.update method does not include rotational velocity. The update method needs to take self and dt (time step) as arguments. The update method should first calculate how much the angle changes during the time step (self.rvel * dt) and assign that to a local variable (e.g. da). If the da value is not equal to zero, then call the rotate method, passing in da as the argument. Then, call the update method in the Thing class, passing in self and dt.
Once you have the update method done, try out the second second test function. Since the anchor point is different, the block should appear to rotate around the center of the screen once.
- Test RotatingBlock with collisions
If you want to incorporate the rotating line in your scene, make sure it has getWidth and getHeight methods. Then update the collision_router so it uses the rotating block collision function with the "rotating line" type.
- Define the __init__ method
- Make a simple obstacle course with rotating objects
Create a very simple obstacle course with one or two rotating objects. Launch one or more balls into the scene.
Create a screen video of your simple obstacle course in action. Please submit it with your code or put it on Google drive with a link to it on classroom.
- Make a scene with user interaction
Create a scene that includes at least one rotating object, at least one instance of each of your other objects, and incorporates some form of user interaction. For example, add paddles to your pinball-style scene from last week that activate when the user hits the space bar. Make something very simple that responds to user input before doing anything more complex.
Create a screen video of your reactive scene in action. Please submit it with your code or put it on Google drive with a link to it on classroom.
These are questions you should be able to answer and may be similar to questions on a quiz or final exam. If you have any questions about them, send your answer to the lab instructor along with any questions in return for some feedback.
- How did inheritance help you on this project?
- What is the difference between the position anchor point and the rotational anchor point?
- What is the difference between an object field and a local variable in a function?
- What is your favorite rotating amusement ride?
Extensions are your opportunity to customize your project, learn something else of interest to you, and improve your grade. The following are some suggested extensions, but you are free to choose your own.
Due to the switch to remote learning, extensions are no longer a graded part of CS 152 for the rest of the semester. They are things you can do on your own to learn more and become better at CS, especially if you are interested in taking more CS courses.
- Create a second rotating object that consists of multiple graphics objects.
- Create more elaborate spaces with more complex interaction and capture interesting additional simulation videos. Need inspiration? Check out this project.
- Create more shape classes, or more complex shapes, and show that they collide and simulate appropriately.
- This simulation does not take into account masses. A challenging extension would be to modify the collision code so that when two things collide the velocity changes take into account the masses. (Conservation of momentum, energy, and geometry. Feel free to approximate.)
- Create a separate scene like putt-putt golf and let the user shoot the golf ball (see the project linked above).
Submit your code
Turn in your code (all files ending with .py) by putting it in a directory in the Courses server. On the Courses server, you should have access to a directory called CS152, and within that, a directory with your user name. Within this directory is a directory named Private. Files that you put into that private directory you can edit, read, and write, and the professor can edit, read, and write, but no one else. To hand in your code and other materials, create a new directory, such as project6, and then copy your code into the project directory for that week. Please submit only code that you want to be graded.
When submitting your code, double check the following.
- Is your name at the top of each code file?
- Does every function have a comment or docstring specifying what it does?
- Is your handin project directory inside your Private folder on Courses?