Welcome to Hackster!
Hackster is a community dedicated to learning hardware, from beginner to pro. Join us, it's free!
galoebn
Published © GPL3+

"Connect 4" game on E-ink

In this project we make a connect 4 game using an e-ink display and an ESP32.

IntermediateFull instructions provided715
"Connect 4" game on E-ink

Things used in this project

Hardware components

2.9inch E-Ink display module
×1
ESP32
Espressif ESP32
×1

Story

Read more

Schematics

Wiring

Unfortunately I can't create a Fritzing file because the parts are not available there. Just connect all the wires so that the colors match. You also have to look at the pinout of your specific ESP32 board.

Code

e-ink_connect4

Arduino
#define ENABLE_GxEPD2_GFX 0

#include <GxEPD2_BW.h> // including both doesn't use more code or ram
#include <GxEPD2_3C.h> // including both doesn't use more code or ram
#include <U8g2_for_Adafruit_GFX.h>

GxEPD2_BW<GxEPD2_290_T94_V2, GxEPD2_290_T94_V2::HEIGHT> display(GxEPD2_290_T94_V2(/*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16, /*BUSY=*/ 4)); // GDEM029T94, Waveshare 2.9" V2 variant
U8G2_FOR_ADAFRUIT_GFX u8g2Fonts;

uint16_t bg = GxEPD_WHITE; //white
uint16_t fg = GxEPD_BLACK;  //black
int x = 150;
int mat[6][7] = {{0,0,0,0,0,0,0},{0,0,0,0,0,0,0},{0,0,0,0,0,0,0},{0,0,0,0,0,0,0},{0,0,0,0,0,0,0},{0,0,0,0,0,0,0}}; //here the placement is stored. 0 --> not occupied; 1 --> playerA; 2 --> playerB
int player = 1; //we begin with playerA
bool win = false;

bool touch1detected = false; //variables to indicate if a touch pin is high
bool touch2detected = false;

void gotTouch2(){
 touch2detected = true;
}
void gotTouch1(){
 touch1detected = true;
}

void place(int player, int x){ //this function fills in the circles/crosses the players place
  int col = (x - 132)/18 - 1;
  display.setPartialWindow(145, 17, 296, 128);
  display.firstPage();

  for(int i = 5; i >= 0; i--){
    if(mat[i][col] == 0){
      mat[i][col] = player;
      break;
    }
  }
  
  
  do{
    display.drawRect(150, 18, 126, 108, fg);
    display.drawLine(150, 36, 274, 36, fg);
    display.drawLine(150, 54, 274, 54, fg);
    display.drawLine(150, 72, 274, 72, fg);
    display.drawLine(150, 90, 274, 90, fg);
    display.drawLine(150, 108, 274, 108, fg);
    display.drawLine(168, 18, 168, 124, fg);
    display.drawLine(186, 18, 186, 124, fg);
    display.drawLine(204, 18, 204, 124, fg);
    display.drawLine(222, 18, 222, 124, fg);
    display.drawLine(240, 18, 240, 124, fg);
    display.drawLine(258, 18, 258, 124, fg);

    for(int i = 0; i < 6; i++){
      for(int j = 0; j < 7; j++){
        if(mat[i][j] == 1){
          display.fillCircle(159+j*18, 27+i*18, 5, fg);
        }
        else if(mat[i][j] == 2){
          display.fillRect(157+j*18, 20+i*18, 4, 14, fg);
          display.fillRect(152+j*18, 25+i*18, 14, 4, fg);
        }
      }
    }
  }
  while(display.nextPage());
}


