$25
It consists of three interrelated parts that we will use to build up an Angry Birds simulation. Lab 9 should give you at least some practice and insight with
classes.
Part 1: CS 1 Birds
Computer games such as Angry Birds are based on simulating the basic rules of physics, or at least some rough approximation to these rules. These simulations involve a simple basic loop where in each iteration
1. The positions and sometimes the velocities of moving objects are both updated by a small amount.
2. Objects are checked for collisions, and changes are made to the simulation based on these collisions.
While never 100% accurate, realistic looking results and physically useful predictions (for scienti?c simulations) can be obtained by making sure the changes in each loop iteration are small.
We will apply this idea to a simple version of angry birds called CS 1 Birds. Along the way you will get practice writing classes and using dictionaries.
The simulation occurs over a rectangular region whose lower left and upper right corners are locations (0; 0) and (1000; 1000). Take note of the playing ?eld. This is different than we used for the pokemon homeworks. It now corresponds to the upper right quadrant of a graph. The simulation will include birds, pigs, and barriers all represented by circles. Bird, pig and barrier positions are in oats and correspond to points in cartesian or (x,y) coordinates. The pigs and barriers are stationary, but the birds will move along a line (no gravity!). Each bird will move in
turn, slowing down or stopping when it strikes a pig or a barrier, and stopping when it becomes too slow or when any part of it goes outside the game rectangle. When a bird strikes a pig, the pig will \pop" and disappear from the simulation. When it strikes a barrier, the barrier will take damage, but may or may not disappear depending on its initial strength and how many times it has been hit. The simulation ends when either all pigs have been \popped" or when all birds have stopped, whichever occurs ?rst.
We can summarize the possible behaviors as follows:
• Bird
1. y - Update the current position by dx and dy
2. collide with a pig - Decrease x velocity by a factor of 2
3. collide with a barrier - Total speed becomes 0
4. stops - total speed becomes < 6, or the bird circle leaves the ?eld.
• Pig
1. bird collides with it - Pops!
• Barrier
1. collide with a bird - Takes mass times speed squared damage. Do not let the strength go below 0
2. crumbles if strength is reduced to 0
Input Files
The input for the exercise will be stored in a single json ?le. The ?le encodes a dictionary of entries for "birds", "pigs", and "barriers". Where each entry is an array of the correct type, birds, pigs, or barriers, and where the elements of each array are a dictionaries of attributes for an individual. This sounds complicated, but it is not. The code below reads in the ?le and then prints out the information for the birds. You can get the information for the pigs by replacing the key "birds" with "pigs" and can get the information on the barriers by using the key "barriers".
You only need to read the ?le once.
A simple program to illustrate the use of json and dictionaries for using the pig, bird and barrier json data.
import json
filename = input("Enter the name of the data file = ")
print(filename)
f = open(filename.strip())
data = f.read().strip()
dictionary = json.loads(data)
print()
print("{} contains the following birds:".format(filename))
for bird in dictionary[ birds ]:
print("{}:\n{}".format(bird[ name ], bird))
Running this with scenario4.json gives the following output:
scenario4.json contains the following birds:
Tweety:
{ y0 : 12, name : Tweety , mass : 0.5, dy : 5.1, x0 : 10, dx : 4.2, radius : 9}
Hawk:
{ y0 : 800, name : Hawk , mass : 10.0, dy : -6, x0 : 100, dx : 8, radius : 20}
Eddie:
{ y0 : 300, name : Eddie , mass : 15, dy : 5.5, x0 : 200, dx : 3.3, radius : 19}
Super Chicken:
{ y0 : 90, name : Super Chicken , mass : 8, dy : 8.2, x0 : 400, dx : 8, radius : 19}
Humming:
{ y0 : 400, name : Humming , mass : 0.1, dy : 4.3, x0 : 80, dx : 4.3, radius : 6.1}
2
We recommend that you run this and play with it to see how it works. You may liberally copy from this in generating your own program.
Each entry in a bird array will have entries for "name", "mass", "radius", "x0", "y0", "dx" and "dy", where the entry for name is a string giving the name of the bird, mass is the bird's mass (used to calculate damage to barriers), x0 and y0 specify the bird's initial position (center of the circle), radius is the bird's radius, and dx and dy specify how far the bird moves in each time step. All values other than name are oats.
The entries in the pig array will have a similar format with entries for "name", "radius", "xc", and "yc", where name is a string giving the name of the pig, xc and yc specify the pig's center position, and radius is the pig's radius. All values other than name are oats.
And ?nally each entry of the barrier array will have entries for "name", "strength", "radius", "xc", and "yc", where name is a string giving the name of the structure, strength is a measure of how much damage it can take before being destroyed, xc and yc specify the structure's position (center of the circle), and radius is the structures radius. All values other than name are oats.
Simulation and Output
At the start of the simulation ask for the scenario ?le, read in the data, and use it to create lists of bird, pig and barrier objects. Note that these must be objects, not just the arrays form the input ?le. Write classes for birds, pigs and barriers; and use the data from the ?le to initialize objects of the classes. You may assume all input is properly formatted, all birds are entirely inside the bounding rectangle at the start, and none of the birds or pigs intersect each other at the start.
You may also assume that each bird's movement (dx; dy) is much smaller than the radii of the pigs and barriers so that you do not need to worry about a bird completely passing through a pig or a barrier in one time step.
After processing the ?le your program should have three lists, one of Bird objects, one of Pig objects and one of Barrier objects. At this point print out the number of birds, the name of each bird and its starting center location, the number of pigs, and the name of each pig and its center location, the number of barriers, the name of each barrier and its center location. The order should be the order the birds/pigs/barriers were read in. Follow the format of the output examples we
have provided in the separate ?les.
The simulation starts at time 0 and runs until either there are no more pigs, or until all birds have left the ?eld or stopped. All position output should be accurate to 1 decimal place. Please follow the output precisely as shown | it should be fairly straightforward In each time step:
1. Only one bird will be on the ?eld at a time. If there is no bird currently on the ?eld, choose the next bird and enter it into play. Print a message. For example,
Time 0: Tweety starts at (10.0,12.0)
2. Increment the time counter
3. Move the current bird by its dx and dy values. (To be clear, the ?rst bird's ?rst step will be
at time 1.)
4. Check to see if the bird's circle intersects the circle of a pig that has not yet been popped.
(Intersection occurs when the distance between the two circle centers is less than or equal to
the sum of the two circle radii.) If so,
3
(a) Print one line giving the time, the name of the bird, the position of the bird, and the
name of the pig. For example,
Time 25: Freddie at (15.3,19.1) pops Wilbur
(b) \Pop" the pig. One easy thing to do is to remove the pig from the list of pigs.
(c) Decrease the dx value (the x speed ONLY) of the bird by 50% (Throughout your code
you might want to make sure that Python knows that the speed is a oat...) Note that
this changes the direction the bird is heading. Print one more line,
Time 25: Freddie at (15.3,19.1) has (dx,dy) = (4.5,5.0)
(d) The data we provide is arranged such that only one pig will be struck at a given time
step. Once you have popped the ?rst pig, you can stop reviewing the rest of the pig list.
5. Check to see if the bird's circle intersects the circle of a barrier that has not yet crumbled.
(Again, intersection occurs when the distance between the two circle centers is less than or
equal to the sum of the two circle radii.) If so,
(a) Print one line giving the time, the name of the bird, the position of the bird, the name
of the barrier and the barrier's strength after the collision. Note that the barrier takes
the bird's mass times its speed squared in damage when hit, but be sure to not let the
barrier go below 0 strength.
Time 25: Freddie at (15.3,19.1) hits Picket, Strength 0.0
(b) If the barrier's strength is dropped to 0, the barrier crumbles and an additional message
should be printed
Time 25: Picket crumbles
(c) Decrease the dx and dy of the bird to 0. Print one more line,
Time 25: Freddie at (15.3,19.1) has (dx,dy) = (0.0,0.0)
(d) Again, the data we provide is arranged such that only one barrier will be struck at a
given time step. Once you have struck the ?rst barrier, you can stop reviewing the rest
of the barrier list.
6. Check two more things in the following order:
(a) If the bird reaches a speed below MINSPEED==6, stop moving the bird, remove it from
the simulation, and move on to the next bird. (Note that the speed is
p
dx2 + dy2.)
When this occurs output the time, the name, the location and the speed the bird, e.g.
Time 281: Super Chicken at (668.0,364.7) with speed 4.6 stops
(b) If any part of the bird's circle has gone outside the rectangle (its x position minus its
radius is less than 0 or its x position plus its radius is greater than 1000, or its y position
minus its radius is less than 0 or its y position plus its radius is greater than 1000) the
bird has left the playing ?eld. When this occurs, output the time, the name and location
of the bird. For example,
Time 25: Big-Bird at (975.0,234.0) has left the game
When a bird stops or leaves the ?eld and there are more birds and more pigs left, start the
next bird immediately at its initial location. Output something like
Time 25: Daffy starts at (123.7,88.5)
4
Just to be clear, the time Da?y starts is the same time the previous bird (Big-Bird) leaves
the board. Da?y does not move until the next time, and therefore no tests against pigs or
barriers are needed.
7. If all pigs are popped then output a message saying something like
Time 33: All pigs are popped. The birds win!
and stop the game.
8. Otherwise, if there are no more birds, output a message with the names of the surviving pigs
(ordered by their order of input). For example,
Time 33: No more birds. The pigs win!
Remaining pigs:
Porky
Brick
and stop the game.
The logic of this is a bit complicated, with a number of cases to check, so implement it carefully!
Use of Classes and Functions
You must use at least three classes, one for a pig, one for a bird, and one for a barrier. The pig
class is the smallest and can be as simple as:
class Pig(object):
def __init__( self, n, x0, y0, r0 ):
self.name = n
self.x = x0
self.y = y0
self.radius = r0
although we added other functionality to our code to make some of the reporting and printing
easier. You are welcome to use this part of the pig de?nition in your code. We will not consider it
in our code comparison. The barriers and birds are increasingly more complicated and we suggest
that in particular you add a lot of functionality into the Bird class to make the simulation easier.
Test Cases
This is the longest and one of the most complicated assignments we have given so far. The program
match portion (autograding) will be worth 110 of the 140 points available for the homework, and
we want you to have an opportunity to get substantial parital credit even if you are having trouble
completing all three classes correctly. To achieve this, we will be providing you with four scenarios
of varying di?culty:
• Scenario 1 (example scenario1.json) will be worth 20 points. The scenario will include birds
and barriers, but no pigs and should terminate immediately after reporting the ?le contents
without executing the simulation loop at all and without having to move the birds.
5
• Scenario 2 (example scenario1.json) will be worth 30 points and will not include any
collisions. You will need to read in and report on the birds, pigs and barriers, but when
the simulation starts the birds will y without hitting anything to the end of the board.
Obviously, the pigs will win.
• Scenario 3 (example scenario3.json), worth 35 points, will add collisions between birds and
pigs, but not striking of barriers by birds.
• Scenario 4 (example scenario4.json), worth 25 points, will also include birds striking bar-
riers.
Thus, if you just implement the code for scenarios 1 and 2 you can earn up to 45% of the autograde
points. Adding in collisions with pigs can get you all the way up to 77% of the autograded points.
Two important notes:
1. Some of the tests we use on Submitty will be di?erent from these example ?les.
2. Do not ask for help on a later scenario until you can prove that your code works for an
earlier scenario. In other words, get Scenario 1 working before you even consider moving on
to Scenario 2, and get Scenario 2 working before you even consider Scenario 3
Module Organization and Submission Instructions
Please follow these instructions carefully: Your program should be split across four ?les,
Pig.py, Bird.py, Barrier.py and hw7.py. hw7.py should start with
from Pig import *
from Bird import *
from Barrier import *
and include the rest of your code. All code should follow our coding guidelines. If you need a
refresher, look at HW6.
We recommend that when you program your solution you start simple and build up:
1. Create the three class ?les, Bird.py, Pig.py, and Barrier.py ?les and write initializers for
them.
2. Write the code to ask for the ?lename, create the lists, and report on the initial list contents.
3. Test against the ?rst scenario to make sure your input is working correctly. At this point you
have earned 20 of 110 points.
4. Add ying to the bird and write the simulation loop without worrying about collisions
5. Test and verify that you correctly solve the second scenario. At this point you have
earned 50 of the 110 autograding points. Save this ?le as a backup.
6. Without breaking scenario 2, add in code to let birds collide with pigs.
7. Test and verify that you correctly solve the ?rst and second scenarios. At this point you
have earned 85 of the 110 autograding points. Save this ?le as a backup.
8. Without breaking scenario 3, add in code to let birds collide with barriers.
9. Test and verify that you correctly solve the ?rst, second and third scenarios. At this point
you have earned 110 of the 110 autograding points. Save this ?le as a backup.
The output from the scenarios and the scenario input ?les can all be found in hw07files.zip. In
order to submit your solution: You will need to submit your homework by dragging all four of
the ?les Bird.py, Pig.py, Barrier.py and hw7.py into the Submitty submission block. Be careful
to name them correctly.
6