Exemple #1
0
    def __init__(self, size):
        """ Constructeur
        Entrée : size : tuple de 2 int. Largeur et hauteur de l'arène, en nombre de Component.
        """
        # init des différentes variables contenant la taille de l'arène.
        # TRODO : virer les variables qui servent à rin.
        self.size = size
        self.width = size[0]
        self.height = size[1]
        self.rectSize = pyRect(0, 0, self.width, self.height)
        # Init diverses
        self.listMarble = []
        self.listMarbleToRemove = []
        self.listMarbleExplosion = []

        # Init du tableau à 2 dimensions contenant les Components. 
        # C'est une liste de "height" éléments.
        # Chacun de ces éléments est une sous-liste, contenant "width" Component.
        self.matrixComponent = []        
        # Pour l'init, on crée les listes et sous-listes avec que des ComponentNothing.
        for _ in xrange(self.height):
            lineComponent = [ ComponentNothing(pyRect(0, 0))
                              for _ in xrange(self.width) ]
            self.matrixComponent.append(lineComponent)

        # Provisoire. Placement des Component pas Nothing, à la main.
        self.matrixComponent[1][2] = ComponentSimplePipe("osef", UP, RIGHT)
        self.matrixComponent[1][3] = ComponentSimplePipe("osef", UP, LEFT)
        self.matrixComponent[0][3] = ComponentSimplePipe("osef", RIGHT, DOWN)
Exemple #2
0
    def generateRandPattern(self, nbrMagi, coordEnd=None):
        """
        génère un pattern de magicien avec tout random : les positions de départ et d'arrivée

        entrées :
            nbrMagi : int. nombre de magicien à mettre dans le pattern.
            coordEnd : si None, on ne fabrique pas les coordonnées de fin
                       si autre chose, on les fabrique.

        plat-dessert :
            tuple de 2 éléments :
             déjà blablaté dans les fonctions plus haut. S'y référer, bordel
        """

        #création d'une liste de Rect avec les coordonnées complètement random,
        #mais comprises dans l'aire de jeu, quand même.
        listCoordStart = [ pyRect(randRange(GAME_RECT.width) + GAME_RECT.left,
                                  randRange(GAME_RECT.height) + GAME_RECT.top)
                           for _ in xrange(nbrMagi)
                         ]

        #si on n'a pas demandé les coordonnées d'arrivée des magiciens, on s'en va direct.
        if coordEnd is None:
            return listCoordStart, None

        #création d'une autre liste de Rect random, pour les coordonnées d'arrivée
        listCoordEnd = [ pyRect(randRange(GAME_RECT.width) + GAME_RECT.left,
                                randRange(GAME_RECT.height) + GAME_RECT.top)
                         for _ in xrange(nbrMagi)
                       ]

        return listCoordStart, listCoordEnd
Exemple #3
0
    def initBursting(self):
        """
        Fonction pemettant d'initialiser l'anim
        et les SpriteSimple du magicien qui explose (BURST)
        """

        self.currentState = BURSTING

        #son : "spflark !!"
        theSoundYargler.playSound(SND_MAG_BURST)

        # --- génération des parties du corps ensanglantés qui s'envolent ---
        # chaque partie du corps est un simple sprite, générée bien comme il
        # faut par le SimpleSpriteGenerator. La position de départ des parties
        # du corps est prise à partir de la position du magicien, avec un petit
        #décalage en plus.

        #le bras droit
        armPosStartRight = self.rect.move(pyRect(10, 2).topleft)
        self.spriteSimpleGenerator.generateMagBurstArmRight(armPosStartRight)

        #le bras gauche
        armPosStartLeft = self.rect.move(pyRect(0, 2).topleft)
        self.spriteSimpleGenerator.generateMagBurstArmLeft(armPosStartLeft)

        #la tête
        headPosStart = self.rect.move(pyRect(5, -3).topleft)
        self.spriteSimpleGenerator.generateMagBurstHead(headPosStart)

        #le simple sprite de l'anim du corps en train d'exploser.
        self.spriteSimpleGenerator.generateMagBurstSplat(self.rect)
Exemple #4
0
    def addSpriteSimple(self, listImgInfo, posStart,
                        nbrImgLoop=IMG_LOOP_ETERNAL,
                        endCondition=END_ON_OUT_GAME_AREA,
                        moveRect=pyRect(), movePeriod=NONE_COUNT,
                        accelRect=pyRect(), accelPeriod=NONE_COUNT,
                        makeDecalCenter=False):
        """
        fonction pour ajouter un SpriteSimple dans le SpriteSimpleManager.

        entrées : voir fonction SpriteSimple.__init__
                  c'est le même bazar.

        plat-dessert : le spriteSimple généré.
        """

        #création du nouveau SpriteSimple, en transmettant les paramètres, juste paf comme ça.
        paramSprite = (listImgInfo, posStart, nbrImgLoop, endCondition,
                       moveRect, movePeriod, accelRect, accelPeriod,
                       makeDecalCenter)

        spriteSimple = SpriteSimple(*paramSprite)

        #ajout du nouveau sprite dans le gros groupe global allSprites, et dans le petit
        #groupe personnel du SpriteSimpleManager.
        self.allSprites.add(spriteSimple)
        self.simpleSpriteGroup.add(spriteSimple)

        #on renvoie le spriteSimple généré, ça peut éventuellement servir pour le code extérieur
        return spriteSimple
