Jeu de réflexes multijoueurs avec Arduino

Uncle Den's Uncle Den's

Jouer à "Pong" sur une TV par la péritel avec Arduino

Août 2021
 

https://youtu.be/UYyoqw1UuQw

Le but de ce montage est double:

But du jeu
La balle rebondit surles bords d'un rectangle, et le joueur dirige vers la gauche/droite un  palet via des boutons poussoirs situés sur la Breadboard Arduino, pour éviter que la balle ne sorte par le bas. A chaque rebond, un point est marqué, le but jdu jeu etant d'accumuler un maximum de point. Le score en cours est affiché en haut à gauche de l'écran, et le score maximum obtenu est écrit juste en dessous.
Pour corser le tout, le jeu accelere petit à petit, le rebond à la surface du palet varie en fonction de où se fait le rebond sur ce palet. Par ailleurs, sur le coté gauche de l'écran s'affiche une jauge. Une fois la jauge remplie, les touche gauche-droite s'inverse, jusqu''au moment où la jauge se remplit de nouveau.

La partie s'arrete lorsque la balle n'a pas été interceptée. (5 secondes se passent, les variables et le score sont réinitialisés, et le jeu est relancé automatiquement)


Le matériel, le montage, la connectique, la programmation.

Arduino va commander l'affichage de la TV via la prise Peritel (ou via la prise RCA que je n'ai pas testé). Il faut installer la bibliothèque (library) TVout.h (voir telechargement plus loin). Il sera ainsi possible de jouer sur un écran de 120*96pixels en noir et blanc. Ce sont les résolutions maximales qu'on peut espérer obtenir avec Arduino). Un petit montage électronique (2 résistances de 1kohm et 471 ohm) doit etre réalisé sur la BreadBoard qui relira l'Arduino à la TV. Pour un Uno ou ATmega168/328, on utilisera les broches 7 et 9, alors que  pour le Leonardo, on utilisera plutot les sorties 8 et 9.

