*
Pong ?
Etape 1 : rebondir contre un obstacle
La balle avance en diagonale et rebondi contre les bords de l'écran et un obstacle ; fonctions et programmation objet.

Maintenant, nous allons insérer des obstacles dans l'écran.

Notre obstacle sera un rectangle dont on connait les positions des coins en haut à gauche et en bas à droite.

 

Pour simplifier l'écriture des coordonnées des points, on utilisera un type particulier qui s'appelle 'classe objet'.

La classe en question (PVector) est un couple de points (x, y).
On utilisera cette classe pour déclarer toutes les données qui fonctionnent en couple : dimEcran, pos, vit, dir, recA (=coin haut gauche) et recB (coin bas droit).

On accède facilement aux données en écrivant tout simplement dimEcran.x pour la largeur et dimEcran.y pour la hauteur

 

Notre programmation set modifié comme suit :

Avant la déclaration de setup et draw, on défini les variables globales :

  • dimEcran = (1000, 800) : hauteur de l'écran,
  • pos = (random(dimEcran.x),random(dimEcran.y)) : position de la balle au départ,
  • dir = (1,1) : direction, >0 donc vers la droite,
  • vit = (5, 5) : ça va plus vite que 1,
  • recDim = (random(3,100),random(3,100)) : dimensions : pas plus de 100*100,
  • recCoin = (random(dimEcran.x-recDim.x),random(dimEcran.y-recDim.y)) : coin en haut à gauche, pas en dehors de l'écran,

dans setup() :

  • on défini la taille de l'écran, attention, il faut convertir les dimEcran.x et .y en entier avec int() comme ceci : size(int(dimEcran.x),int(dimEcran.y));

dans draw() :

  • d'abord on teste pos pour savoir si on touche un bord.
  • ensuite on reteste pos pour savoir si on touche l'obstacle.
  • si il faut inverser la direction x ou y, on le fait.
  • ensuite,on calcule la nouvelle position.
  • et on dessine l'ellipse en position (posX, posY).

 

Remarquer l'usage des fonctions pour représenter le cadre de l'obstacle et changer la couleur. nous en utiliserons de + en +.

Etape 1a : Faire bouger l'obstacle
La balle se ballade. Le cadre est déplacé par la souris.

Super simple.

il suffit d'ajouter les lignes suivantes dans la fonction drawObstacle(), juste avant le dessin du rectangle ...

  recCoin.x=mouseX;
  recCoin.y=mouseY;

Bon, on modifiera le format du rectangle pour qu'il n'occupe pas toute la place.

Il ne reste plus qu'à limiter la position du rectangle et en route vers le casse brique !

Maieuh, on avait dit un pong pour jouer à deux ...

Bon, d'accord, va pour le Pong

Etape 2 : Casse ... brique (ou presque)
L'obstacle est déplacé par la souris, selon un schéma défini. Si la balle atteind une limite, elle repart d'une position aléatoire.

Ici, beacoup de changements :

  • On commence par définir une limite basse et on positionne les éléments en fonction de celle-ci (balle et curseur).
  • Puis, on affiche une limite au delà de laquelle la balle repart d'une position aléatoire dans l'écran,
    cette limite sera faite avec un rectangle plus sombre et pour simplifier l'écriture du programme, le rafraichissement de l'écran sera fait dans une fonction initScreen(),
  • Ensuite, on limite le déplacement de l'obstacle qui devient un curseur (les noms des variables et des fonctions ont changé).
  • Enfin, pour améliorer la lisibilité du programme, le test de contact entre la balle et le curseur ont aussi été mis dans une fonction.
Etape 3 : Capture des touches
Capturer un événement au clavier pour faire bouger le curseur. Préparation pour 2 joueurs car on n'a qu'une seule souris, hélas, c'est là qu'est l'os.

Pour capturer un événement au clavier, il faut :

  • créer une fonction qui déplace le curseur (curseur_move()): on lui donne la nouvelle position et elle calcule & contrôle les coordonnées,
  • modifier curseur_draw(), qui ne fait plus qu'afficher le curseur, on enlève la variable de la souris,
  • ajouter la fonction keyPressed() qui va être appelée à chaque appui d'une touche.
  • Enfin, pour améliorer la lisibilité du programme, le test de contact entre la balle et le curseur ont aussi été mis dans une fonction.
Etape 4 : Affichage du score
Afficher le score se fera avec des caractères ressemblant à la version originale de Pong.

Pour l'instant, on n'incrémente le score que si on touche la face du haut du curseur. On ne bloque pas le jeu si on rate la balle.

Les modifications sont faites à plusieurs endroits :

  • Dans ball_chkPong, on ajoute l'incrément du score si on touche la bonne face,
  • Dans initScreen, on à changé la technique d'effacement complet de l'écran à chaque cycle,

