Déplacer et animer des formes avec PyGame

Se déplacer dans tous les sens avec PyGame se fait en modifiant les coordonnées. Chaque fois que vous déplacez un objet, rien n’a réellement été déplacé.  

En réalité, les pixels ont été dessinés, mis à jour, actualisés, puis dessinés à nouveau, avec de nouvelles coordonnées, donc un nouvel emplacement.

Dans un film, une vidéo ou un jeu, le défilement rapide de plusieurs images, nous donne l’impression qu’il y a un mouvement.

La fréquence des images

FPS (frames per seconde), est la fréquence à laquelle défile une série consécutive d’images par seconde. Les films utilisent 24 images par seconde, mais les jeux informatiques nécessitent une fréquence d’images plus rapide. Trente images par seconde est un bon taux, mais en général, plus la fréquence d’images est élevée, plus le mouvement sera fluide, bien qu’après environ 70 images par seconde, peu de personnes puissent détecter l’amélioration !

En d’autres termes, la fréquence de rafraîchissement est le nombre d’images que le programme dessine par seconde. En fait, ce défilement rapide des images est mesuré en FPS ou en images par seconde.

La classe Clock pour se déplacer avec PyGame

Un objet pygame.time.Clock peut nous aider à contrôler le FPS maximum. Cet objet garantira que le jeu ne s’exécutera pas trop vite en mettant de petites pauses à chaque itération de la boucle. Si nous n’avions pas ces pauses, notre programme fonctionnerait aussi vite que l’ordinateur pourrait le faire. On fait un appel à la méthode tick() dans la boucle pour garantir que le jeu s’exécute à la même vitesse, quelle que soit la vitesse de l’ordinateur.

Nous allons écrire un programme qui dessine un caré à chaque tour de boucle. Dans la boucle, nous utiliserons le module random, afin de générer les coordonnées (x, y) et définir la position aléatoirement.

import pygame, sys, random
from pygame.locals import *

pygame.init()
clock = pygame.time.Clock()

windowWidth = 640
windowHeight = 480
squareX = 0
squareY = 0
YELLOW = (255, 255, 0)

surface = pygame.display.set_mode((windowWidth, windowHeight))
pygame.display.set_caption('Se déplacer et animer les objets !')

while True:

    surface.fill((0, 0, 0))

    # dessiner des rectangles aléatoires
    pygame.draw.rect(surface, YELLOW, (random.randint(0, windowWidth), random.randint(0, windowHeight), 20, 20))

    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
    clock.tick(60)
    pygame.display.update()

Aussi, nous avons importé le module sys, pour pouvoir utiliser la fonction exit().

Lorsque vous exécutez le code précédent, vous verrez un tas de carrés jaunes apparaître et disparaître tout autour de l’écran. En fait, Pygame dessine, efface et redessine des rectangles dans la fenêtre. Ajoutez un # au début de la ligne surface.fill()pour voir ce qui se passera. En effet, ce code efface les données de pixels de l’image précédente. Sinon, nous aurons tous les rectangles dessinés les uns à côté des autres. Maintenant, enlevez le # que vous avez ajouté et remplacez 60 fps par 1. Vous aurez une fréquence d’une image par seconde. Notez que la fonction fill(0,0,0), remplie la fenêtre avec une couleur noire à chaque tour de boucle.

Comment fonctionne le déplacement des objets dans PyGame ?

Nous allons modifier le code précédent, ajoutez ce code avant la boucle while. Il définit une position initiale au milieu de l’écran.

greenSquareX = windowWidth / 2
greenSquareY = windowHeight / 2

Puis, remplacez le code entre la fonction surface.fill() et la boucle for par celui ci :

# déplacer des objets
pygame.draw.rect(surface, GREEN, (greenSquareX, greenSquareY, 20, 20))
greenSquareX += 1
#greenSquareY += 1