Exemple #5
0
    def initDyingNaked(self):
        """
        Fonction à lancer lorsque le magicien va crever dans l'animation DYING_NAKED.

        On peut pas se contenter de génrer cette anim avec uniquement des SpriteSimple,
        car le magicien, quand il s'envole tout nu, génère des petits nuages de pets.
        Les nuages de pets sont des SpriteSimple. Mais leur génération ne peut pas
        être confiée à un SpriteSimple, car ils ne sont pas prévus pour ça.

        Donc l'objet magicien est toujours présent pendant un DYING_NAKED,
        et on le détruit lorsque l'anim est finie.
        """

        self.currentDyingState = DYING_NAKED

        #changement de l'image du sprite, et application du décalage qui va avec
        self.image = self.dicMagicienImg[IMG_DYING_NAKED]
        self.rect.move_ip(DECAL_DYING_NAKED.topleft)

        #initialisation des trucs pour le mouvement. (vers le haut, sans accel)
        #en fait y'aura une accel en X, aléatoire vers la gauche ou la droite,
        #mais on la rajoutera plus tard.
        self.moveCounter = DYIND_NAKED_MOVE_PERIOD
        self.speed = pyRect(0, -4)
        self.currentAccel = pyRect()

        #ça y'en aura besoin pour savoir quand le magicien est sorti de l'écran.
        self.image_height = self.image.get_height()

        #compteur avant le prochain pets, pour savoir quand générer un SimpleSprite de type "Fume"
        self.fartCounter = randRange(FART_PERIOD_MIN, FART_PERIOD_MAX)
Exemple #6
0
 def populateArena(self):
     """ overriden """
     for (coordX, coordY) in LIST_COORD_ASPRO_HALF_LEFT:
         tileToHardDefine = self.arena.getTile(pyRect(coordX, coordY))
         tileToHardDefine.chip = ChipAsproHalfLeft()
     for (coordX, coordY) in LIST_COORD_ASPRO_HALF_RIGHT:
         tileToHardDefine = self.arena.getTile(pyRect(coordX, coordY))
         tileToHardDefine.chip = ChipAsproHalfRight()
Exemple #7
0
    def createMatrixTile(self):
        """
        crée l'arène, avec la matrix des Tile. Et place une Chip dans chaque Tile.
        Les Chip sont déterminées au hasard.
        """

        self.matrixTile = []

        #youpi. Bon, vaut mieux une boucle que des list comprehension imbriquées, à mon avis.
        for y in xrange(self.height):

            lineTile = []

            for x in xrange(self.width):

                posArenaTile = pyRect(x, y)
                posPixelTile = self.posPixelFromPosArena(posArenaTile)

                newChip = self.createChipAtStart()

                param = (self.surfaceDest, posArenaTile, posPixelTile,
                         newChip, self.nbrPlayer)

                newTile = Tile(*param)

                lineTile.append(newTile)

            self.matrixTile.append(lineTile)
Exemple #8
0
    def populateArena(self):
        """ overrides """
        # on définit des tiles. C'est mignon et gentil.
        for hardData in self.listTileToHardDefine:
            coord = hardData[0]
            typeTile = hardData[1][0]
            tileToHardDefine = self.arena.getTile(pyRectTuple(coord))
            if typeTile == "C":
                brouzouf = hardData[1][1]
                tileToHardDefine.chip = ChipCoin(brouzouf)
            else:
                tileToHardDefine.chip = ChipSugar()

        tileToHardDefine = self.arena.getTile(pyRect(4, 3))
        tileToHardDefine.chip = ChipAsproHalfLeft()
        tileToHardDefine = self.arena.getTile(pyRect(6, 3))
        tileToHardDefine.chip = ChipAsproHalfRight()
Exemple #9
0
    def razMovementAndAcceleration(self):
        """
        fixe le mouvement et l'accélération à (0,0) : pas de mouvement, et pas d'accel
        initialise les compteurs pour les périodes de mouvement et d'accélération.
        """

        #les vecteurs de mouvement et d'accélération sont stockés dand des Rects,
        #dont osef le width et le height.
        #Ca permet de profiter de toutes les fonctions cool des Rects (move, clamp, ...)

        #compteur pour l'accélération
        self.accelCounter = ACCEL_PERIOD
        #accélération à (0, 0)
        self.currentAccel = pyRect()

        #compteur pour le mouvement
        self.moveCounter = MOVE_PERIOD
        #mouvement à (0, 0)
        self.speed = pyRect()
Exemple #10
0
    def initCommonStuff(self, surfaceDest, gravityDir, tutorialScheduler=None):
        """ zob
        TRODO : c'est un peu le bordel d'avoir foutu ça là.
        Du coup, quand on regarde dans l'init, on se rend pas compte que y'a
        toutes ces variables membres. donc, c'est mal de faire ça.
        """
        self.surfaceDest = surfaceDest
        self.blinker = None
        self.tutorialScheduler = tutorialScheduler
        self.console = Console(self.surfaceDest, pyRect(400, 10, 235, 460), nbCharMax=25)
        self.console.addText(language.TEXT_HELLO[language.languageCurrent])
        self.console.refresh()
        self.console.display()
        self.manual = ManualInGame(
            self.surfaceDest,
            pyRect(10, 340, 400, 130),
            self.tutorialScheduler)
        self.manual.refresh()
        self.manual.display()

        self.posPixelArena = pyRect(10, 10)

        param = (self.posPixelArena, ARENA_SIZE, TILE_PIXEL_SIZE)
        self.stimuliStocker = StimuliStockerForGame(*param)

        #Ca c'est le putain d'objet qui permet de maîtriser le temps !!!
        #Talaaaa, je suis le maître du temps. et des frames par secondes aussi.
        self.clock = pygame.time.Clock()

        if gravityDir is None:
            self.crawlerGrav = None
            self.gravityMovements = None
            self.crawlerRegen = None
        else:
            (gravPrimDir, gravSecDir, primCoordIsX, gravIncsCoord,
             regenPrimDir, regenSecDir) = DICT_GRAVITY_CONFIG[gravityDir]
            self.crawlerGrav = ArenaCrawler(ARENA_SIZE)
            self.crawlerGrav.config(gravPrimDir, gravSecDir)
            param = (gravityDir, primCoordIsX, gravIncsCoord)
            self.gravityMovements = GravityMovements(*param)
            self.crawlerRegen = ArenaCrawler(ARENA_SIZE)
            self.crawlerRegen.config(regenPrimDir, regenSecDir)
