#
###
# Application: Pycadia
# File:        actor.py
# Description: pycadia Actor class
# Copyright (c) 2002-2003   Andy Balcombe <http://www.anti-particle.com>
###
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#

from math import sqrt, pi, atan
import pygame
from pygame.locals import *

from game_state import Point

class Actor:
    """An enhanced sort of sprite class"""
    def __init__(self, consts, surf_size):
        self.consts = consts
        self.image = pygame.Surface(surf_size).convert()
        self.image.set_colorkey((0,0,0))#, RLEACCEL
        self.rect = self.image.get_rect()
        self.blank_img = pygame.Surface(surf_size).convert()
        self.visible=0
        self.mass=0
        self.brightness = consts.NORM_BRIGHT
        r=self.blank_img.fill((0,0,0))
        
    def check_spin_limits(self):
        """keep spin within range"""
        if self.spin_deg >= self.consts.NUMBER_OF_DEGREES or self.spin_deg <= -self.consts.NUMBER_OF_DEGREES:
            self.spin_deg = 0
        
    def check_position_limits(self):
        """wrap objects around the screen"""
        y = self.rect.height/2  #get height of sprite surface
        if self.pos.x < 0: 
            self.pos.x = self.consts.SCREENRECT.right
        elif self.pos.x > self.consts.SCREENRECT.right:
            self.pos.x = 0
        if self.pos.y < 21+y: 
            self.pos.y = self.consts.SCREENRECT.bottom
        if self.pos.y > self.consts.SCREENRECT.bottom:
            self.pos.y = 21+y

    def rotate_point(self, old_point, angle):
        """returns point rotated by angle"""
        new_point = Point(( float((old_point.x*self.gs.COS(angle))-(old_point.y*self.gs.SIN(angle))),
                            float((old_point.y*self.gs.COS(angle))+(old_point.x*self.gs.SIN(angle)))
                        ))    
        return new_point

    def draw_obj(self):
        #erase old image
        r=self.image.blit(self.blank_img, (0,0))
        #stop now if object is invisible
        if not(self.visible): return
        #initial calcs
        x = self.rect.width / 2  #center pos
        y = self.rect.height / 2
        scalemode = 1.25 * self.scale
        lines = self.lines
        verts = self.verts
        rotation = self.spin_deg
        col = (self.brightness,self.brightness,self.brightness)   
        #draw new image
        self.image.lock()
        for i in range(len(lines)):
            #get initial points...
            xfrom1 = verts[lines[i][0]][0] * scalemode
            yfrom1 = verts[lines[i][0]][1] * scalemode
            xto1 = verts[lines[i][1]][0] * scalemode
            yto1 = verts[lines[i][1]][1] * scalemode
            #...and rotate them to correct angle
            xfrom2 = (xfrom1*self.gs.COS(rotation)) - (yfrom1*self.gs.SIN(rotation))
            yfrom2 = (yfrom1*self.gs.COS(rotation)) + (xfrom1*self.gs.SIN(rotation))
            xto2 = (xto1*self.gs.COS(rotation)) - (yto1*self.gs.SIN(rotation))
            yto2 = (yto1*self.gs.COS(rotation)) + (xto1*self.gs.SIN(rotation))
            #draw the line
            rect=pygame.draw.line(self.image, col, (x+xfrom2,y+yfrom2), (x+xto2,y+yto2), 1)
        self.image.unlock()

    def calc_sun_gravity(self):
        """calculate suns gravity effects on given object (self)"""
        #need to calc?
        if self.mass == 0 or not self.consts.SUN_GRAVITY: return
        #calculate gravity for object mass
        grav_factor = self.consts.SUN_GRAVITY / self.mass
        #calculate distance from the sun
        xLen = self.pos.x - self.consts.SUN_POSITION[0]
        yLen = self.pos.y - self.consts.SUN_POSITION[1]
        length =  sqrt((xLen * xLen) + (yLen * yLen))
        #calculate unit vector
        unitX = xLen / length
        unitY = yLen / length
        #clamp the distance
        if length < self.consts.SUN_DISTCLAMP:
            length = self.consts.SUN_DISTCLAMP
        #gravity is inverse r squared
        unitX = unitX * (grav_factor/(length*length))
        unitY = unitY * (grav_factor/(length*length))
        #update object speed
        self.speed.x += unitX
        self.speed.y += unitY

    def calculate_angle(self, target_obj):
        """calculate the angle to given object"""
        #this function taken from "twitch", a game by David Clark
        ### Copyright (C) 2001  David Clark
        #http://sourceforge.net/projects/twitch/
        delta_x = target_obj.pos.x - self.pos.x * 1.000
        delta_y = target_obj.pos.y - self.pos.y * 1.000
        if delta_x == 0:
            delta_x = 0.1
        angle = int(atan(delta_y / delta_x) * 180 / pi)
        if delta_x < 0:
            angle += 180
        if angle < 0:
            angle += 360
        return (angle - 90) * 4 
        
