« Pygame/Déplacer une image » : différence entre les versions

Contenu supprimé Contenu ajouté
m Formatage, ajout de code
DannyS712 (discussion | contributions)
m <source> -> <syntaxhighlight> (phab:T237267)
Ligne 25 :
Alors commençons par créer notre liste et remplissons-la d'un beau paysage fait de 1 et de 2.
 
<sourcesyntaxhighlight lang="python">
>>> screen = [1, 1, 2, 2, 2, 1]
>>> print screen
[1, 1, 2, 2, 2, 1]
</syntaxhighlight>
</source>
 
Nous venons de créer l'arrière-plan. Mais ça ne sera pas franchement excitant tant que nous n'aurons pas dessiné un joueur à l'écran. Nous allons créer un puissant Héros qui ressemblera à un 8. Déposons-le au milieu de la carte et voyons de quoi il a l'air.
 
<sourcesyntaxhighlight lang="python">
>>> screen[3] = 8
>>> print screen
[1, 1, 2, 8, 2, 1]
</syntaxhighlight>
</source>
 
Vous n'êtes surement pas parvenus plus loin si vous avez tout juste commencé à faire de la programmation graphique avec pygame. Vous avez obtenu quelques trucs mignons sur l'écran, mais ils ne pouvaient se déplacer nulle part. Peut-être que maintenant que notre écran n'est qu'une simple liste de nombres, il est plus facile de voir comment les déplacer ?
Ligne 45 :
Avant que nous puissions déplacer notre personnage, nous avons besoin de garder une trace de sa position. Dans la section précédente, quand nous l'avons dessiné, nous l'avons juste posé à une position arbitraire. Faisons-le plus rigoureusement cette fois-ci.
 
<sourcesyntaxhighlight lang="python">
>>> playerpos = 3
>>> screen[playerpos] = 8
>>> print screen
[1, 1, 2, 8, 2, 1]
</syntaxhighlight>
</source>
 
Maintenant il est assez facile de le déplacer vers une nouvelle position. Changeons simplement la valeur de <code>playerpos</code>, et dessinons-le une nouvelle fois à l'écran.
 
<sourcesyntaxhighlight lang="python">
>>> playerpos = playerpos - 1
>>> screen[playerpos] = 8
>>> print screen
[1, 1, 8, 8, 2, 1]
</syntaxhighlight>
</source>
 
Aïe! Maintenant nous pouvons voir 2 héros. Un dans l'ancienne position, et un dans la nouvelle. C'est exactement la raison pour laquelle nous avons besoin ''d'effacer'' le héros dans son ancienne position avant de le dessiner sur sa nouvelle position. Pour l'effacer, nous devons changer la valeur dans la liste pour qu'elle soit de nouveau comme avant la présence du héros. Pour ça, nous devons conserver une trace des valeurs de l'affichage avant que notre héros ne les remplace. Il y a plusieurs manières de le faire, mais la plus simple est de garder une copie séparée de l'arrière-plan. Ceci signifie que nous devons faire subir quelques modifications à notre jeu.
Ligne 67 :
Ce que nous voulons faire c'est créer une liste séparée que nous appellerons arrière-plan. Nous créerons cet arrière-plan de façon à ce qu'il soit comme notre écran original rempli de 1 et de 2. Ensuite nous copierons chaque objet dans l'ordre de d'affichage : de l'arrière-plan vers l'écran. Après, nous pourrons redessiner notre héros sur l'écran.
 
<sourcesyntaxhighlight lang="python">
>>> background = [1, 1, 2, 2, 2, 1]
>>> screen = [0]*6 #Un nouvel écran vierge
Ligne 81 :
>>> print screen
[1, 1, 2, 8, 2, 1]
</syntaxhighlight>
</source>
 
Cela peut sembler être un surplus de travail. Nous n'en sommes pas plus loin d'où nous étions la dernière fois, lorsque nous avons tenté de le déplacer. Mais cette fois nous avons plus d'information pour pouvoir le déplacer correctement.
Ligne 89 :
Cette fois ci, il sera plus simple de déplacer le héros. D'abord nous effacerons le héros de son ancienne position. Nous faisons cela en recopiant les bonnes valeurs de l'arrière-plan sur l'écran. Ensuite, nous dessinerons le personnage dans sa nouvelle position sur l'écran.
 