Exemple #11
0
def posScreenFromPosArenaMarble(posArena):
    """
    Position à l'écran d'une marble dans une tile, lorsqu'elle n'est pas en train
    de se déplacer d'une tile à une autre. (C'est à dire qu'elle est au milieu de la tile). 
    Entrée : position (X, Y) de la tile dans l'arène.
    Sortie : position (X, Y) à l'écran, en caractère, de la marble.
    """
    # Même décalage que pour posScreenFromPosArenaTile
    # Re-re-décalage de (1, 1) pour placer la marble à peu près au milieu du Component.
    return pyRect(posArena.x * TILE_WIDTH + 3,
                  posArena.y * TILE_HEIGHT + 2)
Exemple #12
0
def posScreenFromPosArenaTile(posArena):
    """
    Position à l'écran du coin haut-gauche d'une tile. 
    Entrée : position (X, Y) de la tile dans l'arène.
    Sortie : position (X, Y) à l'écran, en caractère, du coin haut-gauche de la tile.
    """
    # Décalage de (1, 1) à cause de la bordure de l'arène.
    # Re-décalage de (1, 0) à cause de la colonne de caractère espace à gauche de l'arène.
    # (Voir explication dans ArenaDisplayer pour savoir d'où vient cette colonne d'espace).
    return pyRect(posArena.x * TILE_WIDTH + 2,
                  posArena.y * TILE_HEIGHT + 1)
Exemple #13
0
def calculateListTotalMove(mainMove, listSecMove, indexSecMove):
    """
    calcule une listTotalMove à partir d'un déplacement secondaire et
    d'un déplacement primaire donné.

    entrées :
        mainMove     : rect (X, Y) indiquant le déplacement principal.
                       ce déplacement sera appliqué à chaque cycle..

        listSecMove  : liste de int, représentant le déplacement secondaire.
                       A chaque cycle, on utilise l'élément courant de cette liste
                       pour se déplacer sur une coordonnée (X ou Y), et on avance d'un élément

        indexSecMove : index de coordonnés sur laquelle appliquer le mouvement secondaire.
                       il faut indiquer : MOVE_ON_X, MOVE_ON_Y ou MOVE_NONE

    plat-dessert :
        listTotalMove : liste de Rect (X, Y)
    """
    #construction de listSecMoveCoords : une liste de tuple (X,Y) contenant la succession
    #de mouvement secondaire. (le mouvement est placcé dans la bonne coordonnée)
    if indexSecMove == MOVE_ON_X:
        listSecMoveCoords = [ pyRect(elem, 0) for elem in listSecMove ]
    elif indexSecMove == MOVE_ON_Y:
        listSecMoveCoords = [ pyRect(0, elem) for elem in listSecMove ]
    else:
        #pas de mouvement secondaire. Donc une liste d'un seul elem avec des 0
        listSecMoveCoords = [ pyRect(0, 0), ]

    #on ajoute le mouvement principal à cette liste de tuple(X,Y)
    #contenant les mouvements secondaires.
    #comme ça, on a une liste contenant la somme des deux mouvements.
    listSecMoveCoords = [ rectElem.move(mainMove.topleft)
                          for rectElem in listSecMoveCoords
                        ]

    #transformation de la liste en tuple, juste parce que c'est cool.
    #et utilisation d'un autre nom.
    listTotalMove = tuple(listSecMoveCoords)

    return listTotalMove
Exemple #14
0
    def posPixelFromPosArena(self, posArena):
        """
        conversion position d'une Tile dans l'Arène -> position en pixel à l'écran,
        Entrées : posArena. Rect. Position de la tile dans l'arène.
        Sorties : Rect. Position en pixel, à l'écran, du coin sup gauche de la Tile.
        La fonction ne vérifie pas si la position en param existe vraiment dans l'arène.
        Elle convertit et puis c'est tout.

        TRODO : A mettre dans la View ?? Oui jconfirme
        """
        return pyRect(posArena.x*ARENA_TILE_WIDTH + self.posPixelTopLeft.x,
                      posArena.y*ARENA_TILE_HEIGHT + self.posPixelTopLeft.y)
Exemple #15
0
    def refresh(self):
        """ zob """
        self.imgConsole.fill((0, 0, 0))
        posText = pyRect()

        indexTextEnd = min(len(self.listColoredText),
                           self.nbMaxLine+self.cursorText)

        for coloredText in self.listColoredText[self.cursorText:indexTextEnd]:
            colorToWrite = coloredText[0]
            textToWrite = coloredText[1]
            imgText = self.fontConsole.render(textToWrite, 0, colorToWrite)
            self.imgConsole.blit(imgText, posText)
            posText.move_ip(self.verticalSpaceMove)
Exemple #16
0
    def defineSpeedLimitClampingFromSpeedLimit(self):
        """
        définit l'attribut self.speedLimitClamping, en fonction de l'attribut self.speedLimit
        self.speedLimitClamping est un rect centré sur 0,
        et ayant comme demi-longueur self.speedLimit
        on pourra s'en servir pour limiter la vitesse courante,
        qui doit rester dans les valeurs de speedLimit.
        Et y'aura juste besoin d'un simple clamping, plutôt qu'un tas de if à la con.
        """

        #on définit spd, juste pour raccourcir le nom, sinon c'est chiant.
        spd = self.speedLimit
        #le rect va du point (-spd, -spd) jusqu'au point (+spd, +spd)
        self.speedLimitClamping = pyRect(-spd, -spd, 2*spd, 2*spd)