À chaque fois que nous dessinons le carré, nous ajoutons 1 à la variable de la coordonnée X (la distance à partir de la gauche de l’écran), greenSquareX . Cependant, si nous modifions cette ligne à greenSquareX += 5, le nouveau carré dessiné, sera 5 pixels à droite de l’endroit où il était avant. Cela donne l’illusion que la forme se déplace plus rapidement qu’auparavant. Si nous modifions le nombre que nous ajoutons à greenSquareX à 0, notre forme ne bougerait jamais ; et si nous le modifiions à -5, il reculerait.

Maintenant, commentez la ligne greenSquareX et supprimez le # de greenSquareY. Notre objet va se déplacer vers le bas de l’écran. Toutefois, si nous enlevons le # de greenSquareX et greenSquareY, notre forme se déplacera vers la droite et vers le bas, chaque fois que Pygame mettra à jour l’écran.

Pour se déplacer horizontalement, nous ajoutons une valeur à la coordonnée X, et pour se déplacer verticalement, nous ajoutons une valeur à la coordonnée Y. Comme la boucle ne s’arrête pas, chaque déplacement correspond à une nouvelle image dessinée avec les nouvelles coordonnées. Donc, réellement, l’objet ne se déplace pas, mais il est dessiné dans un nouvel emplacement. Comme c’est rapide, cela donne l’illusion que la forme se déplace.

Se déplacer dans toutes les directions

Si nous ajoutons des valeurs à X et Y, nos formes se déplaceront vers la droite et vers le bas. Et si nous ajoutons une valeur à X et soustrayons une valeur de Y, nos formes se déplaceront vers la droite et vers le haut. Si nous soustrayons une valeur de X et ajoutons une valeur à Y, nos formes se déplaceront vers la gauche et vers le bas. Enfin, si nous soustrayons à la fois des valeurs de X et Y, notre forme se déplacera vers la gauche et vers le haut. Cela signifie que nous avons huit directions dans lesquelles nos objets peuvent se déplacer. En supposant que nous utilisons des nombres entiers et égaux les uns aux autres.

Manipuler des formes avec le clavier

Jouons un peu plus avec les nombres et les décimales. Jusqu’à présent, les valeurs que nous avons utilisées pour animer nos formes étaient des nombres entiers qui restent constants. Mais que se passe-t-il si au lieu d’ajouter 1 aux coordonnées X/Y, nous ajoutions 1, puis (1.1), puis (1.2), et ainsi de suite ?

Supprimez les variables greenSquareX et greenSquareY et repmlacez-les par ce code :

blueSquareX = 0.0
blueSquareY = 0.0
blueSquareVX = 1
blueSquareVY = 1

Remplacez le code se trouvant entre la fonction fill() et la boucle while par celui-ci.

pygame.draw.rect(surface, (0, 0, 255),(blueSquareX, blueSquareY, 20, 20))
blueSquareX += blueSquareVX
blueSquareY += blueSquareVY
blueSquareVX += 0.1
blueSquareVY += 0.1

Nous ajoutons des valeurs à X et Y, donc le rectangle se déplace vers le bas et vers la droite, mais une chose est différente par rapport aux codes précédents. En effet, au fur et à mesure que le programme s’exécute, le rectangle se déplace un peu plus vers la droite en accélérant. C’est parce que nous utilisons des variables qui stockent une mesure de base de la vitesse.

En utilisant d’autres variables pour ajouter une valeur à nos coordonnées X et Y, nous pouvons augmenter la valeur de la distance ajoutée à chaque image, ce qui donne l’illusion d’une accélération. Si nous devions changer notre code pour qu’il augmente nos variables de vitesse ( blueSquareVX / blueSquareVY dans ce cas) par multiplication au lieu de l’addition ou de la soustraction, nos formes accéléreraient de façon exponentielle. Donc, nous aurions à peine le temps de voir l’objet, avant qu’il ne sorte de l’écran.

Où va l’objet quand il se déplace hors de l’écran ?

Même si nos formes se déplacent plus loin de notre écran, ils n’arrêtent pas de bouger et ils continuent indéfiniment, ou jusqu’à ce que vous les arrêtiez et vous les faites revenir.
Redéfinissez la variable blueSquareVX = 8 et dans la boucle modifiez blueSquareVX à blueSquareVX -= 0.2, puis commentez blueSquareVY += 0.1 en ajoutant un #.

