Batakid, un jeu pour enfants de 1 à 100ans

Alors tout a commencé par un peu d’usinage (dans la nuit de samedi à dimanche, quitte à fabriquer mes cadeaux de noel, autant être à la bourre, sinon c’est moins drôle) :

Ce qui après de longs moments bruyants à fini par donner ça :

Auquel on va ajouter quelques transistors et un bon lot de fils :

Puis un arduino méga :

Et enfin on branche le tout :

Et on ferme la boiboite :

Puis on repasse une nuit blanche dans la foulée du réveillon pour faire un peu de code, de sorte que le matin :

Voila le code qui est dedans en ce moment :

/*************************************************************************************
 *                                                                                   *
         Jeu type "batak" minimaliste pour enfant sur base arduino
 *                                                                                   *
 *************************************************************************************/

#include "yasm.h" // http://forum.arduino.cc/index.php?topic=525092
#include "btn.h"
#include <Streaming.h> // https://github.com/janelia-arduino/Streaming



/****définitions relatives aux leds et aux boutons************************************/
#define ON HIGH
#define OFF LOW
#define BTN_NBR 10
const int8_t BtnPin[BTN_NBR] = {44, 42, 40, 38, 36, 34, 32, 30, 26, 28};
const int8_t LedPin[BTN_NBR] = {45, 43, 41, 39, 37, 35, 33, 31, 27, 29};

void toutesLeds(bool aEtat)
{
  for (int8_t i = 0; i < BTN_NBR; i++)
    digitalWrite(LedPin[i], aEtat);
}

BTN Bouton[BTN_NBR];
int8_t BoutonActuel;

void lireBoutons()
{
  BoutonActuel = -1;

  for (uint8_t i = 0; i < BTN_NBR; i++)
    Bouton[i].update(!digitalRead(BtnPin[i]));

  for (uint8_t i = 0; i < BTN_NBR; i++) {
    if (Bouton[i].state(BTN_CLICK)) {
      BoutonActuel = i;
      return;
    }
  }
}

/******** fonction de mise en veille *************************************************/
YASM Veille;

void veille()
{
  if (BoutonActuel != -1)
    Veille.next(veille, true); // si un bouton est appuyé on re-rentre dans l'état pour remettre à zéro le compteur

  if ( Veille.elapsed(600E3))
    //Si on est dans l'état depuis 10 minutes (600*10^3millisecondes) sans actions
    //sur les boutons, alors on met le circuit en veille :
    faisDodo();
}

#include <avr/sleep.h> // https://playground.arduino.cc/Learning/arduinoSleepCode
void faisDodo()
{
  animationFin();
  animationFin();
  toutesLeds(OFF);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  sleep_mode(); // adieu mondre cruel !
}

/****** fonction de chenillard ******************************************************/
YASM Chenillard;
unsigned long ChenDelai;
int8_t ChenNbr;

void chenillard(unsigned long aDelai, int8_t aNombre = 1, bool aAttendreFin = true)
{
  if ( aDelai == 0 ) {
    Chenillard.stop();
    return;
  }
  ChenDelai = aDelai;
  ChenNbr = aNombre;
  Chenillard.next(chen);
  if ( aAttendreFin )
    while ( Chenillard.run() ) {}
}

void chen()
{
  static uint8_t position;

  if ( Chenillard.isFirstRun() )
    position = 0;

  if ( Chenillard.periodic(ChenDelai) ) {
    if ( position >= (BTN_NBR + ChenNbr) ) {
      //si on est arrivé au bout de la chenille, on stoppe le chenillard
      Chenillard.stop();
      //et on remet le dernière led utilisée dans son état initial
      digitalWrite(LedPin[0], !digitalRead(LedPin[0]));
      //puis on quitte avant de rallumer un truc
      return;
    }

    //basculement de l'état de la led courante
    if ( position < BTN_NBR )
      digitalWrite(LedPin[position], !digitalRead(LedPin[position]));
    else if ( position == BTN_NBR )
      digitalWrite(LedPin[0], !digitalRead(LedPin[0]));

    //extinction de la dernière led de la chenille
    int8_t temp = (position - ChenNbr);
    if ( (temp) > -1)
      if ( temp < BTN_NBR )
        digitalWrite(LedPin[temp], !digitalRead(LedPin[temp]));
      else if ( temp == BTN_NBR )
        digitalWrite(LedPin[0], !digitalRead(LedPin[0]));

    position++;
  }
}

void animationFin()
{
  toutesLeds(OFF);
  delay(60);
  toutesLeds(ON);
  delay(60);
  toutesLeds(OFF);
  delay(60);
  toutesLeds(ON);
  delay(60);
  toutesLeds(OFF);
  delay(60);
  toutesLeds(ON);
  delay(60);
  toutesLeds(OFF);
  chenillard(30, 2);
  chenillard(30, 10);
}