Exemple #17
0
 def blitImg(self, posScreen, img):
     """
     blitte une image sur la grande image principale de l'arène.
     Entrées : posScreen : Rect. Position sur l'image d'arrivée, en caractère, 
                           du coin haut-gauche de l'image à blitter.
               img : image à blitter. (liste de string). Les strings composant cette image
                     peuvent avoir des tailles différentes, osef. (Même si ça serait zarbi).
                     Pas de verif ni de tronquage si la longueur d'une des string 
                     est trop grande. (voir description de bitSlice)
     """
     # clonage du Rect contenant les coordonnées de destination du blittage. Car on va
     # le modifier au fur et à mesure qu'on blitte.
     posScreenLocal = pyRect(posScreen.left, posScreen.top)
     # Blittage des lignes de caractère composant l'image, les unes après les autres.
     # A chaque blittage de ligne, on descend d'un caractère pour la ligne suivante.
     for strSlice in img:
         self.blitSlice(posScreenLocal, strSlice)
         posScreenLocal.move_ip((0, +1))
Exemple #18
0
    def updateHurt(self):
        """
        update du magicien (fonction à lancer à chaque cycle de jeu)
        cas où le magicien s'est pris une/plusieurs bullet. (HURT)

        le magicien a un mouvement de recul, tous les X cycles.
        Puis il revient à l'état ALIVE
        """

        #là, on n'exécute pas la super-classe. Sinon le magicien se fait unHurt
        #tout de suite, et c'est pas ce qu'on veut.

        self.hurtCounter -= 1

        if self.hurtCounter <= 0:

            self.hurtCounter = self.hurtPeriod

            #on récupère la distance de mouvement du Hurt, et on le fout en deplacement X
            #pas de déplacement Y pendant un HURT. osef.
            moveXHurt = self.listMovementXWhenHurt[self.hurtMovementCursor]
            moveHurt = pyRect(moveXHurt, 0)

            #application du mouvement du Hurt, et clamping du magicien dans l'écran.
            self.rect.move_ip(moveHurt.topleft)
            self.rect.clamp_ip(MAGI_RECT_CLAMPING)

            #déplacement du curseur pointant sur le mouvement de Hurt courant.
            self.hurtMovementCursor -= 1

            #Si le curseur arrive au début de la liste, on a fait tous les mouvements
            #de recul du Hurt. Le magicien revient à son état normal (ALIVE)
            if self.hurtMovementCursor == 0:

                #on réinitialise son mouvement et son accélération à (0, 0) (bien fait !)
                self.razMovementAndAcceleration()
                self.unHurt()
Exemple #19
0
    def refreshAllScreen(self):
        """
        Réactualise tout le contenu de la grande image de l'arène.
        Attention ! Cette fonction ne doit pas être appelée pendant qu'on est en train
        de dérouler des cycles d'animation. Car ça n'afficherait pas tout comme il faut.
        On ne doit l'appeler que pendant la résolution d'un cycle de jeu.
        La fonction réaffiche tous les Components, et toutes les marbles.
        """
        # On parcourt tous les Component de l'arène
        # TRODO : need a crawler, pour parcourir plus classieusement ?
        for y in xrange(self.arena.height):
            for x in xrange(self.arena.width):
                posArena = pyRect(x, y)
                posScreen = posScreenFromPosArenaTile(posArena)
                component = self.arena.getComponent(posArena)
                # Détermination de l'image correspondant au Component en cours à afficher.
                # not TRODO : on pourrait garder ces images en mémoire, quelque part. Pour
                # ne pas avoir à redéterminer l'image à chaque fois. On va pas le faire, car ça
                # ralentit pas trop (on est en mode texte !). De plus, certaines images de
                # Components pourront changer au cours du jeu. (ex : switch, reset, ...)
                img = self.componentDisplayer.imgFromComponent(component)
                # Blit de l'image du Component sur l'image principale de l'arène.
                self.blitImg(posScreen, img)

        # On parcourt toutes les marbles de l'arène, et on les affiche.
        # On tient pas compte des marble hidden, ni des marble en mouvement. Il est pas
        # censé y avoir ce genre de trucs lorsqu'on n'est pas en train de dérouler une anim.
        for marble in self.arena.listMarble:
            posScreen = posScreenFromPosArenaMarble(marble.pos)
            self.blitImg(posScreen, IMG_MARBLE)

        # On parcourt tous les SimpleSprite, et on les affiche.
        # En fait ça sert à rien mais pour l'instant. Car pas de SimpleSprite si pas pendant
        # une anim. Mais peut-être pour plus tard.
        for simpleSprite in self.listSimpleSprite:
            self.blitImg(simpleSprite.posScreen, simpleSprite.getCurrentImg())
Exemple #20
0
    def draw(self, surfaceDest):
        """
        dessinage de l'élément de menu, sur une surface de destination.
        (voir description de la fonction dans la classe MenuElem)
        """

        #Le self.glowColorIndex se met à jour tout seul, avec la fonction update héritée
        #(voir MenuSensitiveText)
        currentColor = self.glowColorList[self.glowColorIndex]

        #On blite l'image du texte. Récupérée depuis le lamoche interne
        surfaceDest.blit(self.theLamoche.image, self.rectDrawZone)

        #Récupération de la position X du curseur. Il se trouve à droite du texte,
        #à une petite distance de marge de 2 pixel.
        cursorX = self.rectDrawZone.x + self.theLamoche.image.get_width() + 2

        #création du mini-rectangle représentant le curseur. Sa largeur est de 2 pixels.
        #Sa hauteur est celle de la hauteur de la zone de dessin.
        rectCursor = pyRect(cursorX, self.rectDrawZone.y,
                            2, self.rectDrawZone.height)

        #Maintenant qu'on a la position et la couleur du curseur, on le dessine.
        pygame.draw.rect(surfaceDest, currentColor, rectCursor)
