#__________________Cannonball with simple graphics______________________________
#5.py
 
#Here is the code from 4.py of the last lecture. We modified it VERY slightly by adding a graphics
# window and a circle to represent the CB.
 
''' Look for lines flagged with "##".
   These are the only lines that were changed  or added.
 
    In particular, look at how we passed the graphics window to the constructor so that
    the projectile class has access to a window to draw in. Look at how we defined instance
    variables and got a circle object for this class.
 
    NOTE: In this example we gave the Projectile class the ability to do the graphing.
 
    Sometimes you may not want to do that. You may want to keep all the graphics outside
    such a class. If we wanted  to take this route in this example, we can simple define the
    circle object in the main program and then use "move" inside the while loop to draw
    cb once we have its position.
 
    DIMENSIONING: In this example, its possible that the cb flies out of the window. It means
    velocity and/or angle are very high and our window was not big enough. To solve this
    problem, you can
 
       (a) run the loop once without graphics and get the max height and max distance, or
       (b) use calculus to get max height and max distance.
 
    Once you have the proper dimensions (max height, max distance) for any given input parameters,
    you can create a graphics window to handle that size and then run the simulation again, but
    this time graph the cb.
 
'''
 
# HW: How would you make the graphics work for any projectile input parameters? 
 
 
from graphics import *                         ##
 
from math import sin, cos, radians
 
def wait():                     ##
    x = input()                 ##
 
class Projectile:
 
    def __init__(self, angle, velocity, height, w):             ##
        self.xp = 0
        self.yp = 0                         #change from 0 to height if you don't want to start at 0
        theta = radians(angle) 
        self.xv = velocity * cos(theta)
        self.yv = velocity * sin(theta)
        self.win = w                                                            ##
        self.c = Circle(Point(self.xp,self.yp),30)               ##
        self.c.draw(self.win)                                              ##            
        self.c.setFill("red")                                                ##
 
 
 
    def position_update(self, t):
 
        oldx = self.xp                ##
        oldy = self.yp                ##
 
        self.xp = self.xp + t*self.xv
 
        yv_new = self.yv - 9.8*t
 
        average_velocity = (self.yv + yv_new)/2
 
        self.yp = self.yp + t * average_velocity
 
        self.yv = yv_new
 
        self.c.move(self.xp-oldx,self.yp-oldy)                 ##
 
 
 
    def height(self):
         return(self.yp)
 
    def distance(self):
        return(self.xp)
 
#_____________ code below is not in the class ________________________________
 
def get_input_values():
        a = eval(input("Enter launch angle (degrees): "))
        v     = eval(input("Enter initial velocity (meters/sec): "))
        h      = eval(input("Enter initial height   (meters): "))
        t = eval(input("Enter small time-interval between position updates of cb: "))
        return(a,v,h,t)
 
#_______________________________________________________________________
# Here is a main program that uses the above class definition for projectiles
 
# Note that you can add as many methods as you need, and you can make them as
# complex as you need
 
def main():
 
    win = GraphWin("Cannonball trajectory",800,800)           ##
    win.setCoords(-50,-50,4050,8050)                                    ##
 
 
    angle, vel, h0, t = get_input_values()
 
    cb = Projectile(angle, vel, h0,win)      
 
    while (cb.height() >= 0): 
 
        cb.position_update(t)                
 
        print ("CB is now {0:0.2f} meters high and is {1:0.2f} meters away.".
               format(cb.height(),cb.distance()) )
 
        wait()
 
    win.close() 
 
main()
 
