Tetris on Vex IQ gen2 brain

I wanted to share a Tetris clone I wrote for the gen2 IQ brain. No controller required.

Demo:

Source code: vexiq/games/vex_iq_gen2_tetris.cpp at main · iamwill/vexiq · GitHub

I’d love to see what else people have done and I hope this inspires someone out there to build something even better!

Feedback welcome.

Have a great day!

21 Likes

Wow! Thats wild you got that to work!

1 Like

Had time to run this today, nice job.

The code also runs on a VEX EXP brain with almost no modification, just change the controller button events. EXP has a bit more sound capability than IQ2, it has sharps/flats available as notes and 4 octaves. It can also play wav files from the SD card (mono and less than 22.5k sample rate).

here is some demo code showing how to play the tetris theme in both ways (assumes a file Tetris.wav is on SD card).

demo code
/*----------------------------------------------------------------------------*/
/*                                                                            */
/*    Module:       main.cpp                                                  */
/*    Author:       james                                                     */
/*    Created:      3/3/2024, 3:08:15 PM                                      */
/*    Description:  EXP project                                               */
/*                                                                            */
/*    Based on code by Robson Couto modified for EXP.                         */
/*                                                                            */
/*    Tetris theme - (Korobeiniki)                                            */
/*    More songs available at https://github.com/robsoncouto/arduino-songs    */                                            
/*                                                                            */
/*                                                Robson Couto, 2019          */
/*                                                                            */
/*----------------------------------------------------------------------------*/
#include "vex.h"

using namespace vex;

// A global instance of vex::brain used for printing to the EXP brain screen
vex::brain       Brain;


#define NOTE_C4  0
#define NOTE_CS4 1
#define NOTE_D4  2
#define NOTE_DS4 3
#define NOTE_E4  4
#define NOTE_F4  5
#define NOTE_FS4 6
#define NOTE_G4  7
#define NOTE_GS4 8
#define NOTE_A4  9
#define NOTE_AS4 10
#define NOTE_B4  11

#define NOTE_C5  12
#define NOTE_CS5 13
#define NOTE_D5  14
#define NOTE_DS5 15
#define NOTE_E5  16
#define NOTE_F5  17
#define NOTE_FS5 18
#define NOTE_G5  19
#define NOTE_GS5 20
#define NOTE_A5  21
#define NOTE_AS5 22
#define NOTE_B5  23

#define NOTE_C6  24
#define NOTE_CS6 25
#define NOTE_D6  26
#define NOTE_DS6 27
#define NOTE_E6  28
#define NOTE_F6  29
#define NOTE_FS6 30
#define NOTE_G6  31
#define NOTE_GS6 32
#define NOTE_A6  33
#define NOTE_AS6 34
#define NOTE_B6  35

#define REST     99

// change this to make the song slower or faster
int tempo=144; 

