#Dan McGovern and Brian Cohen
#Special Thanks to Sajjan Mehta and Andrew Eshelman
#Recitation 1

from pylab import *
from visual import *
from random import *

print " "

print "Good afternoon, Cadette,"

print"	You are aboard the most advanced intergalactic fighter star ship, the" 
print "SS Ess Ess. The Ess Ess is equipped with state of the art technology."
print "It's capabilities include"
print " "
print "an Electro-Magnetic Force Field (S-button)"
print "a Laser Cannon (Space Bar)"
print "a Teleportation Device (T-button)"
print "a Liquid Hydrogen Thruster (Up)"
print "Deceleration Rocket Packs (Down)"
print "and Rotational Thrusters (Left/Right)"
print " "
print "Your mission, if you choose to accept it, is to navigate the Goldberg"
print "belt--the most dangerous asteroid field in our galaxy (named"
print 'for the famous astrophysicist "Dangerous Goldberg").'
print " "
print "Godspeed, Cadette.  Show those commie asteroids what-for."


'''
Hey Travis, this game is going to blow your mind.  Here are the controls

Left/Right:Rotate ship clockwise/counterclockwise
Up: Accelerate
Down: Decelerate
T: Teleport to random position on screen
S: Employ Shield
Space: Shoot

We conserved momentum and mass in the destruction of asteroids and employed non-relativistic kinematic equations to update the positions of objects.
'''

theta=(pi/2) #initial angle of ship
dtheta=(pi/24) #amount ship turns per key stroke
scene.autoscale=False
scene.range=100 #size of window
ship = pyramid(pos=(0,0,0), size=(12,6,0), m=50) #your sweet ride--an interstellar asteroid destroyer
ship.rotate(angle=theta, axis=(0,0,1))
asteroid=[]
arad= 8 #default asteroid radius
aspeedmax= 30 # default asteroid speed
tele=5 #inital amount of teleports
shot=sphere(pos=(200,200,0), radius=1, color=color.yellow,p=vector(0,0,0)) #the bullet you fire to destroy asteroids
shield = ring(pos=(200,200,0), axis=(0,0,1), radius=10, thickness=1, color=color.blue) #the shield you can use as defence against bloodthirsty asteroids
shot.m=0 #your bullets are massless
score=0 #initial score
alive=3 #inital number of lives
protect=0 #a number used to regualte shield usage
charge=3 #how many volts require to employ shield
lastextralifescore=0 #number used to regulate winning more lives
score_label = label(pos = (75, 90, 0), color = color.white, height = 11,
                    linecolor = color.black, text = 'Score: '+ str(score)) #score indicator
tele_label = label(pos = (78, 80, 0), color = color.white, height = 11,
                    linecolor = color.black, text = 'Teleports: '+ str(tele))#teleport indicator
alive_label = label(pos = (73, 70, 0), color = color.white, height = 11,
                    linecolor = color.black, text = 'Lives: '+ str(alive))#life indicator
shield_label = label(pos = (73, 60, 0), color = color.white, height = 11,
                    linecolor = color.black, text = 'Shield: Charged')#shield indicator


#2 is smallest radius for asteriod pieces.
ship.p=vector(0,0,0) #start at rest
t=0 #inital time
dt = 0.01 #time step

def newasteroid(): #subroutine used to put asteroids into the system
    global arad, scene 
    xory=random() #how we determine which side of the scene the asteroid will enter
    aspeed=aspeedmax*random() #randomized speed of new asteroid
    aangle=2*pi*random() #randomized direction of new asteroid
    if xory<.5: #starts half the asteroids on the left edge of the scene
	asteroid.append(sphere(
		pos=(-100+arad,2*100*random()-100,0),
		radius=arad,
		m=30,
		color=(.4+.2*random(),.4+.2*random(),.4+.2*random()),
		p=vector(aspeed*cos(aangle),aspeed*sin(aangle),0)))
    else: #starts half the asteroids from the bottom edge of the scene
	asteroid.append(sphere(m=30, pos=(2*100*random()-100,-100+arad,0), radius=arad, color=(.4+.2*random(),.4+.2*random(),.4+.2*random()),p=vector(aspeed*cos(aangle),aspeed*sin(aangle),0)))

def breakasteroid(i): #subroutine used to break apart asteroids
	global scene, score
	#asteroid[i].visible=0
	#asteroid = asteroid[0:i] + asteroid[i+1:len(asteroid)]
	shot.pos=(200,200,0) #shot is "destroyed" in collision--stowed away off screen
	shot.p=vector(0,0,0) #shot is set at rest
	ast0=asteroid[i] #reassigns colliding asteroid
	rang = 2*pi*random() #randomized angle that asteroid pieces fly off
	rmag = 10*random()
	score +=100 #score 100 points for destroying an asteroid
	score_label.text = 'Score: '+ str(score)

	ast1 =  sphere(
		pos=ast0.pos,
		radius=ast0.radius/sqrt(2),
		m=ast0.m/2,
		color=ast0.color,
		p=vector(rmag*cos(rang)+ast0.p.x,rmag*sin(rang)+ast0.p.y,0))
	ast2 =  sphere(
		pos=ast0.pos,
		radius=ast0.radius/sqrt(2),
		m=ast0.m/2,
		color=ast0.color,
		p=vector(-rmag*cos(rang)+ast0.p.x,-rmag*sin(rang)+ast0.p.y,0))
	ast0.visible=0
	del ast0
	if ast1.radius>3:
		asteroid[i]=ast1
	else:
		#asteroid[i].visible=0
		del asteroid[i]
		ast1.visible=0
		del ast1
	if ast2.radius>3:
		asteroid.append(ast2)
	else:
		ast2.visible=0
		del ast2

