from sys import platform


if __name__ == "__main__":
    if platform == "darwin":
        from setuptools import setup, find_packages
        from lib.pgfw.pgfw.Configuration import Configuration
        from lib.pgfw.pgfw.Setup import Setup
        config = Configuration()
        setup_obj = Setup()
        version = config.get_section("setup")["version"]
        name = setup_obj.translate_title()
        plist = dict(
            CFBundleIconFile=name,
            CFBundleName=name,
            CFBundleShortVersionString=version,
            CFBundleGetInfoString=' '.join([name, version]),
            CFBundleExecutable=name,
            CFBundleIdentifier='org.' + name.lower())
        setup(name=name,
              version=version,
              app=[dict(script="OPEN-GAME", plist=plist)],
              setup_requires=["py2app"],
              options=dict(py2app=dict(arch="i386",)),
              data_files=["PlanetLicker.py", "resource", "lib", "config", "FreeLicense.txt"])
    elif platform == "win32":
        from lib.pgfw.pgfw.SetupWin import SetupWin
        SetupWin().setup()
    else:
        from lib.pgfw.pgfw.Setup import Setup
        Setup().setup()
from os.path import join, basename
from glob import glob
from random import random, choice, randrange, randint, shuffle
from math import degrees

from pygame import Surface, Color
from pygame.draw import circle, polygon
from pygame.gfxdraw import aacircle
from pygame.image import load
from pygame.transform import rotate
from pygame.event import clear
from pygame.font import Font
from pygame.mixer import Sound, music
from pygame.locals import *

from lib.pgfw.pgfw.Game import Game
from lib.pgfw.pgfw.GameChild import GameChild
from lib.pgfw.pgfw.Sprite import Sprite, BlinkingSprite, RainbowSprite
from lib.pgfw.pgfw.Vector import Vector
from lib.pgfw.pgfw.Animation import Animation
from lib.pgfw.pgfw.extension import (get_distance, get_angle, get_delta, get_endpoint,
                                     get_hue_shifted_surface, fill_tile, get_shadowed_text,
                                     get_hsla_color)

