Back to index

freevial  1.2
freevialglob.py
Go to the documentation of this file.
00001 # -*- coding: utf-8 -*-
00002 
00003 #
00004 # Freevial
00005 # Commonly used stuff
00006 #
00007 # Copyright (C) 2007, 2008 The Freevial Team
00008 #
00009 # By Carles Oriol i Margarit <carles@kumbaworld.com>
00010 # By Siegfried-Angel Gevatter Pujals <siggi.gevatter@gmail.com>
00011 #
00012 # This program is free software: you can redistribute it and/or modify
00013 # it under the terms of the GNU General Public License as published by
00014 # the Free Software Foundation, either version 3 of the License, or
00015 # (at your option) any later version.
00016 #
00017 # This program is distributed in the hope that it will be useful,
00018 # but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020 # GNU General Public License for more details.
00021 #
00022 # You should have received a copy of the GNU General Public License
00023 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
00024 #
00025 
00026 import os.path
00027 import random
00028 import pygame
00029 import locale
00030 import time
00031 import gettext
00032 from pygame.locals import *
00033 
00034 from common.globals import Global
00035 from questions import get_databases
00036 
00037 gettext.install('freevial', '/usr/share/locale', unicode=1)
00038 
00039 textos = []
00040 
00041 
00042 class Equip:
00043        
00044        nom = ''
00045        punts = 0
00046        errors = 0
00047        figureta = 0
00048        actiu = False
00049        eliminat = False
00050 
00051        sfc_nom = None
00052 
00053        def __init__( self ):
00054 
00055               self.preguntes_tot = []
00056               self.preguntes_ok = []
00057 
00058               for num in range(0, 6): 
00059                      self.preguntes_tot.append( 0 )
00060                      self.preguntes_ok.append( 0 )
00061 
00062        def canviaCategoria( self, categoria ):
00063               # Les tenim desendreçades i això ho complica una mica
00064               self.figureta ^= bitCategoria( categoria )
00065 
00066 
00067        def activaCategoria( self, categoria ):
00068               # Les tenim desendreçades i això ho complica una mica
00069               self.figureta |= bitCategoria( categoria )
00070 
00071 
00072        def teCategoria( self, categoria ) :
00073               return (self.figureta & bitCategoria( categoria )) != 0
00074 
00075 
00076 def bitCategoria ( categoria ):
00077        return (0x4,0x8,0x20,0x10,0x2,0x1)[ categoria ]
00078 
00079 
00080 def loadImage( name, colorkey = None, rotate = 0 ):
00081        """ Returns a Surface of the indicated image, which is expected to be in the images folder. """
00082        
00083        fullname = os.path.join(Global.folders['images'], str(name))
00084        
00085        try:
00086               image = pygame.image.load(fullname)
00087        except pygame.error, message:
00088               print _('Failed loading image: %s' % fullname)
00089               raise SystemExit, message
00090        
00091        if colorkey is not None:
00092               if colorkey is -1:
00093                      colorkey = image.get_at((0,0))
00094               image = image.convert()
00095               image.set_colorkey(colorkey, pygame.RLEACCEL)
00096        else:
00097               image = image.convert_alpha()
00098        
00099        if rotate != 0:
00100               image = rotateImage(image, rotate)
00101        
00102        return image  # [ image, image.get_rect() ]
00103 
00104 
00105 def loadSound( name, volume = 1.0, music = False ):
00106        """ Returns a sound object of the indicated audio file, which is expected to be in the sounds folder. """
00107        
00108        if ( Global.MUSIC_MUTE and music ) or ( Global.SOUND_MUTE and not music ) or not pygame.mixer or not pygame.mixer.get_init():
00109        
00110               class NoneSound:
00111                      def load( *args ): pass
00112                      def play( *args ): pass
00113                      def stop( *args ): pass
00114                      def set_volume( *args ): pass
00115               
00116               return NoneSound()
00117        
00118        fullname = os.path.join(Global.folders['sounds'], name)
00119        
00120        try:
00121               if not music:
00122                      obj = pygame.mixer.Sound(fullname)
00123               else:
00124                      obj = pygame.mixer.music
00125                      obj.load(fullname)
00126        except pygame.error, message:
00127               
00128               print _('Failed loading sound: %s' % fullname)
00129               
00130               if not music:
00131                      raise SystemExit, message
00132        
00133        obj.set_volume(float(volume))
00134        
00135        return obj
00136 
00137 default_font = '/usr/share/fonts/truetype/unfonts/UnBatangBold.ttf'
00138 
00139 
00140 def set_default_font( nomfont ):
00141 
00142        if os.path.exists( nomfont ):
00143               default_font = nomfont
00144               
00145 
00146 def render_text( cadena, color, mida, antialias = 0, nomfont = '', maxwidth = 0 ):
00147        """ Function for easier text rendering. """
00148 
00149        global default_font
00150 
00151        if os.path.exists( nomfont ):
00152               font1 = pygame.font.Font( nomfont, mida )
00153        else:
00154               tnomfont = os.path.join(Global.folders['fonts'], default_font if nomfont == '' else nomfont)
00155               if os.path.exists( tnomfont ):
00156                      font1 = pygame.font.Font( tnomfont, mida )
00157               else:
00158                      # NOT WORKING IN PYGAME
00159                      font1 = pygame.font.SysFont( nomfont, mida )
00160               
00161        
00162        text_restant = cadena
00163        sfc = None
00164 
00165        if maxwidth:
00166               sfcs = []
00167 
00168               while text_restant != "":
00169 
00170                      ample = maxwidth + 1
00171                      escriure = text_restant
00172 
00173                      while ample > maxwidth:
00174 
00175                             sfc = font1.render( escriure, antialias, color )
00176                             ample = sfc.get_width()            
00177                      
00178                             if ample > maxwidth:
00179                                    tpos = escriure.rfind( ' ' )
00180                                    if tpos == -1:
00181                                           ample = maxwidth
00182                                    else:
00183                                           escriure = escriure[0:tpos]        
00184 
00185                      sfcs.append( sfc )
00186 
00187                      text_restant = text_restant[ len( escriure )+1:]
00188 
00189               if len(sfcs) > 1:
00190                      iample = 0
00191                      ialt = 0
00192                      for compta in range( 0, len(sfcs) ):
00193                             ialt += max(sfcs[compta].get_height(), mida)
00194                             iample = min(maxwidth, max( iample, sfcs[compta].get_width() ))
00195 
00196                      sfc = pygame.Surface( ( iample, ialt), pygame.SRCALPHA, 32 )
00197 
00198                      pos = 0
00199                      for compta in range( 0, len(sfcs) ):
00200                             sfc.blit( sfcs[compta], (0, pos) )
00201                             pos += max(sfcs[compta].get_height(), mida)
00202 
00203               else:
00204                      sfc = sfcs[0] if len(sfcs) == 1 else None
00205        else:
00206               sfc = font1.render( cadena, antialias, color )
00207 
00208        return sfc
00209 
00210 def screenshot( surface, destination = os.path.join( os.path.expanduser('~'), 'Freevial/Screenshots/' ) ):
00211        """ Saves a screenshot of the indicated surface. """
00212        
00213        destination = os.path.normpath( destination )
00214        
00215        if not os.path.exists( destination ):
00216               os.makedirs( destination )
00217        
00218        # PNG and JPEG saving is new in pygame 1.8.
00219        destination = os.path.join( destination, str( time.time() ) + '.tga' )
00220        
00221        pygame.image.save( surface, destination )
00222 
00223 
00224 def count_not_empty( list, attr = None ):
00225        """ Returns the amount of non-empty elements in a list. Optionally,
00226        if the attr option is set, it will count the amount of elements in
00227        the list that have an attribute named like that which is not empty."""
00228        
00229        count = 0
00230        
00231        for element in list:
00232               if element:
00233                      if not attr or (hasattr(element, attr) and getattr(element, attr)):
00234                             count += 1
00235        
00236        return count
00237 
00238 
00239 def maxPunts( teams ):
00240 
00241        puntsmax = 0
00242 
00243        for num in range( 0, Global.game.max_teams ):
00244               if teams[num].actiu:
00245                      puntsmax = max( puntsmax, teams[num].punts )
00246        
00247        return puntsmax
00248 
00249 
00250 def puntsTotals( teams ):
00251 
00252        punts = 0
00253 
00254        for num in range( 0, Global.game.max_teams ):
00255               punts += teams[num].punts
00256        
00257        return punts
00258 
00259 
00260 def teamsActius( teams ):
00261 
00262        actius = 0
00263 
00264        for num in range( 0, Global.game.max_teams ):
00265               if teams[num].actiu: actius += 1
00266        
00267        return actius
00268 
00269 
00270 def teamsTancat( teams ):
00271 
00272        for num in range( 0, Global.game.max_teams ):
00273               if teams[num].figureta == 63:
00274                      return True
00275        
00276        return False
00277 
00278 
00279 def teamsGuanyador( teams, mode, extra ):
00280 
00281        # Mode 0 - Figureta de 6 peces completa i una diferència de més de 2 punts respecte a l'equip anterior. Guanyador a punts
00282        # Mode 1 - Aconseguir un nombre determinat de punts
00283        # Mode 2 - Ser el darrer equip en fer X cagades
00284        # Mode 3 - Omplir la figureta de 6 peces
00285 
00286        guanyador = -1
00287 
00288        if mode == 0:
00289               puntsmax = 0
00290               equipmax = -1
00291 
00292               if teamsTancat( teams ):
00293 
00294                      for num in range( 0, Global.game.max_teams ):
00295                             if teams[num].actiu:
00296                                    if teams[num].punts == puntsmax:
00297                                           # empat a punts
00298                                           equipmax = -1 
00299 
00300                                    if teams[num].punts > puntsmax:
00301                                           equipmax = num
00302                                           puntsmax = teams[num].punts
00303        
00304               guanyador = equipmax
00305        
00306        elif mode == 1:
00307               
00308               for num in range( 0, Global.game.max_teams ):
00309                      if teams[num].punts >=  extra:
00310                             guanyador = num
00311        
00312        elif mode == 2:
00313               nocagats = []
00314               for num in range( 0, Global.game.max_teams ):
00315                      if teams[num].errors <  extra:
00316                             nocagats.append( num )
00317               if len(nocagats) == 1:
00318                      guanyador = nogacats[0]
00319        
00320        elif mode == 3:
00321               for num in range( 0, Global.game.max_teams ):
00322                      if teams[num].figureta == 63:
00323                             guanyador = num
00324        
00325        return guanyador
00326 
00327 
00328 def seguentEquipActiu( teams, actual ):
00329 
00330        actual += 1
00331 
00332        for num in range(0, Global.game.max_teams ):
00333               if teams[ (actual + num) % Global.game.max_teams ].actiu: 
00334                      return (actual + num) % Global.game.max_teams
00335        
00336        return -1
00337 
00338 
00339 def anteriorEquipActiu( teams, actual ):
00340 
00341        actual -= 1
00342 
00343        for num in range( 0, Global.game.max_teams ):
00344               if teams[ (actual - num ) % Global.game.max_teams ].actiu: 
00345                      return (actual - num ) % Global.game.max_teams
00346        
00347        return -1
00348 
00349 
00350 def list2string( list, wordsEachLine = 5, lineEnd = ',' ):
00351        """ Converts a list of words into a list of comma-separated string with 'wordsEachLine' words. """
00352        
00353        lines = []
00354        string = ''
00355        i = 0
00356        
00357        for author in list:
00358               
00359               if string != '':
00360                      string += ', '
00361               
00362               string += author
00363               
00364               if (wordsEachLine - 1) == (i % wordsEachLine):
00365                      lines.append( str(string + lineEnd) )
00366                      string = ''
00367 
00368               i += 1
00369               
00370        if string != '':
00371               lines.append( str(string + lineEnd) )
00372        
00373        lines[-1] = lines[-1][:-len(lineEnd)]
00374        
00375        return lines
00376 
00377 
00378 def createTextSurface( frases, color, intensitat = 25 ):
00379        """ Creates a help overlay surface and prints the passed text on it. """
00380        
00381        font_step = (768 - (315)) / len(frases) 
00382        font_step = min( font_step, 25 )
00383 
00384        font_size = font_step - (font_step * 10) / 100
00385        if font_size < 10: font_size = 10
00386  
00387        help_overlay = pygame.Surface( ( 1024, 768), pygame.SRCALPHA, 32 )
00388        
00389        for num in range( 0, 10):
00390               help_overlay.fill( (0, 0, 16, num * intensitat), ( 100 + (num * 2), 100 + (num * 2), 1024 - 100 * 2 - (num * 4), 768 - 150 - (num * 4)) )
00391        
00392        nline = 0
00393 
00394        pos = 0
00395        for line in frases:
00396               if line != "":       
00397                      text_pregunta = render_text( line, (0,0,0), font_size, 1, '', 700 )
00398                      help_overlay.blit( text_pregunta, (150 + 2, pos + 142))
00399                      
00400                      text_pregunta = render_text( line, color, font_size, 1, '', 700 )
00401                      help_overlay.blit( text_pregunta, (150, pos + 140))
00402                      
00403                      pos += text_pregunta.get_height()
00404               else:
00405                      pos += font_size     
00406 
00407               nline += 1
00408        
00409        return help_overlay
00410 
00411 
00412 def replaceKeywoards( content ):
00413        """ Replaces keywoards found in the content a help file. """
00414        
00415        for num in range(0, len(content)):
00416               content[num] = unicode(content[num], 'utf-8')
00417        
00418        for (i, line) in enumerate(content):
00419               if line.startswith( '##replace:question-authors' ):
00420                      content[ i : (i + 1) ] = sorted(["%s: %s" % (category.name, category.authors) for category in get_databases()])
00421        
00422        return content
00423 
00424 
00425 def readLocalizedHelpFile( help_section ):
00426        """ Reads a localized file into an unicoded array. """
00427        
00428        # FIXME/TODO: Delete help files and use gettext strings instead.
00429        
00430        filename = os.path.join(Global.folders['help'], (help_section + "_"+ locale.getdefaultlocale()[0][:2] +'.txt'))
00431        
00432        if not os.path.exists (filename):
00433               filename = os.path.join(Global.folders['help'], (help_section + '.txt'))
00434        
00435        lines = []
00436        
00437        for line in replaceKeywoards(open( filename, 'r' ).readlines()):
00438               
00439               if not line[-1:].isalnum():
00440                      line = line[:-1]
00441               
00442               lines.append ( line )
00443        
00444        return lines
00445 
00446 
00447 def createHelpScreen( help_section, alternate_text = False ):
00448        """ Creates a help overlay surface based on a help file. """
00449        
00450        return createTextSurface( readLocalizedHelpFile( help_section ), (0, 255, 255) if alternate_text else (255, 255, 0) )
00451 
00452 i_colors_cat = ( (0,0,255), (255,128,0), (0,255,0),(255,0,0),(255,0,255), (255,255,0) )
00453 
00454 
00455 def initTextos():
00456        global textos
00457 
00458        textos = readLocalizedHelpFile( "textos" )
00459 
00460 
00461 def valorText( ntext ):
00462        return textos[ ntext ]
00463 
00464 
00465 def colorsCategories():
00466 
00467        return i_colors_cat
00468 
00469 
00470 def firstExistingDirectory(name, *dirs):
00471        """ Searches for a directory called by the given name inside all given
00472        directories, and returns the full path to the first one which exists. """
00473        
00474        for directory in dirs:
00475               if os.path.isdir( os.path.join(directory, name) ):
00476                      return os.path.join(directory, name)
00477        
00478        return False
00479 
00480 
00481 HOS_SCORE_MODE0 = 0
00482 HOS_SCORE_MODE1 = 1
00483 HOS_SCORE_MODE2 = 2
00484 HOS_QUIT = 3
00485 HOS_YES = 4
00486 HOS_NO = 5
00487 HOS_PREGUNTADOR_RUN = 6
00488 HOS_PREGUNTADOR_END = 7
00489 HOS_SCORE_MODEW = 8
00490 HOS_RODA_ATURA = 9
00491 HOS_NEW_GAME = 10
00492 
00493 
00494 class helpOnScreen():
00495        
00496        text = ''
00497        scf_text = None
00498        sec_darrera_activitat = -1
00499        sec_timeout = 10
00500 
00501        intensitat = 5
00502        
00503        
00504        def __init__( self, itext ):
00505               
00506               self.creaTextdeTextos ( itext )
00507               self.sec_darrera_activitat = time.time()  
00508        
00509        
00510        def creaTextdeTextos(self, itext ):
00511               
00512               global textos
00513               self.creaText( textos[itext] )
00514        
00515        
00516        def creaText( self, ptext ):
00517               
00518               if self.text != ptext :
00519                      self.text = ptext
00520                      self.sfc_text = render_text( self.text, (128,128,128), 15, 1 )
00521        
00522        
00523        def draw( self, surface, pos, itext = None ):
00524               
00525               if time.time() >= self.sec_darrera_activitat + self.sec_timeout :
00526                      
00527                      if itext: self.creaTextdeTextos ( itext )
00528                      surface.blit( self.sfc_text, pos )
00529        
00530        
00531        def activitat( self, event = None ):
00532               
00533               if not event or event.type == pygame.KEYUP :
00534                      self.sec_darrera_activitat = time.time()
00535 
00536 
00537 class frameRate():
00538        """ Calculates the frame rate (FPS), limits it and, if choosen so, displays it on screen. """
00539        
00540        seconds = fps = fps_current = fps_limit = lastTicks = t_inici = 0
00541        textSurface = None
00542        
00543        def __init__( self, fps_limit = 0 ):
00544               self.fps_limit = fps_limit
00545               self.lastTicks = pygame.time.get_ticks()
00546               self.t_inici = time.time()
00547        
00548        def segons( self ):
00549               return time.time() - self.t_inici
00550 
00551        def next( self, surface = None ):
00552               
00553               if time.time() > self.seconds + 1:
00554                      self.seconds = time.time()
00555                      self.fps = self.fps_current
00556                      self.fps_current = 0
00557                      if Global.DISPLAY_FPS:
00558                             self.textSurface = render_text( 'FPS: ' + str( self.fps if self.fps > 0 else 'N/a' ), (128, 128, 128), 15, 1 )
00559               else:
00560                      self.fps_current += 1
00561               
00562               limit_fps = 1000 / self.fps_limit
00563               limit_ticks = pygame.time.get_ticks() - self.lastTicks
00564               
00565               if limit_ticks < limit_fps:
00566                      pygame.time.wait( limit_fps - limit_ticks )
00567                      self.lastTicks = pygame.time.get_ticks()
00568 
00569               if surface:   
00570                      if self.textSurface and Global.DISPLAY_FPS:
00571                             # display the frame rate on the middle of the screen's bottom
00572                             #surface.blit( self.textSurface, ( (( Global.screen_x / 2 ) - ( self.textSurface.get_width() / 2 )), 740 ) )
00573                             surface.blit( self.textSurface, (250, 740 ) )