## Copyright 2007-2008 Bryce Schroeder ## ## bryce.schroeder@gmail.com ## ## http://www.ferazelhosting.net/~bryce/ ## ##-------------------------------------------------------------------------## ## 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 3 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 General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## ## along with this program. If not, see . ## ############################################################################# from .standard_interpreters import Resource, R from . import g from .interface import IEventHandler #import interface from .ply import lex, yacc import cStringIO import pygame from sys import stderr class AnmState(object): def __init__(self, cords, edges, sound=None): self.cords = cords if sound: self.sound = g.resources.get("Sound",sound) else: self.sound = None #print edges self.edges = dict(edges) def get(self, edge): return self.edges.get(edge,None) def frame(self): return self.cords def play_sound(self): if self.sound: self.sound.play() ############################################################################# ##### LEXER AND PARSER FOR ANIMATION FILES ################################## ############################################################################# tokens = ( "EXPIRE", "SOUND", "STATENAME", "EDGENAME", "INTEGER", "OFFSET", "SNDNAME", # "COMMENT" ) def t_EXPIRE(t): r"expire" return t def t_SOUND(t): r"sound" return t t_STATENAME = r"[A-Z][-a-zA-Z_0-9]*" t_EDGENAME = r"[a-z][-A-Za-z_0-9]*" def t_OFFSET(t): r"[-+][0-9]+[xy]" t.value = t.value[-1], int(t.value[:-1]) return t def t_INTEGER(t): r"[0-9]+" t.value = int(t.value) return t def t_SNDNAME(t): r"\([-a-zA-Z0-9_ ]+\)" t.value = t.value[1:-1] return t def t_error(t): print >> stderr, "animation lexer error", t t_ignore = " \t\n" #t_COMMENT = r"\#.*\n" literals = ",:;." lex.lex() def p_state_list0(p): """state_list : state""" p[0] = [p[1]] def p_state_list1(p): """state_list : state_list state""" p[0] = p[1] + [p[2]] def p_state(p): """state : STATENAME INTEGER ',' INTEGER sound_clause ':' edge_list """ p[0] = p[1], AnmState((p[2], p[4]), p[7], p[5]) def p_sound_clause0(p): """sound_clause : """ p[0] = None def p_sound_clause1(p): """sound_clause : SOUND SNDNAME""" p[0] = p[2] def p_edge_list0(p): """edge_list : edge_list edge""" p[0] = p[1] + [p[2]] def p_edit_list1(p): """edge_list : edge""" p[0] = [p[1]] def p_edge0(p): """edge : EDGENAME ':' edge_rhs ';'""" p[0] = p[1], p[3]+(0,) def p_edge1(p): """edge : EDGENAME INTEGER ':' edge_rhs ';'""" p[0] = p[1], p[4]+(p[2]-1,) def p_edge_rhs0(p): """edge_rhs : STATENAME offset_clause""" p[0] = p[1], p[2] def p_edge_rhs1(p): """edge_rhs : EXPIRE""" p[0] = (None,None) def p_offset_clause0(p): """offset_clause : OFFSET""" p[0] = p[1] def p_offset_clause1(p): """offset_clause : """ p[0] = None #def p_offset_clause_list0(p): # """offset_clause_list : offset_clause_list OFFSET""" # p[0] = p[1] + p[2] #def p_offset_clause_list1(p): # """offset_clause_list : OFFSET""" # p[0] = [p[1]] #def p_offset_clause_list2(p): # """offset_clause_list : """ # p[0] = [] def p_error(p): print >> stderr, "Animation parser error, line", p.lineno, print >> stderr, 'char', p.lexpos yacc.yacc(debug=1) ############################################################################# ############################################################################# ############################################################################# class PropInstance(pygame.sprite.Sprite): def __init__(self, propclass, **kwargs): pygame.sprite.Sprite.__init__(self) self.dead=False self.kind = propclass self.rect = pygame.rect.Rect(0,0,propclass.size[0],propclass.size[1]) self.change_state(propclass.start_state) self.orders = [] self.same_count = 0 self.previous_edge = None def change_state(self, state): if self.dead: return self.state = state self.kind.play_sound(state) self.image = self.kind.frame(state) def transition(self, edge): try: nstate, offs, ifd = self.kind.animation[self.state].edges[edge] except KeyError: return False if nstate == None: # this is where the "respond and say I'm finished" code goes #print "Finished" self.map.remove_prop_by_value(self) self.dead = True if edge == self.previous_edge: self.same_count += 1 else: self.previous_edge = edge self.same_count = 0 if self.same_count < ifd: return False self.change_state(nstate) #print offs if offs: if offs[0] == 'x': self.rect.x += offs[1] elif offs[0] == 'y': self.rect.y += offs[1] self.same_count = 0 return True def add_orders(self, edges): """Takes a sequences of edges.""" for edge in edges: self.add_order(edge) def add_order(self, edge): #print "added", edge self.orders.append(edge) def update(self): #if self.dirty: self.render() #if self.orders: print self.orders if self.dead: return if self.orders and self.transition(self.orders[0]): self.orders.pop(0) else: self.transition('tick') class Prop(Resource): MANDATORY = ['image', 'animation'] #OPTIONAL = ['meta'] def init(self): self.meta = {} if self.parts.has_key('meta'): self.meta = self.process_meta(self.parts['meta']) self.surface = pygame.image.load(cStringIO.StringIO( self.parts['image'])).convert_alpha() self.animation = dict(yacc.parse(self.parts['animation'], tracking=True)) self.size = self.meta['size'] self.start_state = self.meta.get('start', 'Idle') self.dirty = True def instance(self): return PropInstance(self) def frame(self, state): x,y = self.animation[state].frame() return self.surface.subsurface((x*self.size[0],y*self.size[1], self.size[0], self.size[1])) def play_sound(self, state): self.animation[state].play_sound() ############################################################################# ############################################################################# #############################################################################