import pygame, spriteanimation
from pygame.locals import*

#Player class
class Player(pygame.sprite.Sprite):
    move_x = 0
    def __init__(self, initial_position, left_boundary, right_boundary):
        pygame.sprite.Sprite.__init__(self)
        sprite_sheet = spriteanimation.SpriteSheet("Raumschiff.png")
        self.image = sprite_sheet.get_image(0, 0, 20, 40)
        self.rect = self.image.get_rect()
        self.rect.center = initial_position
        self.right_boundary = right_boundary
        self.left_boundary = left_boundary
        
    def update(self):
        self.rect.x += self.move_x
        if self.rect.left <= self.left_boundary or self.rect.right >= self.right_boundary:
            self.stop()
                
    def go_left(self):
        self.move_x = -6
         
    def go_right(self):
        self.move_x = 6
        
    def stop(self):
        self.move_x = 0
    
    def get_pos(self):
        return self.rect.x
    
#Bomb class
class Bomb(pygame.sprite.Sprite):
    def __init__(self, initial_position, size_x, size_y):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface([size_x, size_y])
        self.image.fill((255,0,0))
        self.rect = self.image.get_rect()
        self.rect.center = initial_position
        
    def update(self):
        self.rect.y -= 3
      
#Alien class  
class Alien(pygame.sprite.Sprite):
    move_x = 1
    move_y = 25
    damage_frames = [] 
    def __init__(self, initial_position, left_boundary, right_boundary, hp, animation):
        pygame.sprite.Sprite.__init__(self)
        sprite_sheet = spriteanimation.SpriteSheet("alien_Sprite_Sheet.png")
        
        self.animation = animation
    
        image = sprite_sheet.get_image(2, 5, 20, 20)
        self.damage_frames.append(image)
        image = sprite_sheet.get_image(22, 5, 20, 20)
        self.damage_frames.append(image)
        image = sprite_sheet.get_image(42, 5, 20, 20)
        self.damage_frames.append(image)
        
        self.image = self.damage_frames[0]
        self.rect = self.image.get_rect()
        self.rect.center = initial_position
        self.right_boundary = right_boundary
        self.left_boundary = left_boundary
        self.hp = hp
        self.time_passed = 0
        self.animation.set_framerate(4)
        
    def take_damage(self, damage):
        self.hp -= damage
        if self.hp == 2:
            self.image = self.damage_frames[1]
        elif self.hp == 1:
            self.image = self.damage_frames[2]
        
    def get_hp(self):
        return self.hp
        
    def update(self, time_passed):
        self.rect.x += self.move_x
        if self.rect.right >= self.right_boundary or self.rect.left <= self.left_boundary:
            self.move_x *= -1
            self.rect.y += self.move_y
        if self.hp == 0:
            self.image = self.animation.get_frame(time_passed)
            #print len(self.animation.surfaces)
            print self.animation.get_act_frame()
            
            """ Leider kommt man hier nicht immer rein, was bedeutet, dass manche Aliens nicht gekillt werden. """
            if self.animation.get_act_frame() >= len(self.animation.surfaces)-1:
                print "animation done!"
                print len(self.animation.surfaces)
                self.animation.reset_animation()
                self.kill()
            
class Item(pygame.sprite.Sprite):
    move_x = 5
    move_y = 50
    def __init__(self, initial_position, left_boundary, right_boundary):
        pygame.sprite.Sprite.__init__(self)
        sprite_sheet = spriteanimation.SpriteSheet("Item.png")
        self.image = sprite_sheet.get_image(0, 4, 20, 20)
        self.rect = self.image.get_rect()
        self.rect.center = initial_position
        self.right_boundary = right_boundary
        self.left_boundary = left_boundary
        
    def activate(self):
        pass
    
    def update(self):
        self.rect.x += self.move_x
        self.rect.y += 2
        if self.rect.right >= self.right_boundary or self.rect.left <= self.left_boundary:
            self.move_x *= -1
            self.rect.y += self.move_y
        

#method to show the score and other stats           
def draw_score(score):
    font = pygame.font.SysFont("monospace", 15)
    label = font.render("space=shoot 1=multibomb 2=lazer" + " | Score:" + str(score), 1, (255, 255, 0))
    screen.blit(label, (0, 0))
    
def draw_stats(cooldown):
    cooldown_label = 5
    if cooldown > 5:
        cooldown_label = 0
    else:
        cooldown_label -= cooldown
    font = pygame.font.SysFont("monospace", 15)
    label = font.render("cooldown:" + str(cooldown_label), 1, (255, 0, 255))
    screen.blit(label, (0, 15))
    
def draw_item(item_ready):
    font = pygame.font.SysFont("monospace", 15)
    if item_ready:
        label = font.render("...LAZOR ACTIVATED...", 1, (255, 0, 0))
        screen.blit(label, (150, 15))
    else:
        label = font.render("...LAZOR INACTIVE...", 1, (255, 255, 0))
        screen.blit(label, (150, 15))
    
    
#method to create a multibomb
def fire_multibomb():
    j = -30
    for i in range(9):
        pos = (player.rect.x+j+i*10, player.rect.y)
        bomb = Bomb(pos, 4, 10)
        all_sprites_list.add(bomb)
        bomb_list.add(bomb)

