« Pygame/Concevoir des jeux avec Pygame » : différence entre les versions

m (→‎Fonctions de gestion des ressources : Correction des quotes)
D'abord nous vérifions si l'utilisateur veut quitter le programme, et si oui on quitte le programme. Ensuite nous vérifions si une touche est enfoncée, et si oui, nous vérifions si elle correspond à une des touches affectée au déplacement de la batte, si oui alors nous appelons la méthode de déplacement appropriée, et définissons l'état du joueur. A travers les états "moveup" et "movedown", modifiés par les méthodes <tt>moveup()</tt> et <tt>movedown()</tt>, nous produisons un code plus soigné et nous ne cassons pas l'''encapsulation'', ce qui signifie que vous assignez des attributs aux objets eux-mêmes, sans se référer au nom de l'instance de cet objet. Remarquez que nous avons 3 états : "still", "moveup" et "mouvedown". Encore une fois, ils deviennent utiles si vous voulez débugguer ou calculer un effet sur la balle. Nous vérifions aussi si une touche est "partie" (si elle n'est plus enfoncée), et alors si c'est la bonne touche, nous stoppons le déplacement de la batte.
 
== PuttingAssembler itle alltout together==
 
Bien, vous avez appris toutes les bases nécessaires pour écrire un petit jeu. Vous devez devriez avoir compris comment créer un objet Pygame, comment Pygame affiche les objets, comment manipuler les évènements, et comment vous pouvez utiliser la physique pour introduire des animations dans votre jeu. Maintenant je vais vous montrer comment vous pouvez prendre toutes ces morceaux de code et les assembler dans un jeu qui fonctionne. Ce que nous avons besoin tout d'abord, c'est de faire rebondir la balle sur les bords de l'écran, et que la raquette aussi soit capable de faire rebondir la balle, en d'autres termes, ce ne sera pas un jeu très compliqué. Pour ce faire, nous utiliserons les méthodes de collision de Pygame.
===Let the ball hit sides===
 
===Let the ball hit bats===
=== Faire rebondir la balle sur les bords de l'écran ===
===The Finished product===
 
La principe de base de ce type de rebond est simple à comprendre. Vous prenez les coordonnées des 4 coins de la balle, et vous vérifiez s'ils correspondent avec les coordonnées X et Y des bords de l'écran. Donc si les coins haut-gauche et haut-droit ont leur coordonnée Y à 0, vous savez que la balle est actuellement contre le bord haut de l'écran. Nous ferons tout celà dans la fonction <tt>update()</tt>, après que nous ayons défini la nouvelle position de la balle.
 
<source lang="python">
if not self.area.contains(newPos):
tl = not self.area.collidepoint(newPos.topleft)
tr = not self.area.collidepoint(newPos.topright)
bl = not self.area.collidepoint(newPos.bottomleft)
br = not self.area.collidepoint(newPos.bottomright)
if tr and tl or (br and bl):
angle = -angle
if tl and bl:
self.offcourt(player=2)
if tr and br:
self.offcourt(player=1)
 
self.vector = (angle,z)
</source>
 
Ici nous contrôlons que la variable <tt>area</tt> contient la nouvelle position de la balle. Elle devrait toujours être vraie, nous n'aurons donc pas besoin de la clause <tt>else</tt>, bien que dans d'autres circonstances vous devriez considérer ce cas de figure. Nous contrôlons alors si les coordonnées des quatre coins entrent en collision avec les bords de l'écran, et créons des objets pour chaque résultat. Si c'est vérifié, les objets auront leur valeur à 1, ou <tt>true</tt>. Sinon, la valeur sera <tt>None</tt>, ou <tt>false</tt>. Nous verrons alors si elle touche le dessus ou le dessous, et si oui nous changerons la direction de la balle. En pratique, grâce à l'utilisation des radians, nous pourrons le faire facilement, juste en inversant sa valeur (positif/négatif). Nous contrôlons aussi que la balle ne traverse pas les bords, ou alors nous appellerons la fonction <tt>offcourt()</tt>. Ceci dans mon jeu, replace la balle, ajoute 1 point au score du joueur spécifié lors de l'appel de la fonction, et affiche le nouveau score.
 
Enfin, nous réaffectons le vecteur basé sur le nouvel angle. Et voilà, la balle rebondiras gaiement sur les murs et sortira du court avec un peu de chance.
 
=== Faire rebondir la balle sur la raquette ===
 
Faire en sorte que la balle rebondisse sur les raquettes est similaire au rebonds sur les bords de l'écran. Nous utilisons encore la méthode des collisions, mais cette fois, nous vérifions que les rectangles de la balle entrent en collision avec ceux des raquettes. Dans ce code, nous y ajoutons des suppléments pour éviter certains problèmes. Vous devriez trouver tout un tas de codes supplémentaires à ajouter pour éviter certains problèmes ou bugs, il est plus simple de les trouver lors de l'utilisation.
 