class PlanetLicker(Game, Animation):

    SPAWN_MARGIN = 200
    LICK_A, LICK_B, LICK_C = "lick-a", "lick-b", "lick-c"
    STAR_SATURATION = 60
    STAR_COLORED_LIGHTNESS = 50
    STAR_NEUTRAL_LIGHTNESS = 80
    FADE_OUT_TITLE_LENGTH = 4000
    FADE_IN_TITLE_LENGTH = 1000

    def __init__(self):
        Game.__init__(self)
        Animation.__init__(self, self)
        self.sound_effects = SoundEffects(self)
        self.display_surface = self.get_display_surface()
        self.title = Title(self)
        self.monster = Monster(self)
        self.planets = Planets(self)
        self.hud = HUD(self)
        self.bgm = Sound(self.get_resource("Lick-the-World.ogg"))
        self.subscribe(self.respond)
        self.register(self.reset, self.unsuppress_commands)
        self.reset()

    def set_background(self):
        field = []
        w, h = [Planets.WORLD_SIZE] * 2
        for x in xrange(w):
            field.append([])
            for y in xrange(h):
                if random() < .0005:
                    field[-1].append((randrange(0, 360), choice((10, 20, 30, 40, 50))))
                else:
                    field[-1].append(None)
        background = self.background = Sprite(self, 800)
        color = Color(0, 0, 0)
        for _ in xrange(8):
            frame = Surface((w, h))
            frame.fill((0, 0, 0))
            for x, row in enumerate(field):
                for y, cell in enumerate(row):
                    if cell:
                        rect = Rect((0, 0), [randint(1, 2)] * 2)
                        rect.center = x, y
                        if random() < .5:
                            color.hsla = (cell[0] + randint(-cell[1], cell[1])) % 360, \
                                         self.STAR_SATURATION, self.STAR_COLORED_LIGHTNESS, \
                                         100
                        else:
                            color.hsla = 0, 0, self.STAR_NEUTRAL_LIGHTNESS, 100
                        for ox, oy in (0, 0), (-w, 0), (0, -h), (w, 0), (0, h):
                            frame.fill(color, rect.move(ox, oy))
                            frame.fill(color, rect.move(-1 + ox, -1 + oy))
                            frame.fill(color, rect.move(1 + ox, 1 + oy))
                            frame.fill(color, rect.move(-1 + ox, 1 + oy))
                            frame.fill(color, rect.move(1 + ox, -1 + oy))
                            frame.fill(color, rect.move(-2 + ox, 0 + oy))
                            frame.fill(color, rect.move(2 + ox, 2 + oy))
                            frame.fill(color, rect.move(2 + ox, 0 + oy))
                            frame.fill(color, rect.move(-2 + ox, -2 + oy))
            background.add_frame(frame)
        background.add_location(offset=(w, 0))
        background.add_location(offset=(0, h))
        background.add_location(offset=(w, h))

    def respond(self, event):
        if not self.title.active and not self.commands_suppressed and not self.game_over:
            compare = self.get_game().delegate.compare
            if compare(event, "reset-game"):
                self.reset()
            elif self.compare_lick(event, self.LICK_A):
                self.add_vector(self.LICK_A)
            elif self.compare_lick(event, self.LICK_B):
                self.add_vector(self.LICK_B)
            elif self.compare_lick(event, self.LICK_C):
                self.add_vector(self.LICK_C)

    def unsuppress_commands(self):
        self.commands_suppressed = False

    def compare_lick(self, event, lick):
        compare = self.get_game().delegate.compare
        if self.check_command_line("-makey"):
            return (lick == self.LICK_A and compare(event, "left")) or \
                (lick == self.LICK_B and compare(event, "up")) or \
                (lick == self.LICK_C and compare(event, "right"))
        else:
            return compare(event, lick)

    def add_vector(self, lick):
        closest = None
        min_distance = None
        for planet in self.planets.planets:
            if planet.lick == lick:
                for location in planet.locations:
                    distance = get_distance(location.center, self.monster.location.center)
                    if min_distance is None or distance < min_distance:
                        closest = location
                        min_distance = distance
        if closest is None:
            self.get_game().sound_effects.play("stall")
        else:
            planets = self.monster.collide_with_planets()
            if planets and lick in [planet.lick for planet in planets]:
                for planet in planets:
                    if planet.lick == lick:
                        break
                self.monster.show_lick()
                planet.shrink()
            else:
                angle = get_angle(closest.center, self.monster.location.center)
                vector = Motion(self, degrees(angle))
                self.vectors.append(vector)
                self.get_game().sound_effects.play("propell-2")

    def reset(self):
        self.time_filter.close()
        self.game_over = False
        self.set_background()
        self.planets.reset()
        self.monster.reset()
        self.title.reset()
        self.halt()
        self.obstacles = []
        self.vectors = []
        while True:
            conflict = False
            self.move(randint(0, Planets.WORLD_SIZE),
                      randint(0, Planets.WORLD_SIZE))
            for planet in self.planets.planets:
                for location in planet.locations:
                    if get_distance(location.center, self.monster.location.center) < \
                       self.SPAWN_MARGIN:
                        conflict = True
                        break
                if conflict:
                    break
            if not conflict:
                break
        self.suppress_commands(2000)
        clear()
        self.monster.get_current_frameset().reset()
        self.time_filter.open()

    def move(self, x, y):
        w, h = self.background.location.size
        self.background.move(-x, -y)
        if self.background.location.top > 0:
            self.background.move(dy=-h)
        if self.background.location.right < 0:
            self.background.move(w)
        if self.background.location.bottom < 0:
            self.background.move(dy=h)
        if self.background.location.left > 0:
            self.background.move(-w)
        for planet in self.planets.planets:
            planet.move(-x, -y)
            if planet.location.top > 0:
                planet.move(dy=-h)
            if planet.location.right < 0:
                planet.move(w)
            if planet.location.bottom < 0:
                planet.move(dy=h)
            if planet.location.left > 0:
                planet.move(-w)
        for obstacle in self.obstacles:
            obstacle.move(-x, -y)
            if obstacle.location.top > 0:
                obstacle.move(dy=-h)
            if obstacle.location.right < 0:
                obstacle.move(w)
            if obstacle.location.bottom < 0:
                obstacle.move(dy=h)
            if obstacle.location.left > 0:
                obstacle.move(-w)

    def suppress_commands(self, length):
        self.commands_suppressed = True
        self.reset_timer(self.unsuppress_commands)
        self.time_filter.reset_ticks()
        self.play(self.unsuppress_commands, delay=length, play_once=True)

    def add_obstacles(self, origin):
        for _ in xrange(6):
            obstacle = Obstacle(self)
            obstacle.load_from_path(self.get_resource("mine"), True)
            while True:
                obstacle.location.center = get_endpoint(origin, randrange(0, 360),
                                                        randint(190, 200))
                conflict = False
                for planet in self.planets.planets:
                    if planet.location.colliderect(obstacle.location):
                        conflict = True
                        break
                for other in self.obstacles:
                    if other.location.colliderect(obstacle.location.inflate(20, 20)):
                        conflict = True
                        break
                if not conflict:
                    break
            obstacle.add_location(offset=(Planets.WORLD_SIZE, 0))
            obstacle.add_location(offset=(0, Planets.WORLD_SIZE))
            obstacle.add_location(offset=(Planets.WORLD_SIZE, Planets.WORLD_SIZE))
            self.obstacles.append(obstacle)

    def end_game(self, success=False):
        self.game_over = True
        font = Font(self.get_resource("PetMe.ttf"), 64)
        color = (255, 0, 0)
        if success:
            frame = font.render("YOU WIN!", True, (0, 255, 0))
            self.get_game().sound_effects.play("win")
        else:
            frame = font.render("GAME OVER", True, (255, 0, 0))
        sprite = self.game_over_sprite = Sprite(self)
        sprite.add_frame(frame)
        sprite.location.center = self.display_surface.get_rect().center
        self.play(self.reset, delay=3000, play_once=True)

    def update(self):
        Animation.update(self)
        self.title.update()
        if not self.title.active:
            for vector in self.vectors:
                self.move(*vector.delta)
                vector.update()
                if vector.delta == (0, 0):
                    self.vectors.remove(vector)
            if not self.vectors and self.monster.get_current_frameset().name != "lick":
                self.monster.set_frameset("idle")
            elif self.monster.get_current_frameset().name != "lick":
                self.monster.set_frameset("moving")
            self.background.update()
            self.planets.update()
            damaged = False
            for obstacle in self.obstacles:
                for location in obstacle.locations:
                    if location.colliderect(self.monster.location) and \
                       get_distance(location.center, self.monster.location.center) < \
                       location.w / 2 + self.monster.location.w / 2:
                        if not damaged:
                            self.monster.damage()
                            damaged = True
                        self.obstacles.remove(obstacle)
                obstacle.update()
            self.hud.update()
            self.monster.update()
            self.show_hints()
            if self.game_over:
                self.game_over_sprite.update()

    def show_hints(self):
        for lick in Planets.LICKS:
            closest = None
            min_distance = None
            for planet in self.planets.planets:
                for location in planet.locations:
                    if planet.lick == lick:
                        distance = get_distance(self.monster.location.center,
                                                location.center)
                        if not closest or distance < min_distance:
                            color = planet.get_color()
                            closest = location
                            min_distance = distance
            rect = self.get_display_surface().get_rect()
            if closest and not closest.colliderect(rect.inflate(-20, -20)):
                surface = Surface((20, 30))
                surface.fill((255, 255, 255))
                transparent = (255, 0, 255)
                surface.set_colorkey(transparent)
                polygon(surface, transparent, ((0, 10), (0, 0), (10, 0)))
                polygon(surface, transparent, ((10, 0), (20, 0), (20, 10)))
                circle(surface, color, (10, 20), 8)
                if closest.centery < 0 or closest.centery > rect.h:
                    x = closest.centerx
                    if x < 0:
                        x = 0
                    elif x > rect.w - surface.get_width():
                        x = rect.w - surface.get_width()
                    if closest.centery < 0:
                        y = 0
                    else:
                        y = rect.h - surface.get_height()
                        surface = rotate(surface, 180)
                else:
                    y = closest.centery
                    if closest.centery < 0:
                        y = 0
                    elif closest.centery > rect.h - surface.get_height():
                        y = rect.h - surface.get_height()
                    if closest.centerx < 0:
                        x = 0
                        surface = rotate(surface, 90)
                    else:
                        x = rect.w - surface.get_height()
                        surface = rotate(surface, 270)
                self.get_display_surface().blit(surface, (x, y))


