from os import write
from time import time

from esp_hadouken.GameChild import *

class HighScores(GameChild, list):

    def __init__(self, parent):
        GameChild.__init__(self, parent)
        list.__init__(self, [])
        self.read()

    def read(self):
        for line in open(self.get_path()):
            line = line.strip()
            if line:
                self.append(Score(*line.split(" ")))

    def get_path(self):
        return self.get_resource("scoreboard-scores-path")

    def add(self, player):
        timer = self.get_timer()
        values = (timer["octo"], timer["horse"], timer["diortem"],
                  timer["circulor"], timer["tooth"])
        score = Score(time(), player, timer.total(), *values)
        self.append(score)
        self.write(score)

    def write(self, score):
        scores = open(self.get_path(), "a")
        scores.write(str(score) + "\n")

    def get_most_recent_player(self):
        return self[-1].player


class Score:

    def __init__(self, *args):
        self.date = int(args[0])
        self.player = args[1]
        self.total, self.octo, self.horse, self.diortem, self.circulor, \
                    self.tooth = map(float, args[2:])

    def __str__(self):
        return "%i %s %.3f %.3f %.3f %.3f %.3f %.3f" % \
               (self.date, self.player, self.total, self.octo, self.horse,
                self.diortem, self.circulor, self.tooth)

    def __lt__(self, other):
        return self.total < other.total

    def __repr__(self):
        return self.__str__()
from pygame import Surface

from esp_hadouken.GameChild import *
from esp_hadouken.Input import *
from Row import *
from Heading import *

class Scoreboard(GameChild, Surface):

    active_interval = 0

    def __init__(self, parent):
        GameChild.__init__(self, parent)
        self.init_surface()
        self.set_rect()
        self.heading = Heading(self)
        self.add_rows()
        self.subscribe_to(Input.command_event, self.respond_to_command)
        self.deactivate()

    def init_surface(self):
        config = self.get_configuration()
        step = self.get_step()
        padding = self.get_padding()
        row_height = self.get_row_height()
        height = step * row_height + padding + self.get_heading_height()
        Surface.__init__(self, (config["scoreboard-width"], height))
        self.set_alpha(config["scoreboard-alpha"])

    def get_step(self):
        return self.get_configuration()["scoreboard-interval-length"]

    def get_row_height(self):
        return self.get_configuration()["scoreboard-row-height"]

    def get_padding(self):
        return self.get_configuration()["scoreboard-padding"]

    def get_heading_height(self):
        return self.get_configuration()["scoreboard-heading-height"]
    
    def get_column_widths(self):
        return self.get_configuration()["scoreboard-column-widths"]

    def set_rect(self):
        rect = self.get_rect()
        rect.center = self.get_screen().get_rect().center
        self.rect = rect

    def add_rows(self):
        rows = []
        for ii in range(self.get_step()):
            rows.append(Row(self, ii))
        self.rows = rows

    def respond_to_command(self, event):
        if self.active:
            command = event.command
            if command == "next":
                self.set_active_interval(1)
                self.populate()
            elif command == "previous":
                self.set_active_interval(-1)
                self.populate()

    def set_active_interval(self, increment=0, interval=None):
        if interval is None:
            interval = self.active_interval + increment
        max_interval = self.get_max_interval()
        if interval < 0:
            interval = 0
        elif interval > max_interval:
            interval = max_interval
        self.active_interval = interval

    def get_max_interval(self):
        return len(self.get_high_scores()) / self.get_step()

    def populate(self):
        self.disable_highlights()
        step = self.get_step()
        low = step * self.active_interval
        high = low + step
        interval = self.get_ordered_scores()[low:high]
        interval += [None] * (step - len(interval))
        rows = self.rows
        for ii, score in enumerate(interval):
            score_index = low + ii
            row = rows[ii]
            if score_index == self.get_highlit_score_index():
               row.enable_highlight() 
            row.set_score(score, score_index)
        self.parent.update()

    def disable_highlights(self):
        for row in self.rows:
            row.disable_highlight()

    def get_ordered_scores(self):
        return sorted(self.get_high_scores())

    def activate(self, highlight=True):
        self.active = True
        if highlight:
            self.show_recent_score_interval()
        self.populate()

    def show_recent_score_interval(self):
        ordered = self.get_ordered_scores()
        interval = self.get_highlit_score_index() / self.get_step()
        self.set_active_interval(interval=interval)

    def get_highlit_score_index(self):
        return self.get_ordered_scores().index(self.get_high_scores()[-1])

    def deactivate(self):
        self.active = False

    def update(self):
        if self.active:
            self.clear()
            self.heading.update()
            for row in self.rows:
                row.update()
            self.draw()

    def clear(self):
        self.fill(Color(self.get_configuration()["scoreboard-bg"]))

    def draw(self):
        self.parent.blit(self, self.rect)
from pygame import Surface, Color
from pygame.locals import *

from esp_hadouken.GameChild import *
from esp_hadouken.Font import *