<source lang="python">
else:
# Réduire les rectangles pour ne pas frapper la balle derrière les raquettes
player1.rect.inflate(-3, -3)
player2.rect.inflate(-3, -3)
 
# Est-ce que la raquette et la balle entre en collision ?
# Notez que je mets dans une règle à part qui définit self.hit à 1 quand ils entrent en collision
# et à 0 à la prochaine itération. C'est pour stopper un comportement étrange de la balle
# lorsqu'il trouve une collision *à l'intérieur* de la raquette, la balle s'inverse, et est
# toujours à l'intérieur de la raquette et donc rebondit à l'intérieur.
# De cette façon, la balle peut toujours s'échapper et rebondir correctement
if self.rect.colliderect(player1.rect) == 1 and not self.hit:
angle = math.pi - angle
self.hit = not self.hit
elif self.rect.colliderect(player2.rect) == 1 and not self.hit:
angle = math.pi - angle
self.hit = not self.hit
elif self.hit:
self.hit = not self.hit
self.vector = (angle,z)
</source>
 
Nous débutons cette section à partir de la condition <tt>else</tt>, à cause de la partie précédente du code qui vérifie si la balle frappe les bords. Cela prend tout son sens si elle ne frappe pas les bords, elle pourrait frapper une raquette, donc nous poursuivons la condition précédente. Le premier problème est de réduire le rectangle des joueurs de 3 pixels dans les deux dimensions pour empêcher la raquette de frapper la balle lorsqu'elle est derrière elle. Imaginez que vous venez juste de bouger la raquette et que la balle se trouvait derrière elle, les rectangles se chevauchent, et la balle sera considérée comme "frappée", c'est pour prévenir ce petit bug.
 
Ensuite nous vérifions si les rectangles entrent en collision, avec une correction de bug de plus. Remarquez que j'ai commenté toute cette partie de code, c'est toujours préférable d'expliquer une partie du code qui parait obscure, que ce soit pour les autres qui regardent votre code, ou pour vous lorsque vous y reviendrez plus tard. Sans la correction du bug, la balle pourra heurter un coin de la raquette, changer de direction, et l'image d'après, trouver qu'elle est toujours à l'intérieur de la raquette. Alors le programme pensera que la balle est frappée une nouvelle fois et rechangera de direction. Cela peut survenir plusieurs fois, ce qui rendrait le comportement de la balle complètement irréaliste. Donc nous avons une variable, <tt>self.hit</tt> qui sera définie à <tt>true</tt> quand elle sera frappée, et à <tt>false</tt> une image plus tard. Quand nous vérifions si les rectangles sont entrés en collision, nous contrôlons si <tt>self.hit</tt> est à <tt>true</tt> ou <tt>false</tt> pour stopper les rebonds internes.
 
L'imposant code ici est facile à comprendre. Tous les rectangle possèdent une fonction <tt>colliderect()</tt>, dans laquelle vous envoyez le rectangle d'un autre objet, qui retournera <tt>1</tt> (<tt>true</tt>) si les rectangles se chevauchent, et <tt>0</tt> (<tt>false</tt>) dans le cas contraire. En cas de réponse positive, nous pouvons changer la direction en soustrayant l'angle actuel par <math> \boldsymbol{\pi}</math> (encore un petit truc que vous pouvez faire avec les radians, qui ajustera l'angle de 90 degrés et renverra la bonne direction. Vous pourrez trouver qu'à ce stade la compréhension approfondie des radians soit un ordre!). Pour terminer le contrôle du bug, nous repassons <tt>self.hit</tt> à <tt>false</tt> à partir de l'image qui suit la frappe de la balle.
 
Nous réaffectons alors le vecteur. Vous aimeriez bien sur enlever la même ligne dans la précédente partie de code, mais vous ne pourrez le faire qu'après le test conditionnel <tt>if-else</tt>. Et ce sera tout. Le code assemblé permettra maintenant à la balle de frapper les côtés et les raquettes.
 
=== Le produit final ===
 
Le produit final, avec toutes les parties de code assemblées grâce à du code glu ressemblera à ceci :
 
[[Pyagme/Tom's Pong|Code final de Tom's Pong]]
 
Comme vous avez pu voir le produit fini, je vais vous rediriger vers ''Tom's Pong'', jeu sur lequel est basé ce tutoriel. Téléchargez-le, étudiez le code source, et vous verrez une implémentation de Pong utilisant tout le code que vous avez vu dans ce tutoriel, ainsi que d'autres ajouts fait dans des versions précédentes, comme des propriétés physique pour les effets et ainsi que d'autres résolutions de bugs.
 
Vous pouvez trouver ''Tom's Pong'' sur le site : http://tom.acrewoods.net/projects/pong (GPL v2)
54

modifications