def explosion(r):
	t = 0
	dt = 0.01
	explode = sphere(pos=(r), radius=0, color=color.red)
	while t<0.5:
		rate(1/dt)
		t +=dt
	while t<1.2:
		rate(1/dt)
		t += dt
		explode.radius += 0.7
	while t>1.2:
		rate(1/dt)
		t += dt
		explode.radius -= 0.7
		if t>1.86:
			explode.visible=0
			break

def checkUserInput(): #subroutibe that inputs data with keystrokes
    global scene, theta, dtheta, paddle, pause, key2, tele, ship, protect, charge
    
    if scene.kb.keys:
        key = scene.kb.getkey()
	if key == 'up'  or key=='ctrl+up':
            ship.p+=vector(13*cos(theta),13*sin(theta),0)
	if key == 'down'  or key=='ctrl+down':
            #ship.p+=vector(-7.5*cos(theta),-7.5*sin(theta),0)
	    ship.p=.92*ship.p
        if key == 'left' or key=='ctrl+left':
            theta += dtheta
            ship.rotate(angle = dtheta, axis=vector(0, 0, 1))
        if key == 'right' or key=='ctrl+right':
            theta -= dtheta
            ship.rotate(angle = -dtheta, axis=vector(0, 0, 1))
	if key == 's' and charge>2:
	    protect +=0.6
	    charge =0
	    shield.pos=(ship.pos.x+3*cos(theta),ship.pos.y+6*sin(theta), ship.pos.z)
	    shield_label.text = 'Shield: Charging'
	if key == ' ':
	    shot.pos=ship.pos
	    shot.m=5
	    shot.p=vector(50*cos(theta),50*sin(theta),0)
	if key == 't' and tele>0:
	    tele-=1
	    ship.pos.x=2*100*random()-100
	    ship.pos.y=2*100*random()-100
	    tele_label.text = 'Teleports: '+ str(tele)
	    

while alive>0: #main loop in which posisitions are updated and collisions are checked for.
	if t<0.01:
		newasteroid()
	t+=dt
	checkUserInput()
	#rate=1/dt
	ship.pos+=dt*ship.p/ship.m
	if charge >2:
		shield_label.text = 'Shield: Charged'
	if protect>0.3 and charge <2:
		shield.pos =(ship.pos.x+3*cos(theta),ship.pos.y+6*sin(theta), ship.pos.z)
		for i in xrange(len(asteroid)):
			if abs(asteroid[i].pos-(ship.pos.x+3*cos(theta),ship.pos.y+6*sin(theta), ship.pos.z))<(asteroid[i].radius+shield.radius):
				asteroid[i].visible=0
				asteroid = asteroid[0:i] + asteroid[i+1:len(asteroid)]
				protect=0
				break
	else:
		shield.pos=(200,200,0)
	if protect<0.3 and shield.pos.x<150:
		shield.pos=(200,200,0)
	if shot.m>0:
		shot.pos+=dt*shot.p/shot.m
	for i in xrange(len(asteroid)):
		asteroid[i].pos+=dt*asteroid[i].p/asteroid[i].m
		if abs(asteroid[i].x)>100:
			asteroid[i].pos.x=-asteroid[i].pos.x
		if abs(asteroid[i].y)>100:
			asteroid[i].pos.y=-asteroid[i].pos.y
		if abs(asteroid[i].pos-shot.pos)<asteroid[i].radius:
			#asteroid[i].visible=0
			#asteroid = asteroid[0:i] + asteroid[i+1:len(asteroid)]
			breakasteroid(i)
			break
		if abs(asteroid[i].pos-(ship.pos.x+3*cos(theta),ship.pos.y+6*sin(theta), ship.pos.z))<asteroid[i].radius+8:
			asteroid[i].visible=0
			asteroid = asteroid[0:i] + asteroid[i+1:len(asteroid)]
			explosion((ship.pos.x+3*cos(theta),ship.pos.y+6*sin(theta), ship.pos.z))
			alive+= -1
			alive_label.text = 'Lives: '+ str(alive)
			ship.pos=vector(0,0,0)
			ship.p=vector(0,0,0)
			break
			
	if abs(ship.pos.x)>100:
		ship.pos.x=-ship.pos.x
	if abs(ship.pos.y)>100:
		ship.pos.y=-ship.pos.y
	if abs(shot.pos.x)>100:
		shot.pos.x=-shot.pos.x
	if abs(shot.pos.y)>100:
		shot.pos.y=-shot.pos.y
	if score%1000==0 and score >0 and score!=lastextralifescore:
		alive+= 1
		lastextralifescore=score
		alive_label.text = 'Lives: '+ str(alive)
		tele+= 1
		tele_label.text = 'Teleports: '+ str(tele)
	if t>160:
		if protect>0.3:
			protect -=0.2
		if charge<3:
			charge +=1
		t=0
dead_label = label(pos = (-5, 0, 0), color = color.white, height = 11,
                    linecolor = color.red, text = 'You dead.')