Exemple #21
0
    def posArenaFromPosPixel(self, posPixel):
        """
        conversion position en pixel à l'écran -> position d'une Tile dans l'Arène
        Entrées : posPixel. Rect. Position en pixel, à l'écran, de n'importe quel point de la Tile
        Sorties : Soit un Rect : Position de la tile correspondante dans l'arène.
                  Soit None : la position en pixel ne correspond à aucune Tile.
        Donc y'a une verif dans cette fonction. OKay ?

        A mettre dans la View, ou dans le controleur qui va taper dedans ??
        je sais pas si elle a quelque chose à foutre là cette fonction
        """
        #TRODO : c'est tout pouillave car on fait les calculs avant la verif.
        # Faut inverser. (Et donc connaître le coin bas droite de l'Arena.
        #A faire quand on séparera en MVC comme il faut.
        if self.rectPixelArena.contains(posPixel):

            posX = (posPixel.x - self.rectPixelArena.x) / self.widthPixelTile
            posY = (posPixel.y - self.rectPixelArena.y) / self.heightPixelTile
            posArena = pyRect(posX, posY)
            return posArena

        else:

            return None
Exemple #22
0
 def refresh(self):
     """ zob """
     # Je convertis le tuple en une liste, parce que je vais faire des pop dessus.
     # Donc faut que je puisse le modifier.
     manualTexts = list(language.MANUAL_TEXTS[language.languageCurrent])
     self.imgManual.fill((0, 0, 0))
     pygame.draw.rect(self.imgManual, COLOR_DEFAULT, pyRect(0, 0, 340, 127), 2)
     colorToWrite = COLOR_DEFAULT
     textToWrite = manualTexts.pop(0)
     imgText = self.fontManual.render(textToWrite, 0, colorToWrite)
     self.imgManual.blit(imgText, pyRect(10, 5))
     textToWrite = manualTexts.pop(0)
     imgText = self.fontManual.render(textToWrite, 0, colorToWrite)
     self.imgManual.blit(imgText, pyRect(10, 25))
     textToWrite = manualTexts.pop(0)
     imgText = self.fontManual.render(textToWrite, 0, colorToWrite)
     self.imgManual.blit(imgText, pyRect(10, 45))
     if self.tutorialScheduler is not None:
         textToWrite = manualTexts.pop(0)
         imgText = self.fontManual.render(textToWrite, 0, colorToWrite)
         self.imgManual.blit(imgText, pyRect(10, 85))
         textToWrite = manualTexts.pop(0)
         imgText = self.fontManual.render(textToWrite, 0, colorToWrite)
         self.imgManual.blit(imgText, pyRect(10, 100))
Exemple #23
0
    def __init__(self, surfaceDest, dicImg, fontDefault):
        """
        constructeur. (thx captain obvious)

        entrée :

            surfaceDest, dicImg : voir constructeur de MenuManager

            fontDefault : objet pygame.font.Font. police de caractères par défaut.
        """

        MenuManager.__init__(self, surfaceDest, dicImg)

        self.fontDefault = fontDefault

        imgFrame = self.dicImg[IMG_FRAME_NAME]
        imgButtonOK = self.dicImg[IMG_BUTT_OK]

        # --- Création des éléments du menu ---

        #image statique de l'espèce de fenêtre qu'on fout au milieu de l'écran.
        #mimgFrameName, ça veut dire : l'image de la Frame pour saisir le Name.
        #Et non pas : l'image du nom de la frame. Parce que ça voudrait rien dire. OK put'neg' ?
        mimgFrameName = MenuImage(pyRect(100, 110), imgFrame)

        #création du texte statique demandant au joueur de saisir son nom.
        param = (pyRect(120, 115), self.fontDefault, txtStock.ENTER_NAME)
        mtxtEnterName = MenuText(*param)

        #création du bouton OK. Alors ce bouton, c'est juste une image (de bouton),
        #avec le mot "OK" écrit dessus. Le texte est vraiment en dur de dur.
        #C'est crado, je reconnais. Heureusement que "OK" c'est aussi bien anglais que français.
        param = (pyRect(185, 170), imgButtonOK, self.mactOK)
        mbutiOK = MenuSensitiveImage(*param)

        #Création du MenuElem permettant de saisir une chaîne de caractère (le nom du joueur).
        #La zone de saisie est initalisée avec le nom "officiel" du héros.
        #rah, j'aime pas cette formulation. Tous les param sont coincés à droite, et ça
        #prend plein de ligne pour que d'alle. Mais je peux pas faire ma bidouille de *param,
        #car y'en a qui sont nommé. Ou alors avec un dict mais ça devient vraiment lourd
        #TRODO : au fait c'est bien ou mal, cette écriture *param ? Je l'ai fait partout...
        self.meditPlayerName = MenuEditableText(pyRect(120, 140, 160, 20),
                                                self.fontDefault,
                                                text=NAME_HERO,
                                                maxNbrChar=15)

        #création des menuElem liant des touches à des fonctions.

        #liaisonnage des deux touches entrée à la fonction de validation du nom.
        #(C'est la même fonction que celle qui est liée à l'appui sur le bouton "OK")
        mkeyEnterOK_1 = MenuSensitiveKey(self.mactOK, pygl.K_RETURN)
        mkeyEnterOK_2 = MenuSensitiveKey(self.mactOK, pygl.K_KP_ENTER)

        #liaisonnage de la fonction de quittage à la touche Escape.
        #(C'est pas le quittage classique. Voir description de la fonction mactQuitCancel
        mkeyQuitCancel = MenuSensitiveKey(self.mactQuitCancel, pygl.K_ESCAPE)

        # --- Rangement de tous les MenuElem créés, dans la grande liste globale. ---

        #pas besoin de faire une liste de liste comme dans d'autres MenuManager.
        #Tous les MenuElem qu'on a créé l'ont été de manière individuelle.
        #Y'a juste à les mettre bout à bout dans la liste et voilà.
        self.listMenuElem = (mimgFrameName, mtxtEnterName,
                             self.meditPlayerName, mbutiOK,
                             mkeyQuitCancel, mkeyEnterOK_1, mkeyEnterOK_2)

        #j'indique 2 en paramètre, pour que le focus se mette initialement sur
        #le MenuElem numéro 2 de la liste. C'est à dire la zone de saisie du nom du joueur.
        self.initFocusCyclingInfo(2)