class Row(GameChild, Surface):

    def __init__(self, parent, index):
        GameChild.__init__(self, parent)
        self.index = index
        self.disable_highlight()
        self.init_surface()
        self.set_rect()
        self.set_column_surfaces()

    def enable_highlight(self):
        self.highlit = True

    def disable_highlight(self):
        self.highlit = False

    def init_surface(self):
        parent = self.parent
        width = parent.get_width() - parent.get_padding()
        Surface.__init__(self, (width, parent.get_row_height()))
        self.fill(self.get_color())

    def get_color(self):
        config = self.get_configuration()
        if self.highlit:
            color = config["scoreboard-highlight-color"]
        elif not self.index % 2:
            color = config["scoreboard-row-color-1"]
        else:
            color = config["scoreboard-row-color-2"]
        return Color(color)

    def set_rect(self):
        rect = self.get_rect()
        parent = self.parent
        index = self.index
        padding = parent.get_padding()
        heading = parent.get_heading_height()
        rect.top = padding / 2 + index * parent.get_row_height() + heading
        rect.centerx = parent.get_rect().centerx
        self.rect = rect

    def set_column_surfaces(self):
        self.rank_surf, self.rank_surf_r = self.set_column_surface(0)
        self.initials_surf, self.initials_surf_r = self.set_column_surface(1)
        self.total_surf, self.total_surf_r = self.set_column_surface(2)
        self.split_surfs, self.split_surfs_rs = [], []
        for ii in range(3, 8):
            surf, rect = self.set_column_surface(ii)
            self.split_surfs.append(surf)
            self.split_surfs_rs.append(rect)

    def set_column_surface(self, index):
        ratios = self.parent.get_column_widths()
        relative = self.get_size()
        surf = Surface((relative[0] * ratios[index], relative[1]))
        surf.fill(self.get_color())
        indent = 0
        for ratio in ratios[:index]:
            indent += ratio * relative[0]
        rect = surf.get_rect()
        rect.left = indent
        return surf, rect

    def set_score(self, score, rank):
        self.render_rank(rank)
        self.render_initials(score)
        self.render_total(score)
        if score is None:
            splits = [None] * 5
        else:
            splits = [score.octo, score.horse, score.diortem, score.circulor,
                      score.tooth]
        for ii, split in enumerate(splits):
            self.render_split(ii, split)

    def render_rank(self, rank):
        size = self.get_configuration()["scoreboard-rank-size"]
        rend = Font(self, size).render(str(rank + 1), True, self.get_text_color(),
                                       self.get_color())
        rect = rend.get_rect()
        dest = self.rank_surf
        dest.fill(self.get_color())
        rect.center = dest.get_rect().center
        dest.blit(rend, rect)

    def get_text_color(self):
        return Color(self.get_configuration()["scoreboard-text-color"])

    def render_initials(self, score):
        self.initials_surf.fill(self.get_color())
        if score is None:
            return
        x = 0
        margin = self.get_configuration()["scoreboard-initials-margin"]
        size = self.get_height() - margin * 2
        for letter in score.player:
            self.render_initial(letter, x, size)
            x += size + margin

    def get_blank_char(self):
        return self.get_configuration()["scoreboard-blank-char"]

    def render_initial(self, letter, x, size):
        square = Surface((size, size))
        if letter == self.get_blank_char():
            color = self.get_configuration()["scoreboard-initials-blank-color"]
            color = Color(color)
        else:
            color = self.get_glyph_palette()[ord(letter.lower()) - K_a]
        square.fill(color)
        font_size = self.get_configuration()["scoreboard-initials-size"]
        rend = Font(self, font_size).render(letter, True, self.get_text_color(),
                                            color)
        square_rect = square.get_rect()
        rend_rect = rend.get_rect()
        rend_rect.center = square_rect.center
        square.blit(rend, rend_rect)
        square_rect.centery = self.get_rect().centery
        square_rect.left = x
        self.initials_surf.blit(square, square_rect)

    def render_total(self, score):
        dest = self.total_surf
        dest.fill(self.get_color())
        if score is None:
            return
        text = self.build_time_string(score.total)
        size = self.get_configuration()["scoreboard-total-size"]
        rend = Font(self, size).render(text, True, self.get_text_color(),
                                       self.get_color())
        rect = rend.get_rect()
        rect.center = dest.get_rect().center
        dest.blit(rend, rect)

    def build_time_string(self, time):
        return "%i:%02i" % divmod(int(time), 60)

    def get_blank_time(self):
        return self.get_blank_char()

    def render_split(self, index, time):
        dest = self.split_surfs[index]
        dest.fill(self.get_color())
        if time is None:
            return
        text = self.build_time_string(time)
        size = self.get_configuration()["scoreboard-split-size"]
        rend = Font(self, size).render(text, True, self.get_text_color(),
                                       self.get_color())
        rect = rend.get_rect()
        rect.center = dest.get_rect().center
        dest.blit(rend, rect)

    def update(self):
        self.clear()
        self.draw()

    def clear(self):
        self.fill(self.get_color())

    def draw(self):
        self.blit(self.rank_surf, self.rank_surf_r)
        self.blit(self.initials_surf, self.initials_surf_r)
        self.blit(self.total_surf, self.total_surf_r)
        for ii, surf in enumerate(self.split_surfs):
            self.blit(surf, self.split_surfs_rs[ii])
        self.parent.blit(self, self.rect)
18.207.252.123
18.207.252.123
18.207.252.123
 
August 12, 2013

I've been researching tartan/plaid recently for decoration in my updated version of Ball & Cup, now called Send. I want to create the atmosphere of a sports event, so I plan on drawing tartan patterns at the vertical edges of the screen as backgrounds for areas where spectator ants generate based on player performance. I figured I would make my own patterns, but after browsing tartans available in the official register, I decided to use existing ones instead.

I made a list of the tartans that had what I thought were interesting titles and chose 30 to base the game's levels on. I sequenced them, using their titles to form a loose narrative related to the concept of sending. Here are three tartans in the sequence (levels 6, 7 and 8) generated by an algorithm I inferred by looking at examples that reads a tartan specification and draws its pattern using a simple dithering technique to blend the color stripes.


Acadia


Eve


Spice Apple

It would be wasting an opportunity if I didn't animate the tartans, so I'm thinking about animations for them. One effect I want to try is making them look like water washing over the area where the ants are spectating. I've also recorded some music for the game. Here are the loops for the game over and high scores screens.

Game Over

High Scores