<sourcesyntaxhighlight lang="python">
>>> print screen
[1, 1, 2, 8, 2, 1]
Ligne 97 :
>>> print screen
[1, 1, 8, 2, 2, 1]
</syntaxhighlight>
</source>
 
Et voilà. Le héros s'est déplacé d'un pas vers la gauche. Nous pouvons utiliser le même code pour le bouger une nouvelle fois à gauche.
 
<sourcesyntaxhighlight lang="python">
>>> screen[playerpos] = background[playerpos]
>>> playerpos = playerpos - 1
Ligne 107 :
>>> print screen
[1, 8, 2, 2, 2, 1]
</syntaxhighlight>
</source>
 
Excellent! Ce n'est pas exactement ce que l'on pourrait appeler une animation fluide. Mais avec quelques arrangements, nous ferons ce travail directement avec des graphismes sur l'écran.
Ligne 126 :
# Un autre grand changement, au lieu d'employer des positions en tant que simple index (de 0 à 5), nous aurons besoin de coordonnées à deux dimensions. Nous supposerons également que chaque image de notre jeu aura une largeur de 10 pixels donc avec des positions multiples de 10. Cela revient à multiplier les indices par 10 pour obtenir les coordonnées.
 
<sourcesyntaxhighlight lang="python">
>>> background = [terrain1, terrain1, terrain2, terrain2, terrain2, terrain1]
>>> screen = create_graphics_screen() #Un nouvel écran vierge
Ligne 135 :
>>> playerpos = 3
>>> screen.blit(playerimage, (playerpos*10, 0))
</syntaxhighlight>
</source>
 
Ce code devrait vous sembler très familier, et peut-être même plus encore : le code ci-dessus devrait prendre un peu de sens.
Ligne 145 :
Ce code ne devrait pas vous surprendre.
 
<sourcesyntaxhighlight lang="python">
>>> screen.blit(background[playerpos], (playerpos*10, 0))
>>> playerpos = playerpos - 1
>>> screen.blit(playerimage, (playerpos*10, 0))
</syntaxhighlight>
</source>
 
Voila! Avec ce code, nous avons vu comment afficher un simple arrière-plan avec l'image du héros dessus.
Ligne 179 :
Pour obtenir quelque chose qui apparaisse comme un mouvement fluide, nous déplacerons quelques pixels à la fois. Voici le code pour faire un objet qui se déplace de manière fluide à travers l'écran. Puisque basé sur ce que nous savons déja, ceci devrait vous paraître simple.
 
<sourcesyntaxhighlight lang="python">
>>> screen = create_screen()
>>> player = load_player_image()
Ligne 193 :
... pygame.display.update() #afficher le tout
... pygame.time.delay(100) #arrêter le programme pour 1/10 secondes
</syntaxhighlight>
</source>
 
Et voilà. Ceci correspond au code nécessaire pour animer de façon fluide un objet à travers l'écran. Nous pouvons aussi utiliser un joli personnage d'arrière-plan. Un autre avantage sur cette façon de procéder, est que l'image du joueur peut inclure de la transparence ou être découpée en section, elle sera toujours dessinée correctement sur l'arrière-plan.
Ligne 207 :
Des informations complètes sur ces types de fonctions peuvent être trouvées dans d'autres tutoriaux et références. Le module <code>pygame.image</code> possède une fonction <code>load()</code> qui fera ce que nous voudrons. Les lignes pour charger des images devraient ressembler à ceci.
 
<sourcesyntaxhighlight lang="python">
>>> player = pygame.image.load('player.bmp').convert()
>>> background = pygame.image.load('liquid.bmp').convert()
</syntaxhighlight>
</source>
 
Nous pouvons voir la simplicité de l'exemple, la fonction de chargement demande seulement un nom de fichier et retourne une nouvelle surface avec l'image chargée. Après le chargement, nous faisons appel à la méthode de Surface : <code>convert()</code>. <code>convert()</code> nous retourne une nouvelle Surface contenant l'image, mais convertie dans le même [[w:Espace colorimétrique|espace colorimétrique]] que notre affichage. Maintenant que les images ont le même format d'affichage, le blit est très rapide. Si nous ne faisons pas la conversion, la fonction <code>blit()</code> est plus lente, c'est pourquoi il est préférable de faire la conversion de pixels d'un format à un autre au fur et à mesure.
Ligne 218 :
Cette autre fonction mystérieuse que nous avons vue dans l'exemple précédent était <code>create_screen()</code>. Dans Pygame, c'est simple de créer une nouvelle fenêtre pour les graphismes. Le code pour créer une surface de 640X480 pixels est le suivant. Sans passer aucun autre argument, Pygame choisit la meilleure profondeur de couleur et le meilleur espace colorimétrique pour nous.
 