Exemple #24
0
comme ça je pourrais m'en servir pour plein de trucs.
Je sais pas lesquels, mais plein de trucs. (au moins le SimpleSprite)

"""

import pygame
from common import pyRect

#permet d'indiquer sur quelle coordonnées se trouve le mouvement secondaire du MovingPoint
(MOVE_ON_X,    # le mouvement se trouve sur la coordonnées X
 MOVE_ON_Y,    # le mouvement se trouve sur la coordonnées Y
 MOVE_NONE,    # y'a pas de mouvement secondaire, et crac !
) = range(3)

#mouvement par défaut. Rect(0, 0), c'est à dire pas de mouvement
DEFAULT_MAIN_MOVE = pyRect()


#Je met cette fonction à l'extérieur de la classe. Pour la rendre disponible au code
#extérieur. Comme ça, on peut se calculer soi-même sa listTotalMove et la refiler
#tel quelle à un objet MovingPoint. Ca peut éviter de recalculer plusieurs fois une
#même listTotalMove
def calculateListTotalMove(mainMove, listSecMove, indexSecMove):
    """
    calcule une listTotalMove à partir d'un déplacement secondaire et
    d'un déplacement primaire donné.

    entrées :
        mainMove     : rect (X, Y) indiquant le déplacement principal.
                       ce déplacement sera appliqué à chaque cycle..
Exemple #25
0
#-------------------------------------------------------------------
#test unitaire de GravityMovements
if __name__ == "__main__":

    from common   import pyRect

    # Je devrais utiliser securedPrint, mais bon, c'est les tests unitaires,
    # osef. De plus, je ne print que des caractères ascii, alors tout va bien.
    print " ------- DIR = DOWN --------- "
    gv = GravityMovements()
    gv.addSegmentMove(3, 15, 10)
    gv.addSegmentMove(2, 17, 7)
    gv.addSegmentMove(3, 30, 20)
    gv.addSegmentMove(3, 7, 2)
    print gv.dicMovement
    assert gv.isInGravity(pyRect(2, 9)) == True
    assert gv.isInGravity(pyRect(2, 8)) == True
    assert gv.isInGravity(pyRect(2, 17)) == True
    assert gv.isInGravity(pyRect(2, 7)) == False
    assert gv.isInGravity(pyRect(2, 18)) == False
    assert gv.isInGravity(pyRect(3, 12)) == True
    assert gv.isInGravity(pyRect(3, 9)) == False
    assert gv.isInGravity(pyRect(3, 10)) == False
    assert gv.isInGravity(pyRect(4, 11)) == False

    gv.cancelGravity(pyRect(4, 11))
    assert len(gv.dicMovement.keys()) == 2
    assert gv.dicMovement[2] == [[17, 7]]
    assert gv.dicMovement[3] == [[15, 10], [30, 20], [7, 2]]
    gv.cancelGravity(pyRect(3, 10))
    assert len(gv.dicMovement.keys()) == 2