class Title(Animation):

    PLANET_MARGIN = 53
    TITLE_OFFSET = 11, 11
    BLINK_INTERVAL = 500
    EATEN_SOUND_DELAY = 600
    LICK_LENGTH = 500

    def __init__(self, parent):
        Animation.__init__(self, parent)
        self.display_surface = self.get_display_surface()
        self.audio = Sound(self.get_resource("Lick-Through.ogg"))
        self.set_monster()
        self.set_text()
        self.set_background()
        self.set_planets()
        self.subscribe(self.respond)
        self.register(self.deactivate, self.play_gone_sound_effect, self.end_lick)

    def set_monster(self):
        monster = self.monster = Sprite(self)
        monster.load_from_path(self.get_resource("title"), transparency=True, query="biomass-*.png")
        order = [0, 1, 0, 1, 0, 2, 0, 3, 1, 3, 1, 3, 4, 3]
        interval = [2000, 300, 3000, 300, 2000, 300, 1000, 2000, 300, 3000, 300, 2000, 300, 2000]
        monster.add_frameset(order, interval, "idle", True)
        monster.add_frameset([5], name="lick")

    def set_text(self):
        name = self.name = RainbowSprite(self, load(self.get_resource("title/name.png")).convert_alpha(),
                                         60)
        name.location.topleft = self.TITLE_OFFSET
        prompt = self.prompt = BlinkingSprite(self, self.BLINK_INTERVAL)
        font = Font(self.get_resource("PetMe128.ttf"), 12)
        prompt.add_frame(get_shadowed_text("LICK TO START", font, (0, 2), (255, 255, 255), True))
        prompt.location.midtop = name.location.centerx, name.location.bottom + 15

    def set_background(self):
        background = self.background = Sprite(self)
        base_frame = Surface(self.display_surface.get_size())
        fr = base_frame.get_rect()
        base_column = load(self.get_resource("title/column.png")).convert()
        cr = base_column.get_rect()
        color = Color(0, 0, 0)
        for hue_offset in xrange(0, 360, 4):
            column = get_hue_shifted_surface(base_column, hue_offset)
            frame = base_frame.copy()
            fill_tile(frame, column)
            background.add_frame(frame)

    def set_planets(self):
        planets = self.planets = []
        rect = self.get_display_surface().get_rect()
        for ii, path in enumerate(sorted(glob(join(self.get_resource("title/"), "planet-*.png")))):
            planet = Sprite(self)
            planet.load_from_path(path, transparency=True)
            planet.location.centerx = rect.centerx - (1 - ii) * (self.PLANET_MARGIN + planet.location.w)
            planet.location.bottom = rect.bottom
            planets.append(planet)

    def respond(self, event):
        if self.active and not self.get_game().commands_suppressed:
            compare = self.get_game().compare_lick
            if compare(event, PlanetLicker.LICK_A):
                self.planets[0].hide()
                self.lick()
            elif compare(event, PlanetLicker.LICK_B):
                self.planets[1].hide()
                self.lick()
            elif compare(event, PlanetLicker.LICK_C):
                self.planets[2].hide()
                self.lick()
            if all(planet.is_hidden() for planet in self.planets):
                self.play(self.deactivate, delay=1000, play_once=True)
                self.get_game().suppress_commands(2000)

    def lick(self):
        self.monster.set_frameset("lick")
        self.play(self.end_lick, delay=self.LICK_LENGTH, play_once=True)
        self.play_lick_menu_sound()

    def end_lick(self):
        self.monster.set_frameset("idle")

    def play_lick_menu_sound(self):
        self.get_game().sound_effects.play("licking")
        self.play(self.play_gone_sound_effect, delay=self.EATEN_SOUND_DELAY, play_once=True)

    def play_gone_sound_effect(self):
        self.get_game().sound_effects.play("gone")

    def reset(self):
        self.activate()
        self.monster.location.center = self.get_display_surface().get_rect().center
        for planet in self.planets:
            planet.unhide()
        self.halt()
        self.monster.set_frameset("idle")

    def activate(self):
        self.active = True
        self.audio.play(-1, 0, PlanetLicker.FADE_IN_TITLE_LENGTH)
        self.get_game().bgm.fadeout(PlanetLicker.FADE_IN_TITLE_LENGTH)

    def deactivate(self):
        self.active = False
        self.audio.fadeout(PlanetLicker.FADE_OUT_TITLE_LENGTH)
        self.get_game().bgm.play(-1, 0, PlanetLicker.FADE_IN_TITLE_LENGTH)
        self.get_game().sound_effects.play("start")

    def update(self):
        if self.active:
            Animation.update(self)
            self.background.update()
            self.name.update()
            # self.prompt.update()
            self.monster.update()
            for planet in self.planets:
                planet.update()