Ensuite, pour l'affichage du score, on ajoute les fonctions suivantes :

  • score_draw qui est appelée à chaque cycle et qui calcule la valeur de chaque caractère (s1 - celui des unités et s2 - celui des dizaines),
  • digit_draw qui affiche un caractère numérique grâce a des segments (il y en a 9 possibles)
    J'ai choisi 7 segments normaux + les deux complets de droit et gauche pour simplifier quelques tests,

A chacune de ces fonctions, il faut trasmettre la position d'affichage du coin supérieur-gauche.

Pour améliorer la vitesse de calcul, j'ai pré-calculé des valeurs qui ne le seront que au début du programme et pas à chaque affichage ...

J'ai pas vraiment vu beacoup de changement, mais un peu quand même, dans la fluidité de la bille.

A suivre au prochain chapitre.

Etape 5 : on passe en affichage vertical
Afficher jeu avec un curseur qui défile verticalement à gauche.

Certaines variables ont été renommées pour préparer l'apparition du second curseur.

Des modifications sont faites à plusieurs endroits :

  • Dans keyPressed(), seul le calcul de la position "y" est délégué à la fonction curseur_move(), cette dernière change donc quelque peu.
  • curseur_move() utilise un nouveau paramètre, la direction, ce qui permet de faire le calcul dans la fonction et pas avant.
    De plus, la fonction retourne un résultat qui est la nouvelle position y à prendre.
  • Dans initScreen(), le décors est aussi modifié et le score est décalé autour d'un trait vertical.

Ensuite, pour l'affichage du score, on ajoute les fonctions suivantes :

  • score_draw qui est appelée à chaque cycle et qui calcule la valeur de chaque caractère (s1 - celui des unités et s2 - celui des dizaines),
  • digit_draw qui affiche un caractère numérique grâce a des segments (il y en a 9 possibles)
    J'ai choisi 7 segments normaux + les deux complets de droit et gauche pour simplifier quelques tests,

A chacune de ces fonctions, il faut trasmettre la position d'affichage du coin supérieur-gauche.

Pour améliorer la vitesse de calcul, j'ai pré-calculé des valeurs qui ne le seront que au début du programme et pas à chaque affichage ...

J'ai pas vraiment vu beacoup de changement, mais un peu quand même, dans la fluidité de la bille.

A suivre au prochain chapitre.

Etape 6 : on passe en mode 2 joueurs.
Tout est dans le titre. Fin du projet ... pour l'instant.

Certaines variables ont été doublées et préfixées avec j1_ et j2_ pour différencier les deux joueurs.

Des modifications sont faites à plusieurs endroits :

  • Dans keyPressed(), seul le calcul de la position "y" est délégué à la fonction curseur_move(), cette dernière change donc quelque peu, ajout des lettres a et q pour le joueur 2.
  • curseur_move() utilise un nouveau paramètre, la direction, ce qui permet de faire le calcul dans la fonction et pas avant.
    De plus, la fonction retourne un résultat qui est la nouvelle position y à prendre.
  • curseur_draw() utilise aussi un nouveau paramètre : le curseur à afficher.
  • balle_init() est une nouvelle fonction qui sert à réinitialiser la position de départ de la balle.
    Elle est appelée dans setup() puis à chaque fois qu'un score est modifié dans balle_chkPong() sans paramètres (voir + loin).
  • Dans initScreen(), le décors est aussi modifié et le score est décalé autour d'un trait vertical.

Le plus gros changement tiens dans la "surcharge" de la fonction balle_chkPong qui est définie deux fois, avec des paramères différents :

  • 1ère définition : sans paramètres, sert à faire les rebonds sur les cotés de l'écran, lancer le calcul du score de l'un ou l'autre joureur et réinitialiser la balle
  • 2ème définition : avec un curseur en paramètre : sert à effectuer les rebonds sur le curseur donné,

Chacune de ces fonctions retourne vrai ou faux, selon que le rebond a eu lieu ou non (plus utilisé).

La surcharge d'une fonction est chose courante en programmation Processing (et java) afin de faire des actions similaires, mais avec des paramètres différents.

En fait, c'est surtout utilisé en programmation objet (qu'on verra plus tard).

Il manque quelques petites choses pour rendre le programme intéressant à jouer (c'est quand même pour ça qu'on l'a fait) :

  • donner un effet à la balle solon la façon dont le rebond est fait sur le curseur, en fonction de son déplacement ou de la distance entre le milieu du curseur et l'impact de la balle, à vous de choisir,
  • arrêter le jeu lorsqu'un des deux joueur atteint un score donné (10, par exemple) et afficher le coté du vainqueur (texte, couleur, clignotement, etc. ...).

Fin du projet ou à suivre en prog objet.

Et moi, hé hé, je vais faire un tour en ville, le temps de digérer tout ça, avec une bonne glace (c'est l'printemps !).