• Etape 5 : Notre premier PNJ

    Etape 5 : Mon premier PNJ

     

    1.      L’objet Rect

    2.      Mise à niveau du code

    3.      Création

    4.      Animation

    5.      Interaction

     

     

     

    1. Généralités : l’objet Rect :

     

    Jusqu'à présent nous avons fonctionné de façon quelque peu basique, avec des images (qui sont des Surfaces) que nous placions et déplacions a notre guise. Pour nous diriger petit à petit vers les fonctionnalités qui nous intéressent , nous allons désormais revoir notre système d’objets en utilisant des objets Rect, car ceux-ci possèdent des attributs riches et nous permettrons une meilleur interaction avec notre monde.

     

    Une Objet Rect de Pygame est comme son nom l’indique un rectangle, celui-ci possède les attributs suivants :

     

                        top, left, bottom, right
                        topleft, bottomleft, topright, bottomright
        midtop, midleft, midbottom, midright
        center, centerx, centery
        size, width, height
        w,h

     

     

    Ces attributs peuvent être représentés visuellement ainsi :

     

     Etape 5 : Notre premier PNJ

     

     

     

     

     Ce sont eux qui vont nous permettre une grande souplesse dans le positionnement et dans la détection des collisions (nous y viendrons un peu plus tard dans cet article).

     

     

    Pour définir un objet Rect j’utilise la méthode suivante :

     

    mon_rectangle = pygame.Rect (x, y, longueur, hauteur)

     

    Exemple : mon_carré = pygame.Rect (10, 10, 20, 30)

     

    Sera donc un carré positionné en X = 10, Y = 10, de longueur 20 et hauteur 30

     

     

    2 : Mise a niveau du code :

     

    Reprenons le code de l’Etape2 , nous avions ceci :

     

    perso = pygame.image.load('boy.png').convert_alpha() 

    x = 150 

    y = 250 

     

    Désormais je vais pouvoir déclarer mon personnage différemment :

     

     

    perso = pygame.image.load('boy.png').convert_alpha() 

    perso_rect = pygame.Rect(150,250,200,335) 

     

    je créé  un nouvel objet perso_rect ( j’aurais pu l’appeler autrement ), que je déclare comme étant un objet Rect de Pygame avec les caractéristique ( X=150,Y=250) , les memes valeurs que dans mon ancien code, ceci me permet de garder son positionnement initial, et d’une largeur de 50 et hauteur de 85, qui sont la taille de mon image

    Longueur  200 – 150(qui est la position initiale X) = 50

    Hauteur 335 – 250(qui est la position initiale Y) =85

     

    Pour afficher mon personnage , j’avais le code :

     

    screen.blit(perso,(x,y))

     

    J’utilise désormais l’objet perso_rect qui contient les coordonnées de positionnement :

     

            Screen.blit(perso, perso_rect)

     

    Testons notre code :

     

     Etape 5 : Notre premier PNJ 

     

     

    L’affichage est identique.  

     

     

     !!!  Mais mon personnage ne se déplace plus !

     

    C’est normal nous utilisions les positions  (x,y) dans l’ancien script pour afficher l’image a ces coordonnés avec la méthode blit. A présent nous n’avons plus ces variables, mais nous avons à la place les valeurs X et Y de notre objet ‘perso_rect’. Ce sont ces valeurs que nous allons utiliser à la place

     

    if key[K_LEFT]: 

            perso_rect.x-=1 

        if key[K_RIGHT]: 

            perso_rect.x+=1 

        if key[K_UP]: 

            perso_rect.y-=1 

        if key[K_DOWN]: 

            perso_rect.y+=1 

     

    perso_rect.x à une valeur de 150 et perso_rect.y de 250, car nous les avons déclaré dans la création de notre objet            perso_rect = pygame.Rect(150,250,200,335) 

     

     

    Notre nouveau code :

     

     

    import pygame,sys  

    from pygame import * 

     

    pygame.init() 

     

    screen = pygame.display.set_mode((800,600)) 

    background = pygame.image.load('fond.png').convert() 

     

    perso = pygame.image.load('boy.png').convert_alpha() 

    perso_rect = pygame.Rect(150,250,200,335) 

     

    while True:             # Boucle principale du jeu 

       

        key=pygame.key.get_pressed()   

       

        for event in pygame.event.get(): 

            if event.type == QUIT: 

                sys.exit() 

               

        if key[K_LEFT]: 

            perso_rect.x-=1 

        if key[K_RIGHT]: 

            perso_rect.x+=1 

        if key[K_UP]: 

            perso_rect.y-=1 

        if key[K_DOWN]: 

            perso_rect.y+=1 

       

           

        screen.blit(background,(0,0))  

        screen.blit(perso,perso_rect) 

     

        pygame.display.flip()        

     

     

     

    3. Notre premier PNJ :

     

      

    Etape 5 : Notre premier PNJ

     

    Pas trop tôt !!

     

    Pour faire simple, nous allons faire la même chose que pour notre Héro, une déclaration on ne peut plus simple d’un objet Rect qui contiendra sa position :

     

    pnj = pygame.image.load('pnj.png').convert_alpha() 

    pnj_rect = pygame.Rect(500,400,550,485) 

     

    Et nous l’affichons en fin de script avec

     

    screen.blit(pnj,pnj_rect) 

     

     

     Etape 5 : Notre premier PNJ

     

     

     

      

      

      

      

     

      

      

      

      

      

      

      

      

      

      

      

     

     

     

    4. Animation de notre PNJ:  (en cours d’écriture)

     

    Un peu trop statique à notre goût, donnons un peu vie à notre PNJ, nous aimerions qu’il vadrouille tranquillement tant que nous n’interagissons pas avec lui. Faisons le se déplacer de façon aléatoire.

     

    Nous voulons que notre PNJ de place latéralement sur une surface de 150 pixels, sa position initiale étant de X = 500, il se déplacera jusqu'à X = 650 maximum et fera des aller et retour sur cette distance.

     

     

    import pygame,sys,random   

    from pygame import * 

     

    pygame.init() 

     

    screen = pygame.display.set_mode((800,600)) 

    background = pygame.image.load('fond.png').convert() 

     

    perso = pygame.image.load('boy.png').convert_alpha() 

    perso_rect = pygame.Rect(150,250,200,335) 

     

    pnj = pygame.image.load('pnj.png').convert_alpha() 

    pnj_rect = pygame.Rect(500,400,550,485) 

     

     

    clock=pygame.time.Clock() 

     

    moveleft = False 

    moveright = False 

     

    while True:             # Boucle principale du jeu 

       

        key=pygame.key.get_pressed()   

       

        for event in pygame.event.get(): 

            if event.type == QUIT: 

                sys.exit() 

               

        if key[K_LEFT]: 

            perso_rect.x-=1 

        if key[K_RIGHT]: 

            perso_rect.x+=1 

        if key[K_UP]: 

            perso_rect.y-=1 

        if key[K_DOWN]: 

            perso_rect.y+=1 

       

       

        if moveleft == False: 

            moveright = True 

            if moveright == True: 

                pnj_rect.x+=1 

                if pnj_rect.x == 650 : 

                    moveleft = True 

                    moveright = False 

                   

        if moveright == False: 

            moveleft = True 

            if moveleft == True: 

                pnj_rect.x-=1 

                if pnj_rect.x == 500 : 

                    moveleft = False 

                    moveright = True 

               

               

        screen.blit(background,(0,0))  

        screen.blit(pnj, pnj_rect) 

        screen.blit(perso,perso_rect) 

       

        pygame.display.flip()      

        clock.tick(60) 

     

     

     

     

    1. Interraction :

     

    Ok il est bien beau nôtre PNJ mais il ne fait pas grand-chose, nous aimerions qu’il puisse interagir avec notre Héro.

     

    -          Quand notre Héro est proche de lui, il devra s’arrêter de marcher et lui parler. Si notre personnage s’éloigne alors notre PNJ repartira vaquer à ses occupations.

     

    Pour détecter si notre personnage est assez proche du PNJ, nous allons utiliser la détection des collisions entre deux rectangles, car nos personnages étant des objets Rect, pygame met a notre disposition une fonction de détection d’intersection entre deux objets Rect.

     

                    Rect.colliderect(Rect) : retourne Vrai ou Faux  

     

    Que j’applique à nos deux personnages avec une condition dans la boucle principale de mon programme 

     

    if perso_rect.colliderect(pnj_rect)== True :

            dialogue = 1

    elif perso_rect.colliderect(pnj_rect)== False :

            dialogue = 0 

     

    Et cette action qu’elle est elle ? Nous décidons que notre PNJ va parler à notre héro et lui demander d’effectuer une petite quête, donc si la collision entre notre Héro et notre PNJ est Vraie : nous initialisons une variable ‘dialogue’, si la collision n’est plus vérifiée, nos personnages étant trop loin pour discuter, la valeur de ‘dialogue’ est nulle.

     

    La variable dialogue doit être créée avec la boucle du programme ( dialogue = 0 )

     

    Pour discuter nous avons besoin d’initialiser une Police de caractère et de l’afficher.

     

    ma_police = pygame.font.SysFont('t4cbeaulieux', 16)

     

    Et je créé ma condition :

     

    if dialogue == 1: 

            

         Quete_texte = ma_police.render('Pourriez vous aller au moulin ?',True, (255,255,255)) 

         screen.blit(Quete_texte, (pnj_rect.x-20,pnj_rect.y-20))     

     

    else : 

         screen.blit(background,(0,0)) 

     

    Résumé : si la collision est détectée, Dialogue = 1, le PNJ parle, sinon rien ne s’affiche

     

    Vérifions en lançant notre programme :

     

    Etape 5 : Notre premier PNJ

     

     

    En route pour l’aventure !

     

     

     

    Bon maintenant je veux que mon Héro aille au moulin ! et réalise qu’il n’y à personne, et revienne le dire au PNJ .

     

      

      

      

    Mais comment notre PNJ va-t-il s’avoir que nous sommes bien allé au moulin ?

    ->Tout simplement en créant une variable qui s’initialisera lorsque nous serons au moulin.

     

    Oui mais comment savoir que notre personnage est bien au moulin ?

    -> E n détectant une collision entre notre Héro et le moulin

     

    Oui mais le moulin fait parti du fond de l’écran ? Ce n’est pas un rectangle ou un Objet du jeu ?

    ->   Trichons, et créons un rectangle transparent autour du rectangle, nous pourrons ainsi déclarer une collision.

     

     

    Nous allons déclarer une variable Quête = 0, ce sera l’étape dans la progression de notre Quête, si le personnage va au moulin, celle-ci passera a Quête = 1. Ainsi lorsque notre Héro reviendra voir le PNJ celui-ci saura si oui ou non nous sommes bien allé au moulin.

     

    Créons notre rectangle pour le Moulin :

     

     

    moulin = pygame.Rect (130,460,40,60) 

    moulinimg = pygame.Surface((40,60)) 

    moulinimg.set_alpha(0) # On rend la surface transparente 

     

    et une detection de collision entre le Moulin et le Héro , moyen de savoir que le héro est au bon endroit :

     

    if (perso_rect.colliderect(moulin)) == True: 

             Quete_texte = ma_police.render('Hum , personne ici..',True, (255,255,255))   

             screen.blit(Quete_texte, (perso_rect.x-20,perso_rect.y-20)) 

             Quete = 1 

     

    Notez qu’on itinialise la valeur de Quete à 1 si il y a collision. Donc l’ensemble du code :

     

    import pygame,sys  

    from pygame import * 

     

    pygame.init() 

     

    screen = pygame.display.set_mode((800,600)) 

    background = pygame.image.load('fond.png').convert() 

     

    perso = pygame.image.load('boy.png').convert_alpha() 

    perso_rect = perso.get_rect() 

     

    pnj = pygame.image.load('pnj.png').convert_alpha() 

    pnj_rect = pygame.Rect(500,400,550,485) 

     

    ma_police = pygame.font.SysFont('t4cbeaulieux', 16) 

     

    dialogue = 0 # ici la variable dialogue 

    Quete = 0   # ici l’étape de la quête 

     

    moulin = pygame.Rect (130,460,40,60) # On créé un objet Rect 

    moulinimg = pygame.Surface((40,60)) # On y associe une surface  

    moulinimg.set_alpha(0) # et on rend le tout transparent 

     

    while 1:                # Boucle principale du jeu 

        posx,posy = pygame.mouse.get_pos() 

        key=pygame.key.get_pressed()   

        screen.blit(background,(0,0)) 

        for event in pygame.event.get(): 

            if event.type == QUIT: 

                sys.exit() 

       

        if key[K_LEFT]: 

            perso_rect.x-=1 

        if key[K_RIGHT]: 

            perso_rect.x+=1 

        if key[K_UP]: 

            perso_rect.y-=1 

        if key[K_DOWN]: 

            perso_rect.y+=1 

        if perso_rect.colliderect(pnj_rect)== True : 

            dialogue = 1 

        elif perso_rect.colliderect(pnj_rect)== False : 

            dialogue = 0 

               

        if dialogue ==1:   # Si l’on est en collision , le PNJ parle  

                if Quete== 0 : # Si on est pas encore allé au moulin 

                    Quete_texte = ma_police.render('Pourriez vous aller au moulin ?',True, (255,255,255)) 

                    screen.blit(Quete_texte, (pnj_rect.x-20,pnj_rect.y-20)) 

                   

                if Quete == 1 : # Si l’on y deja allé au moulin 

                    Quete_texte = ma_police.render('Ou diable est il encore allé...',True, (255,255,255)) 

                    screen.blit(Quete_texte, (pnj_rect.x-20,pnj_rect.y-20)) 

        else : # se declanchera si l’on est plus en colision  

            screen.blit(background,(0,0))  

           

        if (perso_rect.colliderect(moulin)) == True: #collision Moulin/Hero 

            Quete_texte = ma_police.render('Hum , personne ici..',True, (255,255,255)) 

            screen.blit(Quete_texte, (perso_rect.x-20,perso_rect.y-20)) 

            Quete = 1 # On donne la valeur de 1 a Quete  

           

        screen.blit(moulinimg, moulin) # on affiche le Rect moulin invisible 

        screen.blit(pnj,pnj_rect) 

        screen.blit(perso,perso_rect) 

       

        pygame.display.set_caption("X = %s   Y = %s " % (posx,posy)) 

        pygame.display.flip()              

         

     

     

     

     

    Voila en gros pour le système d’interaction, qui nous a permis de voir comment détecter des collisions, et de communiquer avec notre héro.

     

    Comme vous vous en doutez, si l’on multiplie les dialogues et les quêtes, notre code va devenir un joyeux champ de bataille.

     

    Nous allons voir dans notre prochain chapitre comment organiser cela un petit peu mieux. Grâce aux Modules et aux fichiers textes.

     

     

      

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     


    Tags Tags : , ,
  • Commentaires

    Aucun commentaire pour le moment

    Suivre le flux RSS des commentaires


    Ajouter un commentaire

    Nom / Pseudo :

    E-mail (facultatif) :

    Site Web (facultatif) :

    Commentaire :