class Obstacle(Sprite):

    def __init__(self, parent):
        Sprite.__init__(self, parent, 300)
        self.alpha_base = 0

    def update(self):
        Sprite.update(self)
        self.alpha_base = (self.alpha_base + 48) % 511
        for location in self.locations:
            for radius in xrange(int(self.location.w / 4.0), 2, -2):
                alpha = int((255 * 0 + .875 * abs(self.alpha_base - 255)) * (1 - (radius / (self.location.w / 4.0))))
                surface = Surface(self.location.inflate(10, 10).size, SRCALPHA)
                circle(surface, (255, 192, 128, alpha), surface.get_rect().center, radius)
                ds = self.get_display_surface()
                ds.blit(surface, location.inflate(10, 10).topleft)


class SoundEffects(GameChild):

    def __init__(self, parent):
        GameChild.__init__(self, parent)
        effects = self.effects = []
        for path in glob(join(self.get_resource("sfx"), "*.wav")):
            effects.append(SoundEffect(self, path))

    def play(self, name, volume=None):
        for effect in self.effects:
            if effect.name == name:
                effect.play(volume=volume)


class SoundEffect(GameChild, Sound):

    DEFAULT_VOLUME = 1.0

    def __init__(self, parent, path, volume=DEFAULT_VOLUME):
        GameChild.__init__(self, parent)
        Sound.__init__(self, path)
        self.name = basename(path).split(".")[0]
        self.display_surface = self.get_display_surface()
        self.set_volume(volume)

    def play(self, loops=0, maxtime=0, fade_ms=0, position=None, x=None, volume=None):
        channel = Sound.play(self, loops, maxtime, fade_ms)
        if x is not None:
            position = float(x) / self.display_surface.get_width()
	if position is not None and channel is not None:
            channel.set_volume(*self.get_panning(position))
        return channel

    def get_panning(self, position):
        return 1 - max(0, ((position - .5) * 2)), \
               1 + min(0, ((position - .5) * 2))