<sourcesyntaxhighlight lang="python">
>>> screen = pygame.display.set_mode((640, 480))
</syntaxhighlight>
</source>
 
== Manipulation des entrées utilisateur ==
Ligne 226 :
Nous avons désespérément besoin de modifier la boucle principale pour prendre en compte une entrée utilisateur, comme par exemple, lorsque celui ci ferme la fenêtre. Nous devons ajouter la manipulation d'évènements à notre programme. Tous les programmes graphiques utilisent ce concept basé sur les évènements. Le programme reçoit des évènements de l'ordinateur lorsqu'une touche du clavier est enfoncée ou lorsque la souris s'est déplacée. Alors le programme répond aux différents évènements. Voici ce à quoi devrait ressembler le code. Au lieu de boucler sur 100 images, nous continuons à boucler jusqu'à ce que l'utilisateur nous demande d'arrêter.
 
<sourcesyntaxhighlight lang="python">
>>> while 1:
... for event in pygame.event.get():
Ligne 232 :
... sys.exit()
... move_and_draw_all_game_objects()
</syntaxhighlight>
</source>
 
Ce que fait ce code est, d'abord de boucler en continu, et ensuite de vérifier s'il y a un quelconque évènement provenant de l'utilisateur. Nous quittons le programme si l'utilistateur appuie sur un bouton de son clavier ou clique sur le bouton de fermeture de la fenêtre. Ensuite avoir vérifié tous les évènements, nous déplaçons et dessinons tous les objets du jeu. (Nous les effacerons également avant de les déplacer).
Ligne 240 :
Voici la partie où nous allons vraiment changer les choses. Disons que nous désirons déplacer 10 images différentes en même temps à l'écran. Une bonne manière de le faire est d'utiliser les classes Python. Nous allons créer une classe qui représente un objet du jeu. Cet objet aura une fonction pour se déplacer lui-même, nous pourrons alors en créer autant que nous le voulons. Les fonctions pour dessiner et déplacer cet objet nécessitent de travailler d'une manière où ils se déplacent seulement d'une image (ou d'un pas) à la fois. Voici le code de python pour créer notre classe.
 
<sourcesyntaxhighlight lang="python">
>>> class GameObject:
... def __init__(self, image, height, speed):
Ligne 250 :
... if self.pos.right > 600:
... self.pos.left = 0
</syntaxhighlight>
</source>
 
Nous avons donc deux fonctions dans notre classe. La méthode <code>__init__()</code> construit notre objet. Elle le positionne et définit sa vitesse. La méthode <code>move()</code> bouge l'objet d'un pas. S'il va trop loin, elle déplace l'objet en arrière vers la gauche.
Ligne 258 :
Maintenant avec notre nouvelle classe, nous pouvons assembler l'intégralité du jeu. Voici à quoi ressemblerait la fonction principale de notre programme.
 
<sourcesyntaxhighlight lang="python">
>>> screen = pygame.display.set_mode((640, 480))
>>> player = pygame.image.load('player.bmp').convert()
Ligne 278 :
... pygame.display.update()
... pygame.time.delay(100)
</syntaxhighlight>
</source>
 
Ceci est le code dont nous avons besoin pour animer 10 objets à l'écran. Le seul point qui ait besoin d'explication, ce sont les deux boucles que nous utilisons pour effacer tous les objets et dessiner tous les objets. De façon à faire les choses proprement, nous avons besoin d'effacer tous les objets avant de redessiner chacun d'eux. Dans notre exemple nous n'avons pas de problème, mais quand les objets se recouvrent, l'utilisation de deux boucles comme celles-ci devient nécessaire. Autrement l'effacement de l'ancienne position d'un objet pourrait effacer la nouvelle position d'un objet affiché avant.