"""
Ludum Dare 21 48 Hour Competition Entry

(c) 2011 - David Sims - @TheDaveSims - david dot sims at digitalsideburns dot com

This code is awful. Don't use it for anything. Seriously. Awful.

Requires Python (http://www.python.org) and Pyglet (http://www.pyglet.org/download.html) to run.

"""

import pyglet,math,random
from pyglet.window import mouse

pyglet.resource.path = ['resources']
pyglet.resource.reindex()

window = pyglet.window.Window(800,600)
window.set_caption("Harvest - LD21 LD48 - dave84")

drawMainScreen = True
canBeginLevel = False
solarSystemCount = 1
totalHumanCount = 0

pickupsound = pyglet.resource.media('pickup.wav', streaming=False)
deadsound = pyglet.resource.media('explosion.wav',streaming=False)
portalopen = pyglet.resource.media('portalopen.wav',streaming=False)
enterportal = pyglet.resource.media('enterportal.wav',streaming=False)


logo = pyglet.resource.image('logo.png')
logo.anchor_x = logo.width//2
logo.anchor_y = logo.height//2
logosprite = pyglet.sprite.Sprite(logo, window.width//2, window.height//2)

bg = pyglet.resource.image('bg.png')
bg.anchor_x = bg.width//2
bg.anchor_y = bg.height//2
bgsprite = pyglet.sprite.Sprite(bg, window.width//2, window.height//2)

highscore = 0

class Ship:
    x = 0
    y = 0
    r = 0
    prevX = 0
    prevY = 0
    xVel = 0
    yVel = 0
    shipsprite = None
    exhaustsprite = None
    timer = 0.0
    def __init__(self,x,y,r):
        self.x = x
        self.prevX = x
        self.prevY = y
        self.y = y
        self.r = r
        xVel = 0.0
        yVel = 0.0
        texture = pyglet.resource.image('ship.png')
        texture.anchor_x = texture.width//2
        texture.anchor_y = texture.height//2
        texture2 = pyglet.resource.image('exhaust.png')
        texture2.anchor_x = texture2.width//2
        texture2.anchor_y = texture2.height//2
        
        self.shipsprite = pyglet.sprite.Sprite(texture, self.x, self.y)
        self.exhaustsprite = pyglet.sprite.Sprite(texture2,self.x,self.y)

    def draw(self):
        if self.timer > 0:
            self.exhaustsprite.draw()
        self.shipsprite.draw()

    def update(self,dt):
        if(self.timer > 0):
            self.timer -= dt
        deltax = self.x - self.prevX
        deltay = self.y - self.prevY

        angle_rad = math.atan2(deltay,deltax)
        angle_deg = angle_rad*180.0/math.pi
        self.shipsprite.rotation = 90 - angle_deg
        self.exhaustsprite.rotation = 90 - angle_deg
        for planet in planets:
            planet.addGravity(self)
        self.prevX = self.x
        self.prevY = self.y
        self.x += (self.xVel * dt)/2000
        self.y += (self.yVel * dt)/2000
        self.shipsprite.x = self.x
        self.shipsprite.y = self.y
        self.exhaustsprite.x = self.x
        self.exhaustsprite.y = self.y
        if self.x < (0 - self.r*2):
            self.x = window.width + self.r*2
        if self.y < (0 - self.r*2):
            self.y = window.height + self.r*2
        if self.x > (window.width + self.r*2):
            self.x = 0 - self.r*2
        if self.y > (window.height + self.r*2):
            self.y = 0 - self.r*2

class Person:
    x = 0
    y = 0
    r = 2
    def __init__(self,x,y):
        self.x = x
        self.y = y


class Planet:
    x = 0
    y = 0
    r = 0
    planetsprite = None
    def __init__(self,initX,initY,initR):
        self.x=int(initX)
        self.y=int(initY)
        self.r=int(initR)
        self.rotation_speed = random.choice([-5,0,5])
        texture = pyglet.resource.image('planet.png')
        texture.anchor_x = texture.width//2
        texture.anchor_y = texture.height//2
        self.planetsprite = pyglet.sprite.Sprite(texture, self.x, self.y)
        self.planetsprite.scale = float(self.r*2)/389


    def update(self,dt):
        self.planetsprite.rotation += self.rotation_speed  * dt
        
    def draw(self):
        self.planetsprite.draw()
        
    def addGravity(self,ship):
        lx = self.x - ship.x
        ly = self.y - ship.y
        ldSq = lx * lx + ly * ly
        if ldSq == 0 : return

        ld = math.sqrt( ldSq )

        grav = (self.r * ship.r) / ( ld )
        ship.xVel += lx * grav
        ship.yVel  += ly * grav
    
    def __str__(self):
        return "x: " + str(self.x) + " self.y: " + str(self.y)  + " r: " + str(self.r)


class Human:
    x = 0
    y = 0
    r = 0
    planetsprite = None
    def __init__(self,initX,initY,initR):
        self.x=int(initX)
        self.y=int(initY)
        self.r=int(initR)
        self.rotation_speed = random.choice([-5,0,5])
        texture = pyglet.resource.image('human.png')
        texture.anchor_x = texture.width//2
        texture.anchor_y = texture.height//2
        self.planetsprite = pyglet.sprite.Sprite(texture, self.x, self.y)
        self.planetsprite.rotation = random.randrange(0,359)


    def update(self,dt):
        pass;
        
    def draw(self):
        self.planetsprite.draw()
        
    def addGravity(self,ship):
        lx = self.x - ship.x
        ly = self.y - ship.y
        ldSq = lx * lx + ly * ly
        if ldSq == 0 : return

        ld = math.sqrt( ldSq )

        grav = (self.r * ship.r) / ( ld )
        ship.xVel += lx * grav
        ship.yVel  += ly * grav
    
    def __str__(self):
        return "x: " + str(self.x) + " self.y: " + str(self.y)  + " r: " + str(self.r)


planets = []
humans = []
lives = 5

ship = Ship(0,0,0)

portal = Planet(0,0,0)
texture = pyglet.resource.image('portal.png')
texture.anchor_x = texture.width//2
texture.anchor_y = texture.height//2
portal.planetsprite = pyglet.sprite.Sprite(texture,portal.x,portal.y)
portal.planetsprite.scale = 1.0
portal.rotation_speed = 5

def distance(x1,y1,x2,y2):
    dx = x2 - x1
    dy = y2 - y1
    return math.sqrt(dx*dx + dy*dy)


def planetIsClear(x,y,r):
    rVal = True
    for planet in planets:
        if distance(x,y,planet.x,planet.y) < (r + planet.r + 50): #20 is a fudge value for clearance, adjust at will
            rVal = False
    return rVal

def createSolarSystem(numPlanets, numHumans):
    global solarSystemCount
    solarSystemCount += 1
    del planets[:]
    del humans[:]
    global canBeginLevel
    canBeginLevel = False
    global scorelabel
    
    
    for x in range(numPlanets):
        r = int(10 + random.random()*(100)+ 20);
        x = random.randint(0+r,window.width -r)
        y = random.randint(0+r,window.height -r)

        while not planetIsClear(x,y,r):
            r = int(10 + random.random()*(100)+20);
            x = random.randint(0+r,window.width -r)
            y = random.randint(0+r,window.height -r)
            
        p = Planet(x,y,r)
        planets.append(p)


    r = 5;
    x = random.randint(0+r,window.width-30 -r)
    y = random.randint(0+r,window.height-30 -r)
    while not planetIsClear(x,y,r):
        x = random.randint(0+r,window.width-30 -r)
        y = random.randint(0+r,window.height-30 -r)
    ship.r = r
    ship.x = x
    ship.y = y
    ship.xVel = 0
    ship.yVel = 0
    ship.shipsprite.x = x
    ship.shipsprite.y = y
    ship.exhaustsprite.x = x
    ship.exhaustsprite.y = y

    r = 15;
    x = random.randint(0+r,window.width -r)
    y = random.randint(0+r,window.height-30 -r)
    while not planetIsClear(x,y,r):
        x = random.randint(0+r,window.width -r)
        y = random.randint(0+r,window.height-30 -r)
    portal.r = r
    portal.x = x
    portal.y = y
    portal.planetsprite.x = x
    portal.planetsprite.y = y

    for x in range(numHumans):

        x = random.randint(0+r,window.width-30 -r)
        y = random.randint(0+r,window.height-30 -r)
        while not planetIsClear(x,y,5):
            x = random.randint(0+r,window.width-30 -r)
            y = random.randint(0+r,window.height-30 -r)
            
        p = Human(x,y,5)
        humans.append(p)
        
    scorelabel.text = str(len(humans)) + ' humans remaining in this system'


label2 = pyglet.text.Label('LD21 LD48 Entry - dave84 - Click to begin', 
                          font_name='Helvetica', 
                          font_size=15,
                          x=window.width//2, y=(window.height//2 - 250),
                          anchor_x='center')

highscorelabel = pyglet.text.Label('High Score: 0',
                          font_name='Helvetica',
                          font_size=20,
                          x=window.width//2, y=(window.height//2 - 100),
                          anchor_x='center')

scorelabel = pyglet.text.Label('0 humans remaining in this system', 
                          font_name='Helvetica', 
                          font_size=10,
                          x=10, y=(window.height - 20)
                          )

liveslabel = pyglet.text.Label(str(lives)+' lives left',
                          font_name='Helvetica', 
                          font_size=10,
                          x=250, y=(window.height - 20)
                          )
totalscorelabel = pyglet.text.Label('Score: ' + str(0),
                          font_name='Helvetica', 
                          font_size=10,
                          x=700, y=(window.height - 20)
                          )
                          
@window.event
def on_draw():
    window.clear()
    bgsprite.draw()
    for planet in planets:
        planet.draw()
    if len(humans) == 0:
        portal.draw()
    for human in humans:
        human.draw()

    ship.draw()
    scorelabel.draw()
    liveslabel.draw()
    totalscorelabel.draw()

    if drawMainScreen:
        label2.draw()
        logosprite.draw()
        highscorelabel.draw()
        
createSolarSystem(random.randint(4,8),random.randint(5,20))

def update(dt):
    global lives
    global canBeginLevel
    global solarSystemCount
    global totalHumanCount
    global drawMainScreen
    global portal
    global highscore
    global highscorelabel
    for human in humans:
        human.update(dt)
    for planet in planets:
        planet.update(dt)
    if canBeginLevel:
        if ship is not None:
            ship.update(dt)
        for planet in planets:
            planet.update(dt)
            if distance(ship.x,ship.y,planet.x,planet.y) < (planet.r + ship.r):
                lives -= 1
                deadsound.play()
                if lives == -1:
                    lives = 5
                    if (solarSystemCount * totalHumanCount) > highscore:
                        highscore = solarSystemCount * totalHumanCount
                        highscorelabel.text = 'High Score: ' + str(solarSystemCount * totalHumanCount)
                    solarSystemCount = 1
                    totalHumanCount = 0
                    totalscorelabel.text = "Score: " + str(solarSystemCount * totalHumanCount)
                    createSolarSystem(random.randint(4,8),random.randint(5,15))
                    drawMainScreen = True
                r = 5
                liveslabel.text = str(lives) + ' lives left'
                x = random.randint(0+r,window.width -r)
                y = random.randint(0+r,window.height -r)
                while not planetIsClear(x,y,5):
                    x = random.randint(0+r,window.width -r)
                    y = random.randint(0+r,window.height -r)
                ship.x = x
                ship.y = y
                ship.exhaustsprite.y = y
                ship.exhaustsprite.x = x
                ship.shipsprite.x = x
                ship.shipsprite.y = y
                canBeginLevel = False
                ship.xVel = 0
                ship.yVel = 0
                

        for human in humans:
            if distance(ship.x,ship.y,human.x,human.y) < (human.r + ship.r):
                humans.remove(human)
                if len(humans) > 0:
                    pickupsound.play()
                else:
                    portalopen.play()
                scorelabel.text = str(len(humans)) + ' humans remaining in this system'
                totalHumanCount += 1
                totalscorelabel.text = "Score: " + str(solarSystemCount * totalHumanCount)
        if len(humans) == 0:
            portal.update(dt)
            if distance(ship.x,ship.y,portal.x,portal.y) < (ship.r + portal.r):
                enterportal.play()
                createSolarSystem(random.randint(4,8),random.randint(5,20))


@window.event
def on_mouse_press(x, y, buttons, modifiers):
    global drawMainScreen,canBeginLevel
    if buttons & mouse.LEFT:
        if drawMainScreen:
            drawMainScreen = False
            return
        elif canBeginLevel == False:
            canBeginLevel = True
        lx = -1 * (x - ship.x)
        ly = -1 * (y - ship.y)
        ldSq = lx * lx + ly * ly
        if ldSq == 0 : return

        ld = math.sqrt( ldSq )

        grav = (1000 * ship.r) / ( ld )
        ship.xVel += lx * grav * 20
        ship.yVel  += ly * grav * 20
        ship.timer = 0.5

pyglet.clock.schedule_interval(update, 1/60.0)


pyglet.app.run()