class Motion(GameChild):

    def __init__(self, parent, angle):
        GameChild.__init__(self, parent)
        self.angle = angle
        self.nodeset = self.get_game().interpolator.get_nodeset("speed")
        self.time_left = self.nodeset.get_length()
        self.update()

    def update(self):
        if self.time_left > 0:
            self.time_left -= self.get_game().time_filter.get_last_frame_duration()
            dx, dy = get_delta(self.angle, self.nodeset.get_y(self.time_left))
            self.delta = -dx, dy
        else:
            self.delta = 0, 0


class Monster(Sprite):

    INITAL_LIFE = 3

    def __init__(self, parent):
        Sprite.__init__(self, parent)
        self.display_surface = self.get_display_surface()
        self.add_frames()
        self.location.center = self.display_surface.get_rect().center
        self.register(self.end_lick)

    def add_frames(self):
        self.load_from_path(self.get_resource("biomass/"), True)
        self.add_frameset([0, 3, 4, 0, 5], [5000, 800, 800, 5000, 200], "idle", True)
        self.add_frameset([0, 1, 2, 1], 100, "lick")
        self.add_frameset(0, name="moving")
        # self.add_frameset([3, 4], [400, 800], "shifty")
        # self.add_frameset(5, name="cute")

    def reset(self):
        self.life = self.INITAL_LIFE
        self.halt(self.end_lick)
        self.set_frameset("idle")

    def collide_with_planets(self):
        planets = []
        for planet in self.get_game().planets.planets:
            for location in planet.locations:
                if location.colliderect(self.location) and \
                   get_distance(self.location.center, location.center) < \
                   location.w / 2 + self.location.w / 2:
                    planets.append(planet)
        return planets

    def damage(self):
        self.life -= 1
        if self.life == 0:
            self.get_game().end_game()
            self.get_game().sound_effects.play("player_death")
        else:
            self.get_game().sound_effects.play("take_damage-1")

    def show_lick(self):
        if not self.get_current_frameset().name == "lick":
            self.set_frameset("lick")
            self.play(self.end_lick, delay=800, play_once=True)
            self.get_game().sound_effects.play("licking")

    def end_lick(self):
        self.set_frameset("idle")

    def update(self):
        Sprite.update(self)