// notes of the moledy followed by the duration.
// a 4 means a quarter note, 8 an eighteenth , 16 sixteenth, so on
// !!negative numbers are used to represent dotted notes,
// so -4 means a dotted quarter note, that is, a quarter plus an eighteenth!!
int melody[] = {

  //Based on the arrangement at https://www.flutetunes.com/tunes.php?id=192
  
  NOTE_E5, 4,  NOTE_B4,8,  NOTE_C5,8,  NOTE_D5,4,  NOTE_C5,8,  NOTE_B4,8,
  NOTE_A4, 4,  NOTE_A4,8,  NOTE_C5,8,  NOTE_E5,4,  NOTE_D5,8,  NOTE_C5,8,
  NOTE_B4, -4,  NOTE_C5,8,  NOTE_D5,4,  NOTE_E5,4,
  NOTE_C5, 4,  NOTE_A4,4,  NOTE_A4,8,  NOTE_A4,4,  NOTE_B4,8,  NOTE_C5,8,

  NOTE_D5, -4,  NOTE_F5,8,  NOTE_A5,4,  NOTE_G5,8,  NOTE_F5,8,
  NOTE_E5, -4,  NOTE_C5,8,  NOTE_E5,4,  NOTE_D5,8,  NOTE_C5,8,
  NOTE_B4, 4,  NOTE_B4,8,  NOTE_C5,8,  NOTE_D5,4,  NOTE_E5,4,
  NOTE_C5, 4,  NOTE_A4,4,  NOTE_A4,4, REST, 4,

  NOTE_E5, 4,  NOTE_B4,8,  NOTE_C5,8,  NOTE_D5,4,  NOTE_C5,8,  NOTE_B4,8,
  NOTE_A4, 4,  NOTE_A4,8,  NOTE_C5,8,  NOTE_E5,4,  NOTE_D5,8,  NOTE_C5,8,
  NOTE_B4, -4,  NOTE_C5,8,  NOTE_D5,4,  NOTE_E5,4,
  NOTE_C5, 4,  NOTE_A4,4,  NOTE_A4,8,  NOTE_A4,4,  NOTE_B4,8,  NOTE_C5,8,

  NOTE_D5, -4,  NOTE_F5,8,  NOTE_A5,4,  NOTE_G5,8,  NOTE_F5,8,
  NOTE_E5, -4,  NOTE_C5,8,  NOTE_E5,4,  NOTE_D5,8,  NOTE_C5,8,
  NOTE_B4, 4,  NOTE_B4,8,  NOTE_C5,8,  NOTE_D5,4,  NOTE_E5,4,
  NOTE_C5, 4,  NOTE_A4,4,  NOTE_A4,4, REST, 4,
  

  NOTE_E5,2,  NOTE_C5,2,
  NOTE_D5,2,   NOTE_B4,2,
  NOTE_C5,2,   NOTE_A4,2,
  NOTE_GS4,2,  NOTE_B4,4,  REST,8, 
  NOTE_E5,2,   NOTE_C5,2,
  NOTE_D5,2,   NOTE_B4,2,
  NOTE_C5,4,   NOTE_E5,4,  NOTE_A5,2,
  NOTE_GS5,2,

};


void soundTrack() {
  // sizeof gives the number of bytes, each int value is composed of two bytes (16 bits)
  // there are two values per note (pitch and duration), so for each note there are four bytes
  int notes=sizeof(melody)/sizeof(melody[0])/2; 

  // this calculates the duration of a whole note in ms (60s/tempo)*4 beats
  int wholenote = (60000 * 4) / tempo;

  int volume = 10;

  int divider = 0, noteDuration = 0;

  while(1) {
    // iterate over the notes of the melody. 
    // Remember, the array is twice the number of notes (notes + durations)
    for (int thisNote = 0; thisNote < notes * 2; thisNote = thisNote + 2) {

      // calculates the duration of each note
      divider = melody[thisNote + 1];
      if (divider > 0) {
        // regular note, just proceed
        noteDuration = (wholenote) / divider;
      } else if (divider < 0) {
        // dotted notes are represented with negative durations!!
        noteDuration = (wholenote) / abs(divider);
        noteDuration *= 1.5; // increases the duration in half for dotted notes
      }

      if( melody[thisNote] == 99 ) {
        // rest
        this_thread::sleep_for(noteDuration);
      }
      else {
        // we only play the note for 90% of the duration, leaving 10% as a pause
        Brain.playNote( melody[thisNote] / 12, melody[thisNote] % 12, noteDuration*0.9, volume );
        this_thread::sleep_for(noteDuration*0.1);
      }
    }
  }
}

int
soundTrackUsingWav() {
    int volume = 10;

    while(1) {
      Brain.playFile("Tetris.wav", volume);

      // wait for completion
      while(Brain.soundIsActive() ) {
        this_thread::sleep_for(100);
      }
    }

    return 0;
}

int main() {
    //thread t1(soundTrackUsingWav);
    soundTrack();

    while(1)
      this_thread::sleep_for(500);
}
3 Likes

I will get a V5 brain and check it out.

2 Likes

EXP, not V5. V5 has no sound capability at all.

2 Likes

I’m working on a dino game similar to chrome://dino

4 Likes

Right on… it doesn’t build for me though:

Log
unix build for platform vexiq2 on Darwin x86_64
CXX src/dino.cpp
CXX src/main.cpp
LINK build/dinogame.elf
arm-none-eabi-ld: build/dinogame.elf section `.text' will not fit in region `SRAM_1_2_3'
arm-none-eabi-ld: region `SRAM_1_2_3' overflowed by 68704 bytes
make: *** [build/dinogame.elf] Error 1

Make process closed with exit code: 2

Two things:

  1. It’s not fully complete, so a lot of functions are not implemented yet, even if they have declarations.
  2. It looks like the error is similar to this one. It appears that I included too many libraries. The new code should work fine.