def setImg( self, imgName=None ): if imgName: if not self.texMgr: self.texMgr = TextureManager() self.image, self.texID = self.texMgr.load_image(\ os.path.join(self.setsMgr.ui_dir,imgName)) else: self.image = None self.imgBox = None self.quad = None
def __init__( self, fontName=None ): """ This class represents a font to be rendered for UIText. """ # store the fontname for FYI's sake (might want to know this) self.fname = fontName self.letterSize = (1,1) self.tilesX = 0 # get the singleton texture manager reference(see TextureManager) self.texMgr = TextureManager() self.setsMgr = SettingsManager() # font map image self.image = None self.imSize = (0,0) # font map texture id self.texID = None # an image returned if a letter/digit is not in the font self.NotDefined, self.NoDefID = self.texMgr.load_image(os.path.join('NotDefined.png')) ### the following two lists are parallel # --> [<lower>,<upper>,<num>] # these bools tell what the font has defined(lowercase, uppercase, numbers) self.blockHt = {'lower':0, 'upper':0, 'digits':0} # the images corresponding to the respective letter and number self.alphabet = {} self.alphabetBox = {} # this determines if a font was loaded properly. self.ready = False self.config = None # process the font if it is provided if fontName: self.setFont( fontName )
class Font: """ An encapsulation of a font to be used by UIText objects """ def __init__( self, fontName=None ): """ This class represents a font to be rendered for UIText. """ # store the fontname for FYI's sake (might want to know this) self.fname = fontName self.letterSize = (1,1) self.tilesX = 0 # get the singleton texture manager reference(see TextureManager) self.texMgr = TextureManager() self.setsMgr = SettingsManager() # font map image self.image = None self.imSize = (0,0) # font map texture id self.texID = None # an image returned if a letter/digit is not in the font self.NotDefined, self.NoDefID = self.texMgr.load_image(os.path.join('NotDefined.png')) ### the following two lists are parallel # --> [<lower>,<upper>,<num>] # these bools tell what the font has defined(lowercase, uppercase, numbers) self.blockHt = {'lower':0, 'upper':0, 'digits':0} # the images corresponding to the respective letter and number self.alphabet = {} self.alphabetBox = {} # this determines if a font was loaded properly. self.ready = False self.config = None # process the font if it is provided if fontName: self.setFont( fontName ) # ...otherwise wait until defined # set and setup the visual representation of the font def setFont( self, fontName ): """ Sets the font represented by this class and loads it into the class by reading the font's respective <font-name>.ini and then cutting """ self.config = SafeConfigParser() self.ready = False # open the font's info file try: self.config.read(os.path.join( self.setsMgr.home_dir, self.setsMgr.media_home , self.setsMgr.font_dir, fontName+'.ini')) except ( ParsingError, MissingSectionHeaderError ): # error reading the file return # straight to your room w/o dessert ####################### # Parse the meta-data # ####################### try: # ensure we have 'details' or fail gracefully ############# ## 'fname' ## ############# try: # store the plain-text name self.fname = self.config.get('details', 'fname') except NoOptionError: # missing name is no big deal, but warn the user print "FontLoad:Warning:", fontName\ ,":[details] section missing 'fname'." ############ ## 'size' ## ############ try: # store all of the sizes available to this self.letterSize = eval( self.config.get('details', 'letterSize'), {},{}) except NoOptionError: # missing 'sizes' means that we don't know what sizes # are defined in the file (this parser will not infer # any other sections on its own) print 'FontLoad:Error:', fontName,\ ":[details] missing 'size' list" return # return failed ################ ## 'tilesX/Y' ## ################ try: self.tilesX = eval(self.config.get('details','tilesX'),{},{}) except NoOptionError: print 'FontLoad:Error:', fontName,": [details] missing 'tilesX'" return # return failed ################### ## block-heights ## ################### try: self.blockHt['lower'] = eval(self.config.get('details','htLower'),{},{}) except NoOptionError: # ignore quietly pass try: self.blockHt['upper'] = eval(self.config.get('details','htUpper'),{},{}) except NoOptionError: # ignore quietly pass try: self.blockHt['digits'] = eval(self.config.get('details','htNum'),{},{}) except NoOptionError: # ignore quietly pass try: self.blockHt['symbols'] = eval(self.config.get('details','htSym'),{},{}) self.suppSyms = eval( self.config.get('details', 'symbols'), {}, {} ) except NoOptionError: # clear what might have been done self.blockHt['symbols'] = 0 self.suppSyms = [] print 'Warning : Font : symbols load failed' # and ignore quietly... just waaalk away, .. nice and slow now.... nothing to see heere.. pass # validate that this font defines at least one of the four if self.blockHt['lower']+self.blockHt['upper']+\ self.blockHt['digits']+self.blockHt['symbols'] == 0: print 'FontLoad:Error:', fontName,\ ":[details] must specify block ht for all letter/number sets in image" return # the font must specify except NoSectionError: print 'FontLoad:Error:', fontName, ': .ini missing [details] section.' return # a font requires this section, return unsuccessfully ######################## # Load/Parse the image # ######################## #self.NotDefined, self.NoDefID = self.texMgr.load_image(os.path.join('fonts','NotDefined.png')) # load the image through the resource manager self.image, self.texID = self.texMgr.load_image( os.path.join(self.setsMgr.font_dir, self.fname) ) if not self.image: print 'FontLoad:Error:', fontName,\ ":Image load was unsuccessful with path,",\ os.path.join(self.setsMgr.home_dir, self.setsMgr.media_home , self.setsMgr.font_dir, self.fname) return # image load failed E = [] if self.blockHt['lower'] > 0: # the following extensions are ordered deliberately E.extend( map(chr, range(97, 123)) ) # ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm' #, 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'] if self.blockHt['upper'] > 0: E.extend( map(chr, range(65, 91)) ) # ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M' #, 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'] if self.blockHt['digits'] > 0: E.extend( map(str, range(0, 10)) ) # [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ] if self.blockHt['symbols'] > 0: E.extend( self.suppSyms ) # include the supported symbols acc. to the .ini x, y = (0, 0) # might be useful later self.imSize = self.image.size # loop over image calculating boxes for letter in E: # the area of the image containing 'this' letter box = ( x, self.imSize[1]-y, x+self.letterSize[0] , self.imSize[1] - (y+self.letterSize[1]) ) # throw it onto the list self.alphabet[letter] = self.image.crop( box ) self.alphabetBox[letter] = box #print letter, x, y # increment the x forward x = x + self.letterSize[0] # check if at z if letter == 'z' or letter == 'Z' or letter == '9' or letter == ' ': x = 0 y = y + self.letterSize[1] elif x/self.letterSize[0] >= self.tilesX: x = 0 y = y + self.letterSize[1] # this is only set in the event that this function completed # all necessary actions and is ready for use. self.ready = True return # gets a letter/digit image from the font at destSize # DEPRECATED: its inefficient to chop up the image into separate textures # as opposed to indexing boxes into a single one (see getCharBox) def getChar( self, character, destSize ): # this is for transforming the image to the desired size data = ( 0, 0, self.letterSize[0], self.letterSize[1] ) if character in self.alphabet: return self.alphabet[character].transform(destSize, Image.EXTENT, data) elif character.swapcase() in self.alphabet: return self.alphabet[character.swapcase()].transform(destSize, Image.EXTENT, data) # the letter is not defined (return the empty image) return self.NotDefined.transform(destSize,Image.EXTENT,data) # Returns the box of a character in the font def getCharBox( self, character ): """ Returns the box of a character in the font """ # get the character from the alphabet if character in self.alphabetBox: #print character, self.alphabetBox[character] return self.alphabetBox[character] elif character.swapcase() in self.alphabetBox: #print character, self.alphabetBox[character.swapcase()] return self.alphabetBox[character.swapcase()] print 'Bad Character:', character # return the NoDef image return (0, 0, self.NotDefined.size[0], self.NotDefined.size[1]) # Returns the font's texture id def getTexID( self ): """ Returns the font's texture id """ return self.texID # This is the function called by the screen on all renderable objects. def render( self, scrScroll=(0,0) ): """ This is a test function and not intended for use in the game, but who am I to judge what's in a game.. """ setMgr = SettingsManager() # returns the id, texBox, position, and a quadBox in pixel coords return [ (self.texID , ( 0, self.image.size[1], self.image.size[0], 0 ) , ( 0, 0, setMgr.screenRes[0], setMgr.screenRes[1] )) ]
def setSprite( self, filename ): """ Loads the ini file and image according to 'filename'. """ # grab this if we haven't already if not self.texMgr: # We store it to be efficient about retrieving it # in case we need to use it later. self.texMgr = TextureManager() if not self.setsMgr: self.setsMgr = SettingsManager() self.config = SafeConfigParser() # open the font's info file try: self.config.read(\ os.path.join( self.setsMgr.home_dir , self.setsMgr.media_home , self.setsMgr.sprites_dir, filename+'.ini')) except ( ParsingError, MissingSectionHeaderError ): # error reading the file raise sys.exc_info()[1], None, sys.exc_info()[2] ####################### # Parse the meta-data # ####################### try: # ensure we have 'details' or fail gracefully ############# ## 'fname' ## ############# try: # store the plain-text name self.filename = self.config.get('details', 'fname') except NoOptionError: self.filename = filename+'.png' raise sys.exc_info()[1], None, sys.exc_info()[2] ################## ## 'directions' ## ################## try: # store all of the supported directions self.directions= eval( self.config.get('details', 'directions'), {},{}) except NoOptionError: # missing 'sizes' means that we don't know what sizes # are defined in the file (this parser will not infer # any other sections on its own) print 'SpriteLoad:Warning:', fontName,\ ":[details] missing 'directions' list; one frame is assumed." ################# ## 'numFrames' ## ################# try: # this is the number of frames per direction self.numFrames = eval(self.config.get('details','numFrames'),{},{}) except NoOptionError: print 'SpriteLoad:Error:',filename,": [details] missing 'numFrames'" raise sys.exc_info()[1], None, sys.exc_info()[2] ################# ## 'frameSize' ## ################# try: # this is the size of each frame self.frameSize = eval(self.config.get('details','frameSize'),{},{}) except NoOptionError: print 'SpriteLoad : Error :', filename,": [details] missing 'frameSize'" raise sys.exc_info()[1], None, sys.exc_info()[2] except NoSectionError: print 'SpriteLoad:Error:', fontName, ': .ini missing [details] section.' raise sys.exc_info()[1], None, sys.exc_info()[2] # load the image through the resource manager self.image, self.texID = self.texMgr.load_image(\ os.path.join(self.setsMgr.sprites_dir, self.filename) ) imSize = self.image.size self.tileWd = imSize[0]/self.numFrames if len(self.directions) > 0: self.tileHt = imSize[1]/len(self.directions) else: self.tileHt = imSize[1] dir = 0 for y in range( 0, imSize[1], self.tileHt ): for x in range( 0, imSize[0], self.tileWd): self.sprBoxes.append( (x, y+self.tileHt, x+self.tileWd, y) ) # store direction offsets based on the order in # self.directions offset = 0 self.directions.reverse() for dir in self.directions: if dir == 'U': self.UP = offset elif dir == 'D': self.DOWN = offset elif dir == 'L': self.LEFT = offset elif dir == 'R': self.RIGHT = offset elif dir == 'UL': self.UL = offset elif dir == 'UR': self.UR = offset elif dir == 'DL': self.DL = offset elif dir == 'DR': self.DU = offset else: print dir, ' SpriteLoad:Warning: Do not put things in the'\ , ' directions list that are not'\ , '[ U, D, L, R, UL, UR, DL, DR ].' offset += self.numFrames
class Sprite(): def __init__(self, filename=None): self.size = [1,1] self.halfSize = [self.size[0]/2, self.size[1]/2] self.scale = (1,1) self.filename = filename self.directions = [] self.numFrames = 0 self.frameSize = [10,10] self.prevDir = 0 # last direction self.pos = [0,0] # current pos self.lastPos = [0,0] # previous pos self.facingDir = [1,1] # the player's current facing direction # visibility self.visible = True # managers self.texMgr = None self.setsMgr = None # our image and corresponding texture id self.image, self.texID = None, -1 self.sprBoxes = [] self.UP = 0 self.DOWN = 0 self.LEFT = 0 self.RIGHT = 0 self.UL = 0 self.UR = 0 self.DL = 0 self.DR = 0 # animation related self.animSpeed = 1 # should be overridden by derived classes self.tick = 0 # the timer counting update ticks(see '.update') self._step = 0 # the texture box self.image, self.texID = None, None self.textureBox = None self.lastTexBox = None # if we have the filename, load the sprite(hope it works) if filename: self.setSprite( filename ) def setSprite( self, filename ): """ Loads the ini file and image according to 'filename'. """ # grab this if we haven't already if not self.texMgr: # We store it to be efficient about retrieving it # in case we need to use it later. self.texMgr = TextureManager() if not self.setsMgr: self.setsMgr = SettingsManager() self.config = SafeConfigParser() # open the font's info file try: self.config.read(\ os.path.join( self.setsMgr.home_dir , self.setsMgr.media_home , self.setsMgr.sprites_dir, filename+'.ini')) except ( ParsingError, MissingSectionHeaderError ): # error reading the file raise sys.exc_info()[1], None, sys.exc_info()[2] ####################### # Parse the meta-data # ####################### try: # ensure we have 'details' or fail gracefully ############# ## 'fname' ## ############# try: # store the plain-text name self.filename = self.config.get('details', 'fname') except NoOptionError: self.filename = filename+'.png' raise sys.exc_info()[1], None, sys.exc_info()[2] ################## ## 'directions' ## ################## try: # store all of the supported directions self.directions= eval( self.config.get('details', 'directions'), {},{}) except NoOptionError: # missing 'sizes' means that we don't know what sizes # are defined in the file (this parser will not infer # any other sections on its own) print 'SpriteLoad:Warning:', fontName,\ ":[details] missing 'directions' list; one frame is assumed." ################# ## 'numFrames' ## ################# try: # this is the number of frames per direction self.numFrames = eval(self.config.get('details','numFrames'),{},{}) except NoOptionError: print 'SpriteLoad:Error:',filename,": [details] missing 'numFrames'" raise sys.exc_info()[1], None, sys.exc_info()[2] ################# ## 'frameSize' ## ################# try: # this is the size of each frame self.frameSize = eval(self.config.get('details','frameSize'),{},{}) except NoOptionError: print 'SpriteLoad : Error :', filename,": [details] missing 'frameSize'" raise sys.exc_info()[1], None, sys.exc_info()[2] except NoSectionError: print 'SpriteLoad:Error:', fontName, ': .ini missing [details] section.' raise sys.exc_info()[1], None, sys.exc_info()[2] # load the image through the resource manager self.image, self.texID = self.texMgr.load_image(\ os.path.join(self.setsMgr.sprites_dir, self.filename) ) imSize = self.image.size self.tileWd = imSize[0]/self.numFrames if len(self.directions) > 0: self.tileHt = imSize[1]/len(self.directions) else: self.tileHt = imSize[1] dir = 0 for y in range( 0, imSize[1], self.tileHt ): for x in range( 0, imSize[0], self.tileWd): self.sprBoxes.append( (x, y+self.tileHt, x+self.tileWd, y) ) # store direction offsets based on the order in # self.directions offset = 0 self.directions.reverse() for dir in self.directions: if dir == 'U': self.UP = offset elif dir == 'D': self.DOWN = offset elif dir == 'L': self.LEFT = offset elif dir == 'R': self.RIGHT = offset elif dir == 'UL': self.UL = offset elif dir == 'UR': self.UR = offset elif dir == 'DL': self.DL = offset elif dir == 'DR': self.DU = offset else: print dir, ' SpriteLoad:Warning: Do not put things in the'\ , ' directions list that are not'\ , '[ U, D, L, R, UL, UR, DL, DR ].' offset += self.numFrames def getFrame( self, (hDir, vDir) ): """ Returns the box of the frame corresponding to the direction implied by hDir and vDir and the current animation step. """ direction = 0 # Facing Left if hDir < 0: # Not facing up or down if vDir == 0: direction = self.LEFT # facing up elif vDir < 0: direction = self.UL # facing down elif vDir > 0: direction = self.DL # Facing Right elif hDir > 0: # Not facing up or down if vDir == 0: direction = self.RIGHT elif vDir < 0: direction = self.UR elif vDir > 0: direction = self.DR # No horizontal movement elif hDir == 0: if vDir == 0: ### special case: direction = self.prevDir ### elif vDir < 0: direction = self.UP elif vDir > 0: direction = self.DOWN self.prevDir = direction # return the box of the frame in the dir and at the # current step, 'self._step' return self.sprBoxes[self._step + direction]
class UIImage(UIObject): def __init__( self, imgName=None, pos=[0,0], size=[1,1]): """ An image on the screen for UI purposes (clickable or not) """ # Base class constructor UIObject.__init__(self) self.pos = pos self.size = size self.image = None # the actual image file self.texID = None # the texture id created for this image self.imgBox = None # the bounding box (usually from 0 to size) self.quad = None # the box repr the area and pos on the screen self.imgFileName = imgName self.texMgr = None self.setsMgr = SettingsManager() # if an image is specified, load it if self.imgFileName: self.setImg( self.imgFileName ) def setSize( self, size=(1,1) ): self.size = size def setPos( self, pos=[0,0] ): UIObject.setPos(self) self.quad = None def setImg( self, imgName=None ): if imgName: if not self.texMgr: self.texMgr = TextureManager() self.image, self.texID = self.texMgr.load_image(\ os.path.join(self.setsMgr.ui_dir,imgName)) else: self.image = None self.imgBox = None self.quad = None def render( self, scrScroll=(0,0) ): """ Called by the screen on this object to retrieve all necessary info regarding the rendering of this object. The name and arguments for this function should not be changed as it will not be known by the Screen class. """ # make sure an image has been loaded before we try and render if not self.image: print "No image loaded" return [] if not self.visible: return [] # we want the whole image to show, so we provide the entire size as # the texture coords if not self.imgBox: self.imgBox = (0, self.image.size[1], self.image.size[0], 0) if not self.quad: pos = ( self.pos[0]-scrScroll[0], self.pos[1]-scrScroll[1]) if self.centerAround: pos = (pos[0]-self.size[0]/2, pos[1]-self.size[1]/2) self.quad = (pos[0], pos[1], pos[0]+self.size[0], pos[1]+self.size[1]) # return this as a list with one object in it(because screen expects a # list of renderable things from return [ ( self.texID, self.imgBox, self.quad) ]