class Planets(GameChild):

    WORLD_SIZE = 1500
    RADII = 64
    LICKS = PlanetLicker.LICK_A, PlanetLicker.LICK_B, PlanetLicker.LICK_C
    CITY, VOLCANO, UNDERWATER, BEACH, ARCADE, GHOST = xrange(6)
    MIN_MARGIN = 400
    MAX_TRIES = 800
    MIN_PLANETS = 3

    def __init__(self, parent):
        GameChild.__init__(self, parent)

    def reset(self):
        self.populate()

    def populate(self):
        kinds = range(6)
        kinds_copy = list(kinds)
        for _ in xrange(3):
            kinds.append(kinds_copy.pop())
        radii = list([self.RADII] * 9)
        shuffle(radii)
        licks = list(self.LICKS + self.LICKS + self.LICKS)
        freeze_avoided = False
        while not freeze_avoided:
            planets = self.planets = []
            for kind, radius, lick in zip(kinds, radii, licks):
                tries = 0
                while True:
                    conflict = False
                    planet = Planet(self, radius, lick, kind)
                    planet.location.center = randint(0, Planets.WORLD_SIZE), \
                                             randint(0, Planets.WORLD_SIZE)
                    planet.add_location(offset=(Planets.WORLD_SIZE, 0))
                    planet.add_location(offset=(0, Planets.WORLD_SIZE))
                    planet.add_location(offset=(Planets.WORLD_SIZE, Planets.WORLD_SIZE))
                    for other in self.planets:
                        for location in other.locations:
                            for my_location in planet.locations:
                                tries += 1
                                if get_distance(location.center, my_location.center) < self.MIN_MARGIN:
                                    conflict = True
                                    break
                            if conflict:
                                break
                        if conflict:
                            break
                    if not conflict or tries > self.MAX_TRIES:
                        break
                planets.append(planet)
                if tries > self.MAX_TRIES:
                    break
            if tries < self.MAX_TRIES:
                freeze_avoided = True
                
    def update(self):
        for planet in self.planets:
            planet.update()


