from GameChild import GameChild

class Animation(GameChild):

    def __init__(self, parent, method=None, interval=None, unfiltered=False):
        GameChild.__init__(self, parent)
        self.unfiltered = unfiltered
        self.default_method = method or self.build_frame
        self.accounts = {}
        self.register(self.default_method, interval=interval)
        self.current_elapsed = 0
        self.last_update = 0

    def build_frame(self):
        pass

    def register(self, *args, **kwargs):
        interval = None
        if kwargs.has_key("interval"):
            interval = kwargs["interval"]
        for method in args:
            if method not in self.accounts:
                self.accounts[method] = Account(interval, self)
            else:
                self.accounts[method].set_interval(interval)

    def play(self, method=None, interval=None, delay=0, play_once=False,
             **kwargs):
        account = self.accounts[self.get_default(method)]
        account.set_delay(delay)
        account.set_args(kwargs)
        account.set_play_once(play_once)
        if interval:
            account.set_interval(interval)
        account.play()

    def get_default(self, method=None):
        if not method:
            method = self.default_method
        return method

    def halt(self, method=None):
        if not method:
            for account in self.accounts.values():
                account.halt()
        else:
            if self.accounts.has_key(method):
                self.accounts[method].halt()

    def is_playing(self, method=None, check_all=False, include_delay=False):
        if check_all:
            return any(self.is_account_playing(account, include_delay) for \
                       method, account in self.accounts.iteritems())
        return self.is_account_playing(self.accounts[self.get_default(method)],
                                       include_delay)

    def is_account_playing(self, account, include_delay):
        return account.playing and (not include_delay or not account.delay)

    def reset_timer(self, method):
        if not method:
            for account in self.accounts.values():
                account.reset_timer()
        else:
            self.accounts[method].reset_timer()

    def update(self):
        for method, account in self.accounts.iteritems():
            if account.update():
                method(**account.args)


class Account:

    def __init__(self, interval, animation):
        self.animation = animation
        self.time_filter = animation.get_game().time_filter
        self.set_interval(interval)
        self.set_delay(0)
        self.set_play_once(False)
        self.interval_index = 0
        self.last_frame = 0
        self.halt()

    def set_interval(self, interval):
        if isinstance(interval, int) or isinstance(interval, str):
            interval = [interval]
        self.interval = interval

    def set_delay(self, delay):
        self.delay = delay

    def set_play_once(self, play_once):
        self.play_once = play_once

    def set_args(self, args):
        self.args = args

    def play(self):
        self.playing = True

    def halt(self):
        self.last_update = None
        self.playing = False

    def update(self):
        if self.playing:
            if self.animation.unfiltered:
                ticks = self.time_filter.get_unfiltered_ticks()
            else:
                ticks = self.time_filter.get_ticks()
            self.update_delay(ticks)
            if not self.delay:
                interval = self.interval
                if interval:
                    if ticks - self.last_frame < self.get_current_interval():
                        return False
                    self.last_frame = ticks
                    self.increment_interval_index()
                if self.play_once:
                    self.halt()
                return True

    def get_current_interval(self):
        return self.interval[self.interval_index]

    def increment_interval_index(self, increment=1):
        index = self.interval_index + increment
        while index >= len(self.interval):
            index -= len(self.interval)
        self.interval_index = index

    def reset_interval(self):
        self.interval_index = 0

    def reset_timer(self):
        if self.animation.unfiltered:
            ticks = self.time_filter.get_unfiltered_ticks()
        else:
            ticks = self.time_filter.get_ticks()
        self.last_frame = ticks

    def update_delay(self, ticks):
        delay = self.delay
        if delay > 0:
            last_update = self.last_update or ticks
            delay -= ticks - last_update
            if delay < 0:
                delay = 0
        self.last_update = ticks
        self.delay = delay
from pygame.event import get, pump, Event, post
from pygame.locals import *

from GameChild import GameChild
from Input import Input

class Delegate(GameChild):

    def __init__(self, game):
        GameChild.__init__(self, game)
        self.subscribers = dict()
        self.load_configuration()
        self.disable()

    def load_configuration(self):
        config = self.get_configuration("event")
        self.cancel_flag_key = config["cancel-flag-key"]
        self.command_key = config["command-key"]
        self.command_event_id = config["command-id-offset"] + \
                                globals()[config["user-event-id"]]

    def disable(self):
        self.enabled = False

    def enable(self):
        self.enabled = True
        self.interpolator = self.get_game().interpolator

    def dispatch(self):
        if self.enabled:
            subscribers = self.subscribers
            for evt in get():
                kind = evt.type
                if kind in subscribers:
                    for subscriber in subscribers[kind]:
                        if not self.interpolator.is_gui_active() or \
                               hasattr(subscriber, "im_class") and \
                               (subscriber.im_class == Input or \
                                subscriber.im_class == \
                                self.interpolator.gui.__class__):
                            self.print_debug("Passing %s to %s" % (evt,
                                                                   subscriber))
                            subscriber(evt)
        else:
            pump()

    def add_subscriber(self, callback, kind=None):
        self.print_debug("Subscribing %s to %s" % (callback, kind))
        if kind is None:
            kind = self.command_event_id
        subscribers = self.subscribers
        if kind not in subscribers:
            subscribers[kind] = list()
        subscribers[kind].append(callback)

    def is_command(self, event):
        return event.type == self.command_event_id

    def remove_subscriber(self, callback, kind=None):
        if kind is None:
            kind = self.command_event_id
        self.subscribers[kind].remove(callback)

    def compare(self, evt, commands=None, cancel=False, **attributes):
        if evt.type == self.command_event_id:
            self.add_cancel_flag_to_attributes(attributes, cancel)
        if commands is not None and not isinstance(commands, list):
            commands = [commands]
        if commands is not None:
            if not self.command_in_list(evt, commands):
                return False
        return all(key in evt.dict and evt.dict[key] == value for \
                   key, value in attributes.iteritems())

    def add_cancel_flag_to_attributes(self, attributes, cancel):
        attributes[self.cancel_flag_key] = cancel

    def command_in_list(self, evt, commands):
        return self.get_command_attribute(evt) in commands

    def get_command_attribute(self, evt):
        return evt.dict[self.command_key]

    def post(self, command=None, cancel=False, **attributes):
        attributes[self.command_key] = command
        self.add_cancel_flag_to_attributes(attributes, cancel)
        post(Event(self.command_event_id, attributes))
184.73.55.221
184.73.55.221
184.73.55.221
 
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


↠ RSS Feed ↞