Exemple #26
0
    def __init__(self, listImgInfo, posStart, nbrImgLoop=IMG_LOOP_ETERNAL,
                 endCondition=END_ON_OUT_GAME_AREA,
                 moveRect=pyRect(), movePeriod=NONE_COUNT,
                 accelRect=pyRect(), accelPeriod=NONE_COUNT,
                 makeDecalCenter=False):
        """
        constructeur. (thx captain obvious)

        entrée :
            listImgInfo : liste de tuple de 3 elements
               - Surface contenant une image du sprite
               - temps(nombre de cycle) avant de passer à l'image suivante
               - rect(X, Y) de décalage à appliquer lorsqu'on passe à l'image suivante
               (le tout premier décalage de listImgInfo sera appliqué dès la création du sprite)

            posStart : rect. position du coin superieur gauche du sprite, à l'écran.
                (enfin presque, because éventuel décalage initial)

            nbrImgLoop : int, ou valeur IMG_LOOP_ETERNAL. Nombre de fois qu'on fait
                défiler la liste d'image avant d'arrêter l'animation. (elle est moche cette phrase)
                si IMG_LOOP_ETERNAL : on arrête jamis l'anim.

            enfCondition : valeurs END_ON_XXX, indiquant à quel moment le sprite sera supprimé.
                Voir définition de ces valeurs au début de ce fichier. On peut les "orer".

            moveRect, movePeriod : rect et int. Mouvement du sprite, et sa période,
                en nombre de cycle. si movePeriod vaut NONE_COUNT : pas de mouvement

            accelRect, accelPeriod : rect et int. Accélération du sprite et sa période (pareil)
                si accelPeriod vaut NONE_COUNT : pas d'accélération

            makeDecalCenter : booléen. si true, à chaque changement d'image,
                on appplique un décalage automatique, de façon à
                ce que les centres des deux images soient confondus.
                (on peut en plus appliquer des décalages individuels avec
                les rects de listImgInfo)

            TRODO : c'est de la merde ce DecalCenter. Faut tout gérer avec des hotPoint,
                j'arrête pas de le dire depuis le début, putain de merde.
        """
        pygame.sprite.Sprite.__init__(self)

        #putain d'initialisations de merde. Y'a pas mieux ?
        self.listImgInfo = listImgInfo
        self.nbrImgLoop = nbrImgLoop
        self.endCondition = endCondition
        #vaut mieux recopier les Rect de position, move et accel.
        #même si c'est pas forcément utile.
        #Si les rect viennent d'une constante, on risque de tout niquer
        self.moveRect = pygame.Rect(moveRect)
        self.movePeriod = movePeriod
        self.accelRect = pygame.Rect(accelRect)
        self.accelPeriod = accelPeriod
        self.makeDecalCenter = makeDecalCenter
        self.rect = pygame.Rect(posStart)

        #curseur sur listImgInfo, indiquant l'image en cours, affiché à l'écran.
        self.imgCursor = 0

        #nombre de boucle déjà faite dans le défilement d'image.
        self.imgLoopMade = 0

        #It's ALIVE  !!! FFEEAAAAAARRRRR !!!!!
        self.currentState = SPRITE_ALIVE

        #on affiche la première image de listImgInfo, et on applique le décalage
        #ça définit également la variable self.changeImageCounter, qui indique le nombre
        #de cycle avant le prochain changement d'image.
        self.refreshImg()

        if self.endCondition & END_ON_OUT_GAME_AREA:

            #le sprite doit se détruire quand il sort de l'aire de jeu. Donc il faut pas se
            #contenter de le définir avec un point. Il lui faut aussi une taille de rectangle,
            #ce qui permettra de savoir quand le sprite est complètement hors de l'écran.
            #(on ne le détruit pas si il est en partie hors de l'écran)

            #du coup, pour déterminer la taille, je me fait pas chier. Je prends la
            #longueur et la largeur max de la liste d'image du sprite.
            #Y'aurait surement moyen de faire plus optimisé, mais KISS.

            #TRODO version 2 : précalculer ça, et donner la possibilité de passer la
            #taille précalculée en paramètre de l'__init__, pour qu'il soit pris tel quel.
            #C'est un gouffre à temps CPU, cette connerie. Bah, osef pour l'instant.

            listWidths  = [ imgInfo[0].get_width()
                            for imgInfo in listImgInfo
                          ]

            listHeights = [ imgInfo[0].get_height()
                            for imgInfo in listImgInfo
                          ]

            self.rect.size = (max(listWidths), max(listHeights))

        if self.movePeriod is not NONE_COUNT:
            #compteur pour les périodes de mouvement, si il y a du mouvement.
            self.moveCounter = self.movePeriod

        if self.accelPeriod is not NONE_COUNT:
            #pareil, mais accélération.
            self.accelCounter = self.accelPeriod
Exemple #27
0
NBR_MAX_VESTE = 5

#coordonnées X des vestes. Ca fait (X1, X2, X1, X2, X1, ...)
listeCoordX = ((VESTE_X1, VESTE_X2) * NBR_MAX_VESTE)[:NBR_MAX_VESTE]

#coordonnée Y des vestes. une liste qui s'incrémente, tout simplement
listeCoordY = tuple( [ VESTE_Y_START + iVeste * VESTE_Y_ADD
                       for iVeste in range(NBR_MAX_VESTE) ])

#coordonnée X, Y des vestes
listeCoord = zip(listeCoordX, listeCoordY)

#liste de Rect, contenant les coordonnées des vestes en jean.
#C'est dans l'ordre dans lequel on vire les points de vie :
#les derniers éléments (donc ceux du bas) sont virés en premier)
LIST_COORD_VESTEJEAN = tuple( [ pyRect(coord[0], coord[1])
                                for coord in listeCoord
                              ])

# --- config du clignotement d'une veste quand on perd un point de vie ---