class Planet(Sprite):

    COLORS = (251, 186, 68), (60, 133, 255), (60, 219, 90)
    SHRINK_STEP = 16
    CANVAS_SIZE = 160

    def __init__(self, parent, radius, lick, kind):
        Sprite.__init__(self, parent)
        self.max_radius = radius
        self.radius = radius
        self.lick = lick
        self.kind = kind
        self.set_ring()
        self.add_frames()

    def set_ring(self):
        ring = self.ring = None
        if self.kind == Planets.CITY:
            self.ring = load(self.get_resource("planets/city_128.png")).convert_alpha()
        elif self.kind == Planets.UNDERWATER:
            self.ring = load(self.get_resource("planets/underwater_128.png")).convert_alpha()
        elif self.kind == Planets.GHOST:
            self.ring = load(self.get_resource("planets/ghost_128.png")).convert_alpha()
        elif self.kind == Planets.BEACH:
            self.ring = load(self.get_resource("planets/beach_128.png")).convert_alpha()
        elif self.kind == Planets.VOLCANO:
            self.ring = load(self.get_resource("planets/volcano_128.png")).convert_alpha()
        elif self.kind == Planets.ARCADE:
            self.ring = load(self.get_resource("planets/arcade_128.png")).convert_alpha()

    def add_frames(self):
        self.clear_frames()
        frame = Surface([self.CANVAS_SIZE] * 2, SRCALPHA)
        circle(frame, self.get_color(), [self.CANVAS_SIZE / 2] * 2, self.radius)
        if self.ring:
            frame.blit(self.ring, (0, 0))
        self.add_frame(frame)

    def get_color(self):
        return self.COLORS[Planets.LICKS.index(self.lick)]

    def shrink(self):
        self.radius -= self.SHRINK_STEP
        if self.radius == 0:
            self.get_game().add_obstacles(self.location.center)
            self.get_game().sound_effects.play("planet_eaten-1")
            self.parent.planets.remove(self)
            if len(self.parent.planets) == self.parent.MIN_PLANETS:
                self.get_game().end_game(True)

    def update(self):
        self.add_frames()
        Sprite.update(self)


class HUD(GameChild):

    BACKGROUND_HSLA = 252, 50, 38, 100

    def __init__(self, parent):
        GameChild.__init__(self, parent)
        self.left = Left(self)
        self.life = Life(self)

    def update(self):
        self.left.update()
        self.life.update()


class Left(Animation):

    GRADIENT_HUE_SHIFT = 0
    TEXT_OFFSET = 12, 4
    DIGIT_OFFSET = 61, -5
    DIGIT_HUE_SHIFT = 70

    def __init__(self, parent):
        Animation.__init__(self, parent)
        self.set_background()
        text = self.text = Sprite(self)
        text.load_from_path(self.get_resource("left/text.png"), True)
        text.location.topleft = self.background.location.move(*self.TEXT_OFFSET).topleft
        self.set_digits()

    def set_background(self):
        background = self.background = Sprite(self)
        image = load(self.get_resource("left/background.png")).convert_alpha()
        image.fill(get_hsla_color(*HUD.BACKGROUND_HSLA), None, BLEND_RGBA_MIN)
        background.add_frame(image)
        background.location.topright = self.get_display_surface().get_rect().topright

    def set_digits(self):
        digits = self.digits = []
        for path in sorted(glob(join(self.get_resource("left"), "digit-*.png"))):
            digit = Sprite(self)
            digit.add_frame(get_hue_shifted_surface(load(path).convert_alpha(), self.DIGIT_HUE_SHIFT))
            digit.location.topleft = self.background.location.move(*self.DIGIT_OFFSET).topleft
            digits.append(digit)

    def update(self):
        Animation.update(self)
        self.background.update()
        self.text.update()
        self.digits[len(self.get_game().planets.planets) - Planets.MIN_PLANETS].update()


class Life(GameChild):

    START_POSITION = 11, 6
    MARGIN = 0

    def __init__(self, parent):
        GameChild.__init__(self, parent)
        self.set_background()
        self.set_hearts()

    def set_background(self):
        background = self.background = Sprite(self)
        image = load(self.get_resource("life/background.png")).convert_alpha()
        image.fill(get_hsla_color(*HUD.BACKGROUND_HSLA), None, BLEND_RGBA_MIN)
        background.add_frame(image)
        background.location.bottomleft = self.get_display_surface().get_rect().bottomleft

    def set_hearts(self):
        self.full_heart = load(self.get_resource("life/heart-full.png")).convert_alpha()
        self.empty_heart = load(self.get_resource("life/heart-empty.png")).convert_alpha()

    def update(self):
        self.background.update()
        x, y = self.background.location.move(*self.START_POSITION).topleft
        ds = self.get_display_surface()
        for ii in xrange(Monster.INITAL_LIFE):
            if ii < self.get_game().monster.life:
                ds.blit(self.full_heart, (x, y))
            else:
                ds.blit(self.empty_heart, (x, y))
            x += self.full_heart.get_width()
54.224.166.141
54.224.166.141
54.224.166.141
 
June 7, 2018


↠ RSS Feed ↞