#method to create the "lazor"      
def fire_lazor():
    pos = (player.rect.x+10, player.rect.y)
    bomb = Bomb(pos, 100, 400)
    all_sprites_list.add(bomb)
    bomb_list.add(bomb)
        
#method to create an item
def create_item():
    item = Item((35, 50), 0, screen_width)
    item_list.add(item)
    all_sprites_list.add(item)
    
def create_explosion_frame_list(sheet, animation):
    image_ex1 = sheet.get_image(0, 0, 20, 20)
    animation.add_frame(image_ex1)
    image_ex2 = sheet.get_image(20, 0, 20, 20)
    animation.add_frame(image_ex2)
    image_ex3 = sheet.get_image(40, 0, 20, 20)
    animation.add_frame(image_ex3)
    image_ex4 = sheet.get_image(60, 0, 20, 20)
    animation.add_frame(image_ex4)
        
pygame.init()
pygame.mixer.init()

#variables
screen_width = 500
score = 0
running = True
item_ready = False
screen = pygame.display.set_mode((screen_width, 600), 0, 32)
pygame.display.set_caption('BombGame')

multibomb_sound = pygame.mixer.Sound("multibomb.wav")
explosion_sound = pygame.mixer.Sound("explosion.wav")
fire_sound = pygame.mixer.Sound("fire.wav")
lazer_sound = pygame.mixer.Sound("chicken.wav")
music = pygame.mixer.music.load("scaryAlienNoise.wav")

explosion_frame_list = []
sheet = spriteanimation.SpriteSheet("explosion_Sprite_Sheet.png")
animation = spriteanimation.Animation(explosion_frame_list)
create_explosion_frame_list(sheet, animation)

clock = pygame.time.Clock()
fps = 60
milliseconds = clock.tick(fps)
seconds = milliseconds/1000.0
cooldown = 0
item_time = 0
time_passed = 0

#sprite lists
all_sprites_list = pygame.sprite.Group()
alien_list = pygame.sprite.Group()
bomb_list = pygame.sprite.Group()
item_list = pygame.sprite.Group()

#init player
player = Player((250,570), 0, screen_width)        
all_sprites_list.add(player)

#init aliens
for i in range(20):
    pos = (10+i*25, 50)   
    alien = Alien(pos, 0, screen_width, 3, animation)
    alien_list.add(alien)
    all_sprites_list.add(alien)
        
pygame.mixer.music.play(-1)

while running:
    #Clock
    clock.tick(fps)
    cooldown += seconds
    item_time += seconds
    time_passed += seconds
    
    #handle events
    for event in pygame.event.get():
        if event.type == QUIT:
            running = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                if player.rect.left > player.left_boundary:
                    player.go_left()
            if event.key == pygame.K_RIGHT:
                if player.rect.right < player.right_boundary:
                    player.go_right()
            if event.key == pygame.K_SPACE:
                    pos = (player.rect.x+10, player.rect.y)
                    pygame.mixer.Sound.play(fire_sound)
                    bomb = Bomb(pos, 4, 10)
                    all_sprites_list.add(bomb)
                    bomb_list.add(bomb)
            if event.key == pygame.K_1:
                    if cooldown / 5.0 >= 1:
                        cooldown = 0
                        fire_multibomb()
                        pygame.mixer.Sound.play(multibomb_sound)
            if event.key == pygame.K_2:
                    if item_ready:
                        fire_lazor()
                        pygame.mixer.Sound.play(lazer_sound)
                        item_ready = False
                    
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT and player.move_x < 0:
                player.stop()
            if event.key == pygame.K_RIGHT and player.move_x > 0:
                player.stop()

    #create item
    if item_time >= 10.0:
        item_time = -50.0
        create_item()
                
    #update all sprites
    alien_list.update(time_passed)
    bomb_list.update()
    player.update()
    item_list.update()
    #all_sprites_list.update()
    
    #bomb collision          
    for bomb in bomb_list:
        alien_hit_list = pygame.sprite.spritecollide(bomb, alien_list, False)
        item_hit_list = pygame.sprite.spritecollide(bomb, item_list, True)
        
        for item in item_hit_list:
            bomb_list.remove(bomb)
            all_sprites_list.remove(bomb)
            item_ready = True
            item.activate()
            draw_item(item_ready)
            
        for alien in alien_hit_list:
            bomb_list.remove(bomb)
            all_sprites_list.remove(bomb)
            alien.take_damage(1)
            if alien.get_hp() <= 0:
                alien.update(time_passed)
                all_sprites_list.draw(screen)
                #alien.kill()
                #alien_list.remove(alien)
                #all_sprites_list.remove(alien)
                pygame.mixer.Sound.play(explosion_sound)
                score += 1
                draw_score(score)
                print(score)
            
        if bomb.rect.y < 30:
            bomb_list.remove(bomb)
            all_sprites_list.remove(bomb)
      
    #draw everything      
    screen.fill((0,0,0))
    
    all_sprites_list.draw(screen)
    draw_score(score)
    draw_stats(cooldown)
    draw_item(item_ready)
    pygame.display.update()
    
    
pygame.quit()
    
    