/***** Programme principal ********************/
YASM Programme;

void prg_init()
{
  if (Programme.isFirstRun())
    toutesLeds(OFF);

  if (Programme.periodic(700)) {
    digitalWrite(LedPin[9], !digitalRead(LedPin[9]));
    digitalWrite(LedPin[0], !digitalRead(LedPin[0]));
    digitalWrite(LedPin[1], !digitalRead(LedPin[1]));
  }

  switch (BoutonActuel) {
    case 9:
      Programme.next(prg_jeu1);
      break;
    case 0:
      Programme.next(prg_jeu2);
      break;
    case 1:
      Programme.next(prg_jeu3);
      break;
  }


}

void prg_jeu1()
{
  //allume/éteint chaque led

  if (Programme.isFirstRun())
    toutesLeds(OFF);

  if ( BoutonActuel != -1 )
    digitalWrite(LedPin[BoutonActuel] , !digitalRead(LedPin[BoutonActuel]));

  //test pour voir si toutes leds allumées :
  int8_t nombre = 0;
  for (int8_t i = 0; i < BTN_NBR; i++)
    nombre += (digitalRead(LedPin[i]) == ON);
  if ( nombre == BTN_NBR ) {
    delay(400); //sinon c'est pas beau
    animationFin();
    Programme.next(prg_init);
  }


}

void prg_jeu2()
{
  //chenillard avec plus ou moins de leds

  if (Programme.isFirstRun()) {
    toutesLeds(OFF);
    for (uint8_t i = 0; i < random(9); i++)
      digitalWrite(LedPin[random(9)], !digitalRead(LedPin[random(9)]));
    chenillard(50, 6);
  }

  if ( BoutonActuel != -1 ) {
    chenillard(400, BoutonActuel + 1, false);
    Programme.next(prg_jeu2, true); //remise à zéro des compteurs de temps
  }

  if ( Programme.elapsed(180E3))
    //si 3 minutes (180*10^3 ms) sont écoulées sans actions, on quitte le jeu
    Programme.next(prg_init);

  //test pour voir si toutes leds allumées :
  int8_t nombre = 0;
  for (int8_t i = 0; i < BTN_NBR; i++)
    nombre += (digitalRead(LedPin[i]) == ON);
  if ( nombre == BTN_NBR ) {
    delay(400); //sinon c'est pas beau
    animationFin();
    Programme.next(prg_init);
  }
}

void prg_jeu3()
{
  //allume/eteint chaque led dans l'ordre
  static uint8_t position;

  if (Programme.isFirstRun()) {
    toutesLeds(OFF);
    position = 0;
  }

  if ( position == 10 ) {
    delay(400); //sinon c'est pas beau
    animationFin();
    Programme.next(prg_init);
  }

  if ( BoutonActuel == position ) {
    digitalWrite(LedPin[position], ON);
    position++;
    return; //ici il faut quitter immédiatement sinon le test suivant annule l'action en cours !
  }

  if ( (BoutonActuel != -1) && (BoutonActuel == (position - 1)) ) {
    position--;
    digitalWrite(LedPin[position], OFF);
  }


}



void setup()
{
  for (int8_t i = 0; i < BTN_NBR; i++) {
    //paramétrage des broches utilisées
    pinMode(LedPin[i], OUTPUT);
    pinMode(BtnPin[i], INPUT_PULLUP);
  }
  randomSeed(analogRead(A0));

  //Serial.begin(115200);
  animationFin();
  Programme.next(prg_init);
  Veille.next(veille);
}

void loop()
{
  lireBoutons();
  Veille.run();
  Programme.run();
  Chenillard.run();
}

Le code est ici : github

Bravo,

Le père noël est passé à temps.

Ps: video de fraisage en mode privée , impossible à lire.

À temps mais de justesse !
Vidéo corrigée

Fraiseuse maison on dirait.. le résultat est nickel.

Bonjour,
Juste pour savoir, on joue comment? Que l'on me pardonne mon ignorance.

bah en fait le programme batak n'est pas encore fait

pour le moment, le but est d'allumer toutes les leds pour gagner, et il y a trois jeux possible