Maintenant, lorsque nous exécutons le code, nous voyons que notre carré se déplace vers la droite, avant de ralentir pour s’arrêter puis revenir, formant un arc. En effet, c’est parce que la variable blueSquareVX décrémente. Jouez avec ces valeurs pour voir l’effet qu’elles auront sur la façon dont notre forme va se déplacer. Aussi, vous pouvez commenter la fonction fill(), pour voir la trajectoire de l’objet.

Animer d’autres propriétés

En plus de permettre à un objet de se déplacer, nous pouvons utiliser la même approche pour modifier les variables au fil du temps et affecter d’autres propriétés, comme les dimensions de nos formes. Pour cela, remplacez les variables qui se trouvent juste au-dessus de la boucle while par :

rectX = windowWidth / 2
rectY = windowHeight / 2
rectWidth = 50
rectHeight = 50

Et, remplacez le code entre la fonction fill() et la boucle while par :

pygame.draw.rect(surface, (255, 255, 0), (rectX - rectWidth / 2, rectY - rectHeight / 2, rectWidth, rectHeight))
    rectWidth += 1
    rectHeight += 1
    

Ici, pygame.draw.rect dessine un carré, mais, nous avons remplacé les paramètres qui déterminent la largeur et la hauteur par des variables que nous pouvons modifier.

Nous ajoutons aussi un peu de maths dans notre code. Au fur et à mesure que le carré grandit, le point à partir duquel il est dessiné ne changera pas. Donc, le carré ne va pas se déplacer dans la fenêtre. En soustrayant la moitié de la largeur et la moitié de la hauteur des coordonnées auxquelles nous dessinons notre forme, notre carré restera au centre de la fenêtre en grandissant.

En fait, l’utilisation de variables dans nos calculs, permet de garder la forme toujours au centre de la fenêtre.
Si nous définissant les variables rectWidth et rectHeight sur 50 et changeons le += en -= , notre carré diminuera de taille tout en restant au centre de notre fenêtre.

Changer les couleurs

Remplacez les variables au-dessus de la boucle while par ce code.

squaresRed = random.randint(0, 255)
squaresBlue = random.randint(0, 255)
squaresGreen = random.randint(0, 255)

Puis remplacez le code entre la fonction fill() et la boucle for par ce code.

pygame.draw.rect(surface, (squaresRed, squaresGreen,
                               squaresBlue), (50, 50, windowWidth / 2, windowHeight / 2))
if squaresRed >= 255:
    squaresRed = random.randint(0, 255)
else:
    squaresRed += 1
if squaresGreen >= 255:
    squaresGreen = random.randint(0, 255)
else:
    squaresGreen += 1
if squaresBlue >= 255:
    squaresBlue = random.randint(0, 255)
else:
    squaresBlue += 1
     

Ce code, a quelque chose d’un peu différent comparé aux exemples précédents. En effet, nous ne faisons pas qu’ajouter et soustraire des valeurs à chaque fois que nous dessinons nos formes. Cependant, nous vérifions les valeurs que nous avons avant de les modifier, en utilisant une instruction if, else.

Avec les vérifications if, else, nous nous assurons que les valeurs des couleurs ne dépassent pas 255. Si nos valeurs sont sur le point de dépasser 255, nous leur attribuons une valeur aléatoire entre 0 et 255. La couleur de notre carré changera et continuera ensuite à se déplacer dans la palette des couleurs RVB en ajoutant 1 aux variables squaresRed , squaresGreen et squaresBlue pendant que notre programme Pygame s’exécute.

Tout comme les exemples précédent, si nous ajoutions un plus grand nombre à chacune de nos variables, les couleurs défileront rapidement. De même, si nous ajoutions un moins à chaque valeur RVB à chaque mise à jour de Pygame, le défilement des couleurs sera plus lent.

Déplacer et animer des formes avec PyGame

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.

Retour en haut