#valeur initiale du blinkCounter
BLINK_COUNTER_INIT = 50
#pas de décrémentation de blinkCounter
BLINK_COUNTER_STEP = 1
#pas de déplacement (incr ou decr) de blinkRandomCursor
BLINK_RANDOM_STEP = 5
#grille de random, utilisé pour recalculer le blinkRandomEnd
#(car il faut qu'il soit un multiple de 5, donc on prend un random sur la grid,
#puis on le multiplie par le Random Step)
BLINK_RANDOM_GRID = BLINK_COUNTER_INIT / BLINK_RANDOM_STEP
Exemple #28
0
    def __init__(self, dicAmmoViewerImg, spriteSimpleGenerator):
        """
        constructeur. (thx captain obvious)

        entrée :
            dicAmmoViewerImg : dictionnaire de correspondance
                               identifiant d'image -> image

            spriteSimpleGenerator : classe eponyme. Pour que l'ammoviewer génère
                                    des petits sprites si il a envie (les bulletSmoke)

        """
        self.dicAmmoViewerImg = dicAmmoViewerImg
        self.spriteSimpleGenerator = spriteSimpleGenerator

        #je voulais utiliser les dirtySprites, mais j'arrive pas à les faire
        #fonctionner comme il faut. Ca n'enregistre pas le rect de clear.
        #que celui de dessinage. (ou l'inverse ?). Voir mon article de blog à ce sujet.
        #http://recher.wordpress.com/2010/07/13/vulture-repellent-doesnt-work
        #bref. Ce groupe contient les sprites des Bullet et des Shell à afficher.
        self.groupBulShell = pygame.sprite.RenderUpdates()

        #calcul du décalage total entre 2 BulletShell
        heightBulletShell = self.dicAmmoViewerImg[imgShell].get_height()
        decalTwoBulletShell_Y = heightBulletShell + SPACING_Y_BULLETS
        self.decalTwoBulletShell = pyRect(0, decalTwoBulletShell_Y)

        #liste des BulletShell chargées (on les voit à l'écran)
        self.listBulShellLoaded = []
        #liste des BulletShell pas chargé (on les voit pas).
        self.listBulShellToLoad = []

        #céation des sprites de Bullet et de Shell
        #héhé, j'adore ce concept d'appeler une variable "_" parce qu'on n'en a pas besoin.
        for _ in xrange(NBR_MAX_CARTOUCHE):

            sprShell = pygame.sprite.Sprite()
            sprShell.image = self.dicAmmoViewerImg[imgShell]

            sprBullet = pygame.sprite.Sprite()
            sprBullet.image = self.dicAmmoViewerImg[imgBullet]

            #on ajoute le BulletShell dans la liste des "à charger"
            #donc là, elles vont pas encore s'afficher.
            self.listBulShellToLoad.append((sprShell, sprBullet))

        #position de la prochaine cartouche qui va se recharger.
        #(Ce sera la toute première cartouche, donc on la place au niveau
        #de l'ammoBox (chargeur contenant toutes les cartouches)
        self.posShellToReload = pygame.Rect(POS_AMMO_BOX)

        #variable indiquant au code principal si y'a eu des changements de sprites.
        #(image, pos, cachage/montrage, ...)
        self.isUpdatingSthg = True

        #nombre de coups de feu et de réarmement à faire.
        self.nbrOfFireToDo = 0
        self.nbrOfRearmToDo = 0

        #on indique qu'il faut charger toutes les cartouches, dès le départ.
        #Comme ça, ça exécute la fonction qui les affiche et les positionne bien comme il faut.
        #Pas besoin de doubloniser le code avec une boucle qui les positionnerait toute d'un coup.
        #factorisation power !!
        #Par contre, j'ai codé ça de façon à ce que y'ait qu'un seul reload par cycle. Même si il
        #faut en faire plein d'un coup. Du coup, au début de la partie, on voit les cartouches
        #qui apparaissent une par une, mais très vite. Eh bien moi je trouve ça cool et j'ai
        #décidé de le laisser comme ça.
        self.nbrOfReloadToDo = NBR_MAX_CARTOUCHE

        #curseur sur la liste MOVEMENT_REARMING. Permet de savoir où on en est
        #dans le déplacement des cartouches quand il y a un rearm
        self.cursorRearmMovement = NONE_COUNT
Exemple #29
0
ni si on fait un fire ou un rearm alors que y'a plus de BulletShell dans le chargeur.
Je suppose que ça plante. De toute façon c'est pas censé arriver. La classe Hero
contient les sécurités nécessaires pour éviter ces conneries.

et y'a un gosse qui fait "tic tic tic" et "ding !" dans le fond du car.
Euh... Moi j'suis pas là hein ! J'ai rien à voir là dedans moi !!
"""

import pygame

from common import pyRect, NONE_COUNT
from hero import NBR_MAX_CARTOUCHE

#position de l'ammoBox. En vrai c'est une image fixe. Mais faut placer
#correctement les cartouches par rapport à cette image fisc.
POS_AMMO_BOX = pyRect(4, 134)

#décalage entre une Shell et le Bullet correspondant
DECALAGE_SHELL_BULLET = pyRect(16, 3)
#espacement vertical entre deux BulletShell
SPACING_Y_BULLETS = 2

#liste des mouvements à appliquer aux cartouches restantes dans le flingue,
#lorsque le héros réarme. Ici, les cartouches montent, de 4 pix par 4 pix
MOVEMENT_REARMING = (pyRect(0, -4), ) * 5

#identifiant des images
(imgBullet,       #Bullet
 imgShell,        #Shell. Qui reste tel quel après le tir. Mais disparaît à la fin du rearm.
) = range(2)
Exemple #30
0
) = range(3)

#préfixe dans les noms de fichiers image du magicien.
IMG_FILENAME_PREFIX = "m"

#correspondance entre nom de fichier court et identifiant d'image
#pour trouver le vrai nom du fichier : <prefix> + <nomcourt> + ".png"
LIST_IMG_FILE_SHORT_NAME = (
 (IMG_NORMAL,      "norm"),
 (IMG_DYING_NAKED, "naked"),
 (IMG_HURT,        "hurt"),
)

#taille du magicien. (J'aurais pu prendre directos les tailles de son image,
#mais j'avais pas envie)
MAGICIAN_SIZE  = pyRect(0, 0, 21, 33)

#les etats du magicien
(APPEARING,         #en train d'apparaître à l'écran
 ALIVE,             #vivant, etat normal
 HURT,              #en train de se prendre une/plusieurs balles dans la gueule
 DYING,             #en train de crever (animation à la con du magicien qui meurt)
 BURSTING,          #en train d'exploser (anim à la con)
 DEAD,              #mort. La boucle principale du jeu doit le supprimer.
) = range(6)

#nombre de point de vie initial du magicien. Un bullet enlève un point de vie.
LIFE_POINT_INIT = 2

#nombre de points de dégats que doit se prendre le magicien en une seule fois, pour se faire BURST
#En théorie, le BURST s'applique même si il reste des points de vie au magicien.