le premier est hyper simple : un appui sur un bouton=allumage/extinction de la led (je fabrique ce truc pour mon fils de 2 ans, au départ, ne l'oublions pas...)
le second est similaire, mais cette fois il faut le faire dans l'ordre pour que ça fonctionne
et le troisième (enfin le second dans le code : prg_jeu2 ) était juste un essai d'affichage, mais c'est finalement devenu une sorte de casse-tête assez efficace : au démarrage il y a un allumage aléatoire de certaines leds, et ensuite chaque appui sur une touche déclenche un chenillard, le nombre de leds étant directement lié au numéro du bouton appuyé (de 1 à 10 leds), avec une particularité toutefois : le chenillard ne fait pas tourner un état mais un changement d'état. Donc une led déjà allumée s'éteindra lors du passage de la chenille pour se rallumer à la fin, et inversement.
Jusque là, rien de bien fantastique : quel que soit le nombre de leds incriminées dans le chenillard, on va donc se retrouver à la fin de l'animation avec exactement les mêmes leds allumées qu'au début.
Oui mais seulement un appui sur un autre bouton pendant le déroulement du chenillard en change le nombre de leds, donc on peut ainsi figer des leds dans un état puisque si on raccourcit la chenille, elle abandonne sa "queue" en surnombre dans l'état courant. Ou si on la rallonge elle peut aussi provoquer des changements.
Ça semble simple dit comme ça, mais vu les heures que ma mère, mon oncle et ma tante ont passé dessus... c'est pas si mal :slight_smile:

edit : curieux, le code est affiché en vrac dans le message, alors qu'il est indenté correctement dans mon éditeur ??? on dirait que les tabulations ne sont pas affichées --> edit2 c'est bien ça, il faut indenter avec des espace pour que ça s'affiche correctement

Merci pour tes explications.
Et il y a combien de bouton poussoir?
Avec le programme, je vais avoir des soucis, je suis PIC en plus en Basic... noooooon pas taper.
Comme ma fille attend des jumeaux, j'ai 2 ans pour faire.
Et je n'ai pas (encore) de CNC, il y a du boulot.

Alors t''as tout le temps de te mettre sur arduino d'ici là :wink:

Et les boutons, il me semble facile sur les photos de voir qu'il y en a 10 ? Mais peu importe, tu peux en mettre le nombre que tu veux tant que tu as assez de broches pour les brancher

Si je comprends bien, ce sont des BP avec des LED?

Super boulot !! J’adore la boîte et l’usage des machines à état

C’est un lot de bouton de kit gamer/ arcade ? Où les avez vous trouvés?

merci :slight_smile:

Pour les boutons c'est ici sur aliexpress. Ce sont des boutons pour borne d'arcade, en effet.

Au départ, j'avais prévu d'utiliser seulement des boutons blancs, et de remplacer la led par une WS2812, de manière à pouvoir choisir les couleurs à volonté, mais je n'ai pas reçu les boutons blancs à temps. Et dans un sens, heureusement, vu que j'ai fini vraiment de justesse. Avec le temps de trafiquer les boutons, et de faire un code plus complexe je n'aurais jamais été prêt à temps pour Noël !

Le code a pas mal évolué depuis le premier message, il faut aller voir la version courante sur github.

des boutons russes - c'est louche :slight_smile:

Leptro:
Fraiseuse maison on dirait.. le résultat est nickel.

Oui, construction maison, détourné en routeur. Mais comme c'était pas prévu pour au départ, c'est pas assez rigide, il faudrait que je revoie les guidages
Voir ici pour la machine.

:confused:

J-M-L:
des boutons russes - c’est louche :slight_smile:

Heu ? Alors là j’ai pas compris ??

Screenshot_20190101_205053.png

bricofoy:
:confused:
Heu ? Alors là j’ai pas compris ??

euh moi le lien m’emmène sur

russe.png

ha ha, particularité bien pénible d'aliexpress : peu importe le libellé du lien, si la dernière fois un lien dans une langue autre que l'anglais a été ouvert (par exemple dans ton cas un lien en aliexpress.ru, manifestement), la langue reste enregistrée dans un cookie, et par la suite toutes les pages aliexpress s'ouvrent dans cette langue.

Il faut sélectionner "go to global site, english" dans la barre en haut à droite de la page pour revenir à la normale :wink:

oui - c'était juste pour faire un peu d'humour :slight_smile:

Les boutons poussoirs sont commandés. Maintenant, faut faire.

Oui. Tu nous diras ce que ça donne :slight_smile:

Si vous avez des idées de jeux à faire avec ces 10 boutons lumineux, je suis preneur, je sèche un peu sur les évolutions à proposer.
Pour le moment, j'ai :

  • allumer/éteindre
  • allumer seulement dans l'ordre
  • allumer d'abord l'intérieur pour déverrouiller l'extérieur
  • allumer avec des compléments à 10 (par exemple si on a appuyé en premier sur 7, il faut ensuite appuyer sur 3, sinon les deux boutons s’éteignent) qui reste à debugger un peu
  • allumer avec un chenillard (un bon casse tête ! )

Bonsoir
une sorte de SImon à 10 boutons maxi :
les leds s'allument une à une selon un motif aléatoire
lesd eteintes il faut reproduire avec les boutons le même motif