bool check_if_4(){    //this function checks if theres a line of four pieces
  for(int i = 0; i < 3; i++){
    for(int j = 0; j < 7; j++){
      if(mat[i][j] == mat[i+1][j] && mat[i+1][j] == mat[i+2][j] && mat[i+2][j] == mat[i+3][j] && mat[i][j] != 0){
        return true;
      }
    }
  }

  for(int i = 0; i < 6; i++){
    for(int j = 0; j < 4; j++){
      if(mat[i][j] == mat[i][j+1] && mat[i][j+1] == mat[i][j+2] && mat[i][j+2] == mat[i][j+3] && mat[i][j] != 0){
        return true;
      }
    }
  }

  for(int i = 0; i < 3; i++){
    for(int j = 0; j < 4; j++){
      if(mat[i][j] == mat[i+1][j+1] && mat[i+1][j+1] == mat[i+2][j+2] && mat[i+2][j+2] == mat[i+3][j+3] && mat[i][j] != 0){
        return true;
      }
    }
  }

  for(int i = 0; i < 3; i++){
    for(int j = 3; j < 7; j++){
      if(mat[i][j] == mat[i+1][j-1] && mat[i+1][j-1] == mat[i+2][j-2] && mat[i+2][j-2] == mat[i+3][j-3] && mat[i][j] != 0){
        return true;
      }
    }
  }
  
  return false;
}


void(* resetFunc) (void) = 0; //resets the game if someone won


void setup()
{
  touchAttachInterrupt(T3, gotTouch2, 40); //the 40 sets the sensitivity of the touchpin
  touchAttachInterrupt(T4, gotTouch1, 40); //bigger number --> higher sensitivity
  
  display.init();
  display.setTextColor(GxEPD_BLACK);
  
  display.firstPage();
  display.setRotation(1); //rotate the screen 90°

  u8g2Fonts.begin(display); // connect u8g2 procedures to Adafruit GFX
  delay(1000);

  u8g2Fonts.setFont(u8g2_font_logisoso16_tr);

  u8g2Fonts.setForegroundColor(fg);         // apply Adafruit GFX color
  u8g2Fonts.setBackgroundColor(bg); 
  
  do
  {
    display.fillScreen(GxEPD_WHITE);
    u8g2Fonts.setCursor(10, 30); 
    u8g2Fonts.println("Connect 4"); //title
    u8g2Fonts.setCursor(10, 80); 
    u8g2Fonts.println("Player A");
    

    display.drawRect(150, 18, 126, 108, fg); //print the grid
    display.drawLine(150, 36, 274, 36, fg);
    display.drawLine(150, 54, 274, 54, fg);
    display.drawLine(150, 72, 274, 72, fg);
    display.drawLine(150, 90, 274, 90, fg);
    display.drawLine(150, 108, 274, 108, fg);
    display.drawLine(168, 18, 168, 124, fg);
    display.drawLine(186, 18, 186, 124, fg);
    display.drawLine(204, 18, 204, 124, fg);
    display.drawLine(222, 18, 222, 124, fg);
    display.drawLine(240, 18, 240, 124, fg);
    display.drawLine(258, 18, 258, 124, fg);
  }
  while (display.nextPage());
}


void loop(){
  
  display.setPartialWindow(150, 0, 126, 15);
  display.firstPage();
  
  do{
    display.fillTriangle(x, 4, x+18, 4, x+9, 13, fg);
  }
  while(display.nextPage());
  
  delay(100);
  touch2detected = false;
  touch1detected = false;
  while(!touch2detected && !touch1detected){delay(10);} //the program waits until there is a touch input
  if(touch1detected){
    place(player, x);
    
    if(check_if_4()){  //if true someone connected 4 --> the game is over
      display.setPartialWindow(0, 35, 140, 98);
      display.firstPage(); 
  
      do
      {
        display.fillScreen(GxEPD_WHITE);
        u8g2Fonts.setCursor(10, 80); 
        if(player == 1){u8g2Fonts.println("Player A won");}
        else{u8g2Fonts.println("Player B won");}
      }
      while (display.nextPage()); 
      delay(3000);
      resetFunc(); //reset the program
    }
    
    if(player == 1){player = 2;} //switch players
    else{player = 1;}

    display.setPartialWindow(0, 35, 140, 98);
    display.firstPage(); 
  
    do
    {
      display.fillScreen(GxEPD_WHITE);
      u8g2Fonts.setCursor(10, 80); 
      if(player == 1){u8g2Fonts.println("Player A");}
      else{u8g2Fonts.println("Player B");}
    }
    while (display.nextPage());  
  }
  
  else{
    x += 18;
    if(x > 258){x = 150;}
  }

}

Credits

galoebn
9 projects • 5 followers
Contact

Comments

Please log in or sign up to comment.