Saint Louis University |
Computer Science 1300
|
Computer Science Department |
The goal of this assignment is to create, document and implement a new class, Ball, which simulates the movement of a ball under the effects of gravity. For this assignment, we will provide all of the other portions of the code, including a driver for gathering input from the user as well as all of the necessary graphics for visualizing the simulation. However you must define and implement the Ball class properly for the simulation to be complete.
For this assignment you must work individually in regard to the design and implementation of your project.
Please make sure you adhere to the policies on academic integrity in this regard.
Your main task is to implement and document a Ball class, described briefly with the following class diagram:
Our software will explicitly rely on each of the above methods, so you must be careful to accurately reflect the given specifications. For most, the desired behavior should be self-evident from the method names. The advance method warrants further explanation. Your Ball objects will live in a World that will have been created by our part of the software. The World is built as an extension of a Canvas but has additional code which acts as a clock in some sense. For each tick of the clock, the world will call the method advance method for each ball in the world, sending a reference to the world as a parameter. The behavior of the method for a given object should be to update the state of that particular object for one simulated timestep. So your entire focus is thinking about a single Ball, and how its position and velocity attributes change with a tick of the (virtual) clock.
For the sake of completeness, we next review some elementary physics to explain the desired behavior.
position
In real life, the position would be measured in terms of a unit of of distance such as a meter; here we represent the position in terms of pixels or fractions thereof. The position of the ball is relative to the world's coordinate system, namely with the positive Y-axis oriented downward. For simplicity, we suggest that you represent the position vector as two separate values, separately representing the X- and Y-components of the position (though it would be possible to define a vector class if we wished).
velocity
A velocity is not simply a representation speed, but also of direction of motion. Therefore, a velocity is also represented by a pair of coordinates. In the real world, a velocity might be measured in units such as meters per second (m/s); in our world, we will measure velocity in terms of pixels per tick. Therefore, if a ball had a constant velocity of
gravity
By the law of inertia, in the absence of any outside forces the velocity would remain unchanged. Yet gravity is such an outside force. At each clock tick, the gravity does not directly effect the position of a ball, but it will directly effect the velocity of the ball.
In general, such a force should also be represented as a vector, and thus have separate X- and Y-coordinates. For simplicity, we assume that gravity in our world is aligned with the Y-axis so that there is only one coordinate. A positive value for the gravity means that balls are being pulled downward (i.e., along the positive Y-axis); in contrast, a negative gravity value would be interpreted as balls being pulled upward.
As for gravity, we felt that it was a more natural model to keep gravity as an attribute of the world rather than of an individual ball. Yet for the ball to be able to update itself, it must be aware of the gravity setting. For this reason, notice that the advance(world) method takes the world as a parameter. Though you do not need to fully understand the World class, what is important is that you may call world.getGravity() to get the current setting.
Your only responsibility is to create a file Ball.py with an implementation of a Ball class. To help you test your class, we are providing two scripts. You do not need to read any of our source code (in fact, we suggest you do not read these scripts), but you will need to start the Python interpreter by executing one of those scripts (rather than executing Ball.py).
The first is a very basic text-only driver (SimulationText.py) that provide a simulation of the first 10 steps of a single ball. For example, if picking an initial position of
After step 1 the ball is at (105.00, 44.00) After step 2 the ball is at (110.00, 40.00) After step 3 the ball is at (115.00, 38.00) After step 4 the ball is at (120.00, 38.00) After step 5 the ball is at (125.00, 40.00) After step 6 the ball is at (130.00, 44.00) After step 7 the ball is at (135.00, 50.00) After step 8 the ball is at (140.00, 58.00) After step 9 the ball is at (145.00, 68.00) After step 10 the ball is at (150.00, 80.00)
Note: If you don't see why these are the expected values, then it is important that you first review the model and simulate the model manually; there is no point to start coding. Also, there is a slight subtlety in the above nubmers in that we are doing a discrete simulation of what should be a continuous process. So there is a question when updating the position and veloicty of the ball during a timestep of whether the position is updated with the new velocity or the old velocity. Either is a reasonable simulation but the above numbers were generated presuming that the position is updated with the (existing) velocity and then gravity is applied to velocity.
For a bit more fun, we provide a graphical driver (SimulationGraphical.py). This program starts with a series of questions to define the characteristics of the World. After setting up the world, the driver prompts you to introduce one or more balls with a given set of initial characteristics. It then simulates the motion of these balls so long as they remain in the visible portion of the world. Once the balls leave the world they are destroyed and the driver will prompt you to start again.
You should note that our driver intentionally suggests default responses for each question posed, and you may signify that you are willing to accept the default by simply pressing return. This should make it much easier for you to repeat certain tests by a series of accepted defaults.
Notice also that the driver allows you to add a sequence of identical balls to the screen (in a staggered fashion) rather than simply one ball at a time. By using a sequence of balls, you can get a more interesting visual trail of the traveling balls, as shown in the following diagram
You will need to have our two drivers (SimulationText.py, SimulationGraphics.py) and your Ball.py in the same folder.
You may wish to tackle the assignment in stages, making sure to succeed in each stage before continuing to the next.
You must make sure that you create a file Ball.py which defines the Ball class as described precisely in the earlier diagram. Otherwise, either of our simultations will likely complain when trying to import the Ball class.
If you properly set the instance variables from within the constructor and implement the "get" methods, then our simluations will at least demonstrate the existance of the Ball (though without it advance from timestep to timestep).
Start to implement the advance routine, ignoring gravity for the time being. You should use the velocity to control the movement of the ball's position.
Finally, take gravity into account and put everything together.
This project must be submitted electronically using our department's git repository. More specifically, we have created a folder named program04 in your repositiory and you should place the following two files within:
Ball.py: this file should contain all of your source code.
readme.txt: for every project a "readme" text file must be submitted containing:
See as well a discussion of the late policy for programming assignments.
The assignment is worth 40 points, approprtioned as follows:
We will award 4 additional points to students who successfully meet the following challenge.
The interface we provided also allows you to add a Star to the world. Adjust your advance routine so that the ball is properly affected by the gravity of the Star.
Physics 102:
Incorporating the gravity of a star is more complicated than the gravity of a world, for two reasons. Both the strength of the gravity and the direction of the force depend on the relative position of the ball and the star. For comparison, the gravity of the world was assumed to be a constant force, aligned along the Y-axis, thus of the form (0,g) for some value g. The gravity between the star and a ball should be a vector pointing from the ball towards the star. The magnitude of that force should depending upon the mass of the star and the distance between the center of the ball and the center of the star. Specifically, the magnitude of the force equals the star's mass divided by the square of the distance between the star and ball's centers.
Coding Issues:
There are some additional issues to cope with, though this is extra credit after all. For simplicity, at most one star can exist in the world at any given time. You can query the world to return this star to you through the method
star = world.getStar() if star: // star exists. Add your code here to adapt. else: // no star. do the original math
A star's position and mass can be queried through the use of methods getPositionX(), getPositionY() and getMass().
You may find need to compute a square root. A function for computing a square root is included in the math library of Python. You may use it by stating
If you have everything implemented correctly and use the default parameters for the extra credit, you will get an orbit as shown in the following figure