(voir les liens https://code.google.com/archive/p/arduino-tvout/ , https://eecs.blog/arduino-tvout-library-image-output/ , https://eecs.blog/arduino-rca-video-output-to-tv/ )

connexion peritel

 

MCU

SYNC

VIDEO

AUDIO

Arduino

SYNC

VIDEO

AUDIO

ATmega168/328

PB1

PD7

PB3

NG,Decimila,UNO

9

7

11

ATmega1280/2560

PB5

PA7

PB4

Mega

11

29

10

ATmega644/1284p*

PD5

PA7

PD7

Sanguino

13

24

8

ATmega32u4**

PB5

PB4

PB7

Leonardo

9

8

11

AT90USB1286

PB5

PF7

PB4

Teensy++

_

_

_

Le cable péritel etant croisé, il conviendra de connecter les bonnes fiches:

connexion péritel

 

Avec cette librairy (+librairy fontAll.h vue un peu plus loin), il est ainsi possible de (coordonnée: x et y, couleurs 0=noir et 1= blanc):

configuraiton de l'affichage

TV.begin(PAL,120,96);

efface l'écran

TV.clear_screen();

dessiner un pixel

TV.set_pixel(x,y,couleur);

dessiner une ligne TV.draw_line(x1,y1,x2,y2,couleur);
dessiner un rectangle

TV.draw_rect(x,y,largeur,hauteur,couleur de la bordure,couleur de remplissage);

délais d'attente

TV.delay(60);

positionnement du curseur (texte)

TV.set_cursor(x,y);

écrire un texte

TV.println(texte à écrire);

sélection de la police (ici font6x8)

TV.select_font(font6x8);


Ainsi avec la librairy TVout.h, on pourra dessiner des points, des lignes et des rectangles voire des cercles (voir liste complete en fin de cette page ou sur https://sourceforge.net/p/arduino-tvout/wiki/FDcomplete/

 

L'affichage du score necessaite l'installation de la librairy fontALL.h (non disponible directement dans Croquis/inclure une biblbiothèque dans l'interface de programmation Aduino). Il faut l'installer à la main.  (voir derniere partie de la page https://knowledge.parcours-performance.com/librairies-arduino-installer/ )

méthode manuelle

  1. fermer l’interface arduino ;
  2. dezipper le fichier téléchargé et y sélectionner le ou les répertoires que je veux réellement installer (Copier).
  3. coller ces répertoires dans le répertoire “user/ Documents\Arduino\libraries”
  4. redémarrer l’interface arduino, la ou les librairies sont maintenant disponibles.

 

> télécharger les library TVout et FontALL (zip) à dézipper et glisser dans Mes_documents\Arduino\libraries (c'est le dossier sur mon ordinateur perso)

 

Afin de controler la raquette, on aura besoin de 2 boutons poussoirs et de 2 résistances (élevée, peu importe la valeur) Voici le montage complet:

montage arduino peritel

 

 


 


#include <TVout.h>
#include <fontALL.h>

TVout TV;
int score=0;
int scoremax=0;
const int xcadrejaugemin=0;
const int wcadrejauge=8;
const int ycadrejaugemin=20;
const int hcadrejauge=95-ycadrejaugemin;

float vjauge=0.4;
const int hj=hcadrejauge-4;
const int yjmin= ycadrejaugemin+2;
const int yjmax= ycadrejaugemin+hcadrejauge-2;
const int xjmin=xcadrejaugemin+2;
const int wj=wcadrejauge-4;
float hjauge=0.0;

float vlim=1.8;
const int gauche=10;
const int droite=11;
float xbal=60.2;
float ybal=2.1;
float vxbal=-1.1;
float vybal=0.9;
float delai=40;
const float deltat=0.01;
int xibal=int(xbal);
int yibal=int(ybal);
const int xmin=30;
const int xmax=118;
const int ymin=1;
const int ymax=94;
const int rxmin=xmin-1;
const int rw=xmax-xmin+2;
const int rymin=ymin-1;
const int rh=ymax-ymin+2;
float largbar=8;
int xbar = int((xmin+xmax-largbar)/2);
int ybar =ymax+1;
int barMax=36;
int vbar=3;

void setup() {
TV.begin(PAL,120,96);
TV.select_font(font6x8);
pinMode(gauche, INPUT);
pinMode(droite, INPUT);
TV.clear_screen();
TV.draw_rect(rxmin,rymin,rw,rh,1,0); //cadre de jeu
TV.draw_line(rxmin,rymin+rh,rxmin+rw,rymin+rh,0); // on efface la base du cadre de jeu
TV.draw_rect(xcadrejaugemin,ycadrejaugemin,wcadrejauge,hcadrejauge,1,0);// cadre jauge
}

void loop() {
TV.set_cursor(0,0);
TV.println(score);
TV.set_cursor(0,10);
TV.println(scoremax);

// jauge
hjauge=hjauge+vjauge;
if (int(hjauge)>hj){
  vbar=-vbar;
  hjauge=0.0;
  TV.draw_rect(xjmin,yjmin,wj,hj,0,0);
}

TV.draw_rect(xjmin,yjmax-int(hjauge),wj,int(hjauge),1,1);

// emplacement du palet
TV.draw_line(xbar,ybar,int(xbar+largbar),ybar,0); // on efface le precedent palet
xbar=xbar+vbar*(digitalRead(droite)-digitalRead(gauche));
if (xbar<xmin){xbar=xmin;}
else if ((xbar+largbar)>xmax){xbar=int(xmax-largbar);}
TV.draw_line(xbar,ybar,int(xbar+largbar),ybar,1); // on le reaffiche


//TV.set_cursor(0,10);
TV.set_pixel(xibal,yibal,0); // on efface la précedente balle
xbal+=vxbal;
ybal+=vybal;
delai=delai-deltat;
if (delai < 10){
  delai=10;}

//TV.draw_line(0,25,100,25,1);
if (xbal < xmin){
  xbal=xmin+xmin-xbal;
  vxbal=-vxbal;
  score+=1;
}else if (xbal > xmax){
  xbal=xmax+xmax-xbal;
  vxbal=-vxbal;
  score+=1;
}
if (ybal < ymin){
  ybal=ymin+ymin-ybal;
  vybal=-vybal;
  score+=1;
}else if (ybal > ymax){
  if ((xbal>=xbar)and(xbal<=(xbar+largbar))){
    ybal=ymax+ymax-ybal;
    vybal=-vybal;
    vxbal=vxbal+vlim*(xbal-(xbar+largbar/2))/largbar;
    score+=1;
    if (vxbal<-vlim) {vxbal=-vlim;}
    else if (vxbal>vlim) {vxbal=vlim;}
   
    }
   else{ // perdu : 5 secondes de fin de partie
    xibal=int(xbal);
    yibal=int(ybal);
    if ((xbal-float(xibal))>0.5) {xibal+=1;}
  
    if ((ybal-float(yibal))>0.5) {yibal+=1;}
    if (yibal>ymax){yibal=ymax;}
    TV.set_pixel(xibal,yibal,1); // on affiche la nouvelle balle

    TV.delay(5000);
    // on reinitialise les variables de départ
  TV.draw_line(xbar,ybar,int(xbar+largbar),ybar,0);// on efface le palet
    if (scoremax<score){scoremax=score;}
    score=0;
    xbal=60;
    ybal=2.1;
    xbar=60;
  vxbal=-1.1;
  vybal=0.9;
  delai=60;
  TV.set_pixel(xibal,yibal,0);// on efface la balle
  xibal=int(xbal);
  yibal=int(ybal);
  TV.set_pixel(xibal,yibal,1); // on affiche la nouvelle balle
  TV.draw_line(xbar,ybar,int(xbar+largbar),ybar,1);// on affiche le palet
    TV.delay(1000);
  TV.draw_rect(0,0,28,19,0,0);

   
   }
}

xibal=int(xbal);
yibal=int(ybal);
if ((xbal-float(xibal))>0.5) {xibal+=1;}
if ((ybal-float(yibal))>0.5) {yibal+=1;}

TV.set_pixel(int(xibal),int(yibal),1);
TV.delay(int(delai));
}
 


Details

The complete list of functions not broken down into sections.


Voir mes Aquarelles - Mon site sur les aquarelles

Blog sur mes aquarelles