Space Shooters

A two player shooting game based on an ESP32 and ILI9341 TFT display.

This game was first imagined after creating the previous Arduino-based two player shooter and used new skills learned from the Arduino Racing Game.

Game Play

Simply put: this is a duel. First to 10 wins.

There is a 5 second count down time and the game starts. The game will not stop until someone is hit.

The arena of this battle to the death is contained within the bounds of the ILI9341 TFT screen. Your only defence from your opponent is behind a central island displaying the current score.

To help you carry out this task you are equipped with 16 shots. These shots will ricochet off the central island and wrap around the screen edges.

Hardware

Specification

ESP32 & shield – however any ESP32 should work.

ILI9341 TFT screen (240 x 320)

Two – 5 key keypad with analog outputs

Pinout

Controllers:

  • Ground and 3.3V
  • Player 1 output to D32 of ESP32
  • Player 2 output to D33 of ESP32

Screen:

Software

To date, this is the single largest sketch I’ve written – so that probably means that it’s the most inefficient sketch, too.

#include <TFT_eSPI.h> // Hardware-specific library
#include <SPI.h>

TFT_eSPI tft = TFT_eSPI();

const int keypadPin_P1 = 32;
const int keypadPin_P2 = 33;

int key_p1;
int key_p2;

const int ammo = 16;

//PLAYER 1 = blue
//PLAYER 2 = red

int x_p1 = 60;
int x_p2 = 260;
int y_p1 = 120;
int y_p2 = 120;
int rot_p1 = 0;
int rot_p2 = 4;

int shotCount_p1 = 0;
int shotX_p1[16];
int shotY_p1[16];
int shotRot_p1[16];
long shotTime_p1 = 0;
int shotCount_p2 = 0;
int shotX_p2[16];
int shotY_p2[16];
int shotRot_p2[16];
long shotTime_p2 = 0;

long gameTimer = 0;
const int refreshTime = 25;

bool moveCrafts = false;
//int movecraftcount = 0;

int score_p1 = 0;
int score_p2 = 0;

bool newHit = false;

//******************************
void setup() {

  tft.init();
  tft.fillScreen(TFT_BLACK);  //clear screen
  tft.setSwapBytes(true);     //required for displaying images
  tft.setRotation(1);
  tft.setTextColor(TFT_WHITE, TFT_BLACK);

  pinMode(keypadPin_P1, INPUT);
  pinMode(keypadPin_P2, INPUT);

  Serial.begin(115200);

  countDown();

  setupGame();

}
//******************************
void loop() {

  key_p1 = (analogRead(keypadPin_P1) + 10) / 100;
  key_p2 = (analogRead(keypadPin_P2) + 10) / 100;

  if (millis() > (gameTimer + refreshTime)) {
    gameTimer = millis();

    erasePreviousShots(shotCount_p1, shotCount_p2);
    moveShots(shotCount_p1, shotCount_p2);
    bounceCheck();
    drawShots(shotCount_p1, shotCount_p2);

    shotCollisionDetection(shotCount_p1, shotCount_p2);
    if (newHit) {
      updateScore();
      delay(1000);
      newHit = false;
      setupGame();
    }

  /*   if (movecraftcount == 2) {  */
  
      if (moveCrafts) {
      //recieve input & move crafts
      erasePreviousCrafts();
      actionInputs(key_p1, key_p2);
      drawCrafts();

    }

    moveCrafts = ! moveCrafts;
   // (movecraftcount < 2) ? movecraftcount++ : movecraftcount = 0;
  }

}
//******************************
void countDown () {

  for (int i = 5; i > 0; i--) {
    String countdownString = String(i);
    tft.drawString(countdownString, 140, 90, 7);
    delay(1000);
  }

  tft.fillRect(100, 70, 100, 100, TFT_BLACK);
}
//**********************************************
void setupGame () {

  tft.fillScreen(TFT_BLACK);

  //draw inner box
  tft.drawRect(120, 90, 82, 62, TFT_WHITE);     //main outline
  tft.drawLine(160, 90, 160, 150, TFT_WHITE);   //central divider
  tft.drawLine(120, 140, 200, 140, TFT_WHITE);  //shot divider

  //test scores
  tft.drawString(String(score_p1), 125, 92, 7);
  tft.drawString(String(score_p2), 165, 92, 7);

  //initialise p1 & p2 shot locations

  for (int i = 0; i < 8; i++) {
    shotX_p1[i] = (i * 5) + 123;
    shotX_p1[i + 8] = (i * 5) + 123;
    shotY_p1[i] = 143;
    shotY_p1[i + 8] = 148;

    shotX_p2[i] = (i * 5) + 163;
    shotX_p2[i + 8] = (i * 5) + 163;
    shotY_p2[i] = 143;
    shotY_p2[i + 8] = 148;

  }

  //draw shots
  for (int i = 0; i < 16; i++) {
    tft.fillRect(shotX_p1[i] - 1, shotY_p1[i] - 1, 3, 3, TFT_BLUE);
    tft.fillRect(shotX_p2[i] - 1, shotY_p2[i] - 1, 3, 3, TFT_RED);
  }

  x_p1 = 60;
  x_p2 = 260;
  y_p1 = 120;
  y_p2 = 120;

  shotCount_p1 = 0;
  shotCount_p2 = 0;
  rot_p1 = 0;
  rot_p2 = 4;

}
//**********************************************
void actionInputs(int p1_input, int p2_input) {

  //P1 keyboard decision tree
  switch (p1_input) {
    case 0:   //left
      (rot_p1 > 0) ? rot_p1-- : rot_p1 = 7 ;
      break;

    case 4:   //up
      moveForward(rot_p1, 1);
      //accelerate(rot_p1);     //<<<<<Write function
      break;

    case 10:  //down
      //deaccelerate(rot_p1);   //<<<write function
      break;

    case 18:  //right
      (rot_p1 < 7) ? rot_p1++ : rot_p1 = 0;
      break;

    case 29:  //action
      if (millis() > (shotTime_p1 + 500)) {
        shotTime_p1 = millis();
        if (shotCount_p1 < ammo) {
          plantShot(x_p1, y_p1, rot_p1, shotCount_p1, 1);
          shotCount_p1++;
        }
      }
      break;

    default:
      break;
  }

  //P2 keyboard decision tree
  switch (p2_input) {
    case 0:   //left
      (rot_p2 > 0) ? rot_p2-- : rot_p2 = 7 ;
      break;

    case 4:   //up
      moveForward(rot_p2, 2);
      //accelerate(rot_p2);     //<<<<<Write function
      break;

    case 10:  //down
      //deaccelerate(rot_p2);   //<<<write function
      break;

    case 18:  //right
      (rot_p2 < 7) ? rot_p2++ : rot_p2 = 0;
      break;

    case 29:  //action
      if (millis() > (shotTime_p2 + 500)) {
        shotTime_p2 = millis();
        if (shotCount_p2 < ammo) {
          plantShot(x_p2, y_p2, rot_p2, shotCount_p2, 2);
          shotCount_p2++;
        }
      }
      break;

    default:
      break;
  }

}


//**********************************************
void moveShots(int shotRef_p1, int shotRef_p2) {

  //move shots for player 1
  for (int ms = 0; ms < shotRef_p1; ms++) {

    switch (shotRot_p1[ms]) {
      case 0:
        (shotY_p1[ms] > 3) ? shotY_p1[ms]-- : shotY_p1[ms] = 240;  //confirm what to do if out of bounds
        break;

      case 1:
        (shotY_p1[ms] > 1) ? shotY_p1[ms]-- : shotY_p1[ms] = 240;
        (shotX_p1[ms] < 318) ? shotX_p1[ms]++ : shotX_p1[ms] = 1;
        break;

      case 2:
        (shotX_p1[ms] < 318) ? shotX_p1[ms]++ : shotX_p1[ms] = 1;
        break;

      case 3:
        (shotY_p1[ms] < 238) ? shotY_p1[ms]++ : shotY_p1[ms] = 1;
        (shotX_p1[ms] < 318) ? shotX_p1[ms]++ : shotX_p1[ms] = 1;
        break;

      case 4:
        (shotY_p1[ms] < 238) ? shotY_p1[ms]++ : shotY_p1[ms] = 1;
        break;

      case 5:
        (shotY_p1[ms] < 238) ? shotY_p1[ms]++ : shotY_p1[ms] = 1;
        (shotX_p1[ms] > 1) ? shotX_p1[ms]-- : shotX_p1[ms] = 320;
        break;

      case 6:
        (shotX_p1[ms] > 1) ? shotX_p1[ms]-- : shotX_p1[ms] = 320;
        break;

      case 7:
        (shotY_p1[ms] > 1) ? shotY_p1[ms]-- : shotY_p1[ms] = 240;
        (shotX_p1[ms] > 1) ? shotX_p1[ms]-- : shotX_p1[ms] = 320;
        break;

      default:
        break;
    }
  }

  //move shots for player 2
  for (int ms = 0; ms < shotRef_p2; ms++) {

    switch (shotRot_p2[ms]) {
      case 0:
        (shotY_p2[ms] > 1) ? shotY_p2[ms]-- : shotY_p2[ms] = 240;  //confirm what to do if out of bounds
        break;

      case 1:
        (shotY_p2[ms] > 1) ? shotY_p2[ms]-- : shotY_p2[ms] = 240;
        (shotX_p2[ms] < 318) ? shotX_p2[ms]++ : shotX_p2[ms] = 1;
        break;

      case 2:
        (shotX_p2[ms] < 318) ? shotX_p2[ms]++ : shotX_p2[ms] = 1;
        break;

      case 3:
        (shotY_p2[ms] < 238) ? shotY_p2[ms]++ : shotY_p2[ms] = 1;
        (shotX_p2[ms] < 318) ? shotX_p2[ms]++ : shotX_p2[ms] = 1;
        break;

      case 4:
        (shotY_p2[ms] < 238) ? shotY_p2[ms]++ : shotY_p2[ms] = 1;
        break;

      case 5:
        (shotY_p2[ms] < 238) ? shotY_p2[ms]++ : shotY_p2[ms] = 1;
        (shotX_p2[ms] > 1) ? shotX_p2[ms]-- : shotX_p2[ms] = 320;
        break;

      case 6:
        (shotX_p2[ms] > 1) ? shotX_p2[ms]-- : shotX_p2[ms] = 320;
        break;

      case 7:
        (shotY_p2[ms] > 1) ? shotY_p2[ms]-- : shotY_p2[ms] = 240;
        (shotX_p2[ms] > 1) ? shotX_p2[ms]-- : shotX_p2[ms] = 320;
        break;

      default:
        break;
    }
  }
}
//****************************************************
void erasePreviousShots(int shotRef_p1, int shotRef_p2) {

  tft.fillRect(121, 141, 39, 9, TFT_BLACK);
  tft.fillRect(161, 141, 39, 9, TFT_BLACK);

  for (int es = 0; es < shotRef_p1; es++) {
    tft.fillRect(shotX_p1[es] - 1, shotY_p1[es] - 1, 3, 3, TFT_BLACK);
  }

  for (int es = 0; es < shotRef_p2; es++) {
    tft.fillRect(shotX_p2[es] - 1, shotY_p2[es] - 1, 3, 3, TFT_BLACK);
  }

}
//****************************************************
void drawShots(int shotRef_p1, int shotRef_p2) {

  for (int ds = 0; ds < ammo; ds++) {
    tft.fillRect(shotX_p1[ds] - 1, shotY_p1[ds] - 1, 3, 3, TFT_BLUE);
  }

  for (int ds = 0; ds < ammo; ds++) {
    tft.fillRect(shotX_p2[ds] - 1, shotY_p2[ds] - 1, 3, 3, TFT_RED);
  }

}
//****************************************************
void plantShot(int _x, int _y, int _rot, int _shotCount, int playerNo) {

  if (playerNo == 1) {
    switch (_rot) {
      case 0:
        shotX_p1[_shotCount] = _x;
        shotY_p1[_shotCount] = _y - 6;
        shotRot_p1[_shotCount] = 0;
        break;

      case 1:
        shotX_p1[_shotCount] = _x + 6;
        shotY_p1[_shotCount] = _y - 6;
        shotRot_p1[_shotCount] = 1;
        break;
      case 2:
        shotX_p1[_shotCount] = _x + 6;
        shotY_p1[_shotCount] = _y;
        shotRot_p1[_shotCount] = 2;
        break;

      case 3:
        shotX_p1[_shotCount] = _x + 6;
        shotY_p1[_shotCount] = _y + 6;
        shotRot_p1[_shotCount] = 3;
        break;

      case 4:
        shotX_p1[_shotCount] = _x ;
        shotY_p1[_shotCount] = _y + 6;
        shotRot_p1[_shotCount] = 4;
        break;

      case 5:
        shotX_p1[_shotCount] = _x - 6;
        shotY_p1[_shotCount] = _y + 6;
        shotRot_p1[_shotCount] = 5;
        break;

      case 6:
        shotX_p1[_shotCount] = _x - 6;
        shotY_p1[_shotCount] = _y;
        shotRot_p1[_shotCount] = 6;
        break;

      case 7:
        shotX_p1[_shotCount] = _x - 6;
        shotY_p1[_shotCount] = _y - 6;
        shotRot_p1[_shotCount] = 7;
        break;

      default:
        break;
    }


  } else if (playerNo == 2) {
    switch (_rot) {
      case 0:
        shotX_p2[_shotCount] = _x;
        shotY_p2[_shotCount] = _y - 6;
        shotRot_p2[_shotCount] = 0;
        break;

      case 1:
        shotX_p2[_shotCount] = _x + 6;
        shotY_p2[_shotCount] = _y - 6;
        shotRot_p2[_shotCount] = 1;
        break;
      case 2:
        shotX_p2[_shotCount] = _x + 6;
        shotY_p2[_shotCount] = _y;
        shotRot_p2[_shotCount] = 2;
        break;

      case 3:
        shotX_p2[_shotCount] = _x + 6;
        shotY_p2[_shotCount] = _y + 6;
        shotRot_p2[_shotCount] = 3;
        break;

      case 4:
        shotX_p2[_shotCount] = _x ;
        shotY_p2[_shotCount] = _y + 6;
        shotRot_p2[_shotCount] = 4;
        break;

      case 5:
        shotX_p2[_shotCount] = _x - 6;
        shotY_p2[_shotCount] = _y + 6;
        shotRot_p2[_shotCount] = 5;
        break;

      case 6:
        shotX_p2[_shotCount] = _x - 6;
        shotY_p2[_shotCount] = _y;
        shotRot_p2[_shotCount] = 6;
        break;

      case 7:
        shotX_p2[_shotCount] = _x - 6;
        shotY_p2[_shotCount] = _y - 6;
        shotRot_p2[_shotCount] = 7;
        break;

      default:
        break;
    }

  }
}
//****************************************************
void moveForward(int rotation, int playerNo) {

  if (playerNo == 1 ) {

    switch (rotation) {
      case 0:
        if ((x_p1 > 115) && (x_p1 < 207)) { //underside
          if (y_p1 == 157) {
            break;
          }
        }
        (y_p1 > 9) ? y_p1-- : y_p1 = 9;
        break;

      case 1:
        if ((x_p1 > 115) && (x_p1 < 207)) { //underside
          if (y_p1 == 157) {
            break;
          }
        }
        if ((y_p1 > 85) && (y_p1 < 157)) {  //left hand side
          if (x_p1 == 115) {
            break;
          }
        }
        (y_p1 > 9) ? y_p1-- : y_p1 = 9;
        (x_p1 < 315) ? x_p1++ : x_p1 = 315;
        break;

      case 2:
        if ((y_p1 > 85) && (y_p1 < 157)) {  //left hand side
          if (x_p1 == 115) {
            break;
          }
        }
        (x_p1 < 315) ? x_p1++ : x_p1 = 315;
        break;

      case 3:
        if ((y_p1 > 85) && (y_p1 < 157)) {  //left hand side
          if (x_p1 == 115) {
            break;
          }
        }
        if ((x_p1 > 115) && (x_p1 < 207)) {   //top
          if (y_p1 == 85) {
            break;
          }
        }
        (y_p1 < 231) ? y_p1++ : y_p1 = 231;
        (x_p1 < 315) ? x_p1++ : x_p1 = 315;
        break;

      case 4:
        if ((x_p1 > 115) && (x_p1 < 207)) {   //top
          if (y_p1 == 85) {
            break;
          }
        }
        (y_p1 < 231) ? y_p1++ : y_p1 = 231;
        break;

      case 5:
        if ((x_p1 > 115) && (x_p1 < 207)) {   //top
          if (y_p1 == 85) {
            break;
          }
        }
        if ((y_p1 > 85) && (y_p1 < 157)) {    //right
          if (x_p1 == 207) {
            break;
          }
        }
        (y_p1 < 231) ? y_p1++ : y_p1 = 231;
        (x_p1 > 9) ? x_p1-- : x_p1 = 9;
        break;

      case 6:
        if ((y_p1 > 85) && (y_p1 < 157)) {    //right
          if (x_p1 == 207) {
            break;
          }
        }
        (x_p1 > 9) ? x_p1-- : x_p1 = 9;
        break;

      case 7:
        if ((y_p1 > 85) && (y_p1 < 157)) {    //right
          if (x_p1 == 207) {
            break;
          }
        }
        if ((x_p1 > 115) && (x_p1 < 207)) { //underside
          if (y_p1 == 157) {
            break;
          }
        }
        (y_p1 > 9) ? y_p1-- : y_p1 = 9;
        (x_p1 > 9) ? x_p1-- : x_p1 = 9;
        break;

      default:
        break;
    }

  } else if (playerNo == 2) {
    switch (rotation) {
      case 0:
        if ((x_p2 > 115) && (x_p2 < 207)) { //underside
          if (y_p2 == 157) {
            break;
          }
        }
        (y_p2 > 9) ? y_p2-- : y_p2 = 9;
        break;

      case 1:
        if ((x_p2 > 115) && (x_p2 < 207)) { //underside
          if (y_p2 == 157) {
            break;
          }
        }
        if ((y_p2 > 85) && (y_p2 < 157)) {  //left hand side
          if (x_p2 == 115) {
            break;
          }
        }
        (y_p2 > 9) ? y_p2-- : y_p2 = 9;
        (x_p2 < 315) ? x_p2++ : x_p2 = 315;
        break;

      case 2:
        if ((y_p2 > 85) && (y_p2 < 157)) {  //left hand side
          if (x_p2 == 115) {
            break;
          }
        }
        (x_p2 < 315) ? x_p2++ : x_p2 = 315;
        break;

      case 3:
        if ((y_p2 > 85) && (y_p2 < 157)) {  //left hand side
          if (x_p2 == 115) {
            break;
          }
        }
        if ((x_p2 > 115) && (x_p2 < 207)) {   //top
          if (y_p2 == 85) {
            break;
          }
        }
        (y_p2 < 231) ? y_p2++ : y_p2 = 231;
        (x_p2 < 315) ? x_p2++ : x_p2 = 315;
        break;

      case 4:
        if ((x_p2 > 115) && (x_p2 < 207)) {   //top
          if (y_p2 == 85) {
            break;
          }
        }
        (y_p2 < 231) ? y_p2++ : y_p2 = 231;
        break;

      case 5:
        if ((x_p2 > 115) && (x_p2 < 207)) {   //top
          if (y_p2 == 85) {
            break;
          }
        }
        if ((y_p2 > 85) && (y_p2 < 157)) {    //right
          if (x_p2 == 207) {
            break;
          }
        }
        (y_p2 < 231) ? y_p2++ : y_p2 = 231;
        (x_p2 > 9) ? x_p2-- : x_p2 = 9;
        break;

      case 6:
        if ((y_p2 > 85) && (y_p2 < 157)) {    //right
          if (x_p2 == 207) {
            break;
          }
        }
        (x_p2 > 9) ? x_p2-- : x_p2 = 9;
        break;

      case 7:
        if ((y_p2 > 85) && (y_p2 < 157)) {    //right
          if (x_p2 == 207) {
            break;
          }
        }
        if ((x_p2 > 115) && (x_p2 < 207)) { //underside
          if (y_p2 == 157) {
            break;
          }
        }
        (y_p2 > 9) ? y_p2-- : y_p2 = 9;
        (x_p2 > 9) ? x_p2-- : x_p2 = 9;
        break;

      default:
        break;
    }

  }
}
//****************************************************
void erasePreviousCrafts() {

  tft.fillRect(x_p1 - 4, y_p1 - 4, 9, 9,  TFT_BLACK);
  tft.fillRect(x_p2 - 4, y_p2 - 4, 9, 9,  TFT_BLACK);

}
//****************************************************
void drawCrafts() {

  switch (rot_p1) {
    case 0:
      tft.fillTriangle(x_p1, y_p1 - 4, x_p1 + 3, y_p1 + 4, x_p1 - 3, y_p1 + 4, TFT_BLUE); //up
      break;
    case 1:
      tft.fillTriangle(x_p1 + 4, y_p1 - 4, x_p1, y_p1 + 4, x_p1 - 4, y_p1, TFT_BLUE); //up-right
      break;
    case 2:
      tft.fillTriangle(x_p1 + 4, y_p1, x_p1 - 4, y_p1 + 3, x_p1 - 4, y_p1 - 3, TFT_BLUE); //right
      break;
    case 3:
      tft.fillTriangle(x_p1 + 4, y_p1 + 4, x_p1 - 4, y_p1, x_p1, y_p1 - 4, TFT_BLUE); //down-right
      break;
    case 4:
      tft.fillTriangle(x_p1, y_p1 + 4, x_p1 - 3, y_p1 - 4, x_p1 + 3, y_p1 - 4, TFT_BLUE); //down
      break;
    case 5:
      tft.fillTriangle(x_p1 - 4, y_p1 + 4, x_p1, y_p1 - 4, x_p1 + 4, y_p1, TFT_BLUE); //down-left
      break;
    case 6:
      tft.fillTriangle(x_p1 - 4, y_p1, x_p1 + 4, y_p1 - 3, x_p1 + 4, y_p1 + 3, TFT_BLUE); //left
      break;
    case 7:
      tft.fillTriangle(x_p1 - 4, y_p1 - 4, x_p1 + 4, y_p1, x_p1, y_p1 + 4, TFT_BLUE); //up-left
      break;
    default:
      break;
  }

  switch (rot_p2) {
    case 0:
      tft.fillTriangle(x_p2, y_p2 - 4, x_p2 + 3, y_p2 + 4, x_p2 - 3, y_p2 + 4, TFT_RED); //up
      break;
    case 1:
      tft.fillTriangle(x_p2 + 4, y_p2 - 4, x_p2, y_p2 + 4, x_p2 - 4, y_p2, TFT_RED); //up-right
      break;
    case 2:
      tft.fillTriangle(x_p2 + 4, y_p2, x_p2 - 4, y_p2 + 3, x_p2 - 4, y_p2 - 3, TFT_RED); //right
      break;
    case 3:
      tft.fillTriangle(x_p2 + 4, y_p2 + 4, x_p2 - 4, y_p2, x_p2, y_p2 - 4, TFT_RED); //down-right
      break;
    case 4:
      tft.fillTriangle(x_p2, y_p2 + 4, x_p2 - 3, y_p2 - 4, x_p2 + 3, y_p2 - 4, TFT_RED); //down
      break;
    case 5:
      tft.fillTriangle(x_p2 - 4, y_p2 + 4, x_p2, y_p2 - 4, x_p2 + 4, y_p2, TFT_RED); //down-left
      break;
    case 6:
      tft.fillTriangle(x_p2 - 4, y_p2, x_p2 + 4, y_p2 - 3, x_p2 + 4, y_p2 + 3, TFT_RED); //left
      break;
    case 7:
      tft.fillTriangle(x_p2 - 4, y_p2 - 4, x_p2 + 4, y_p2, x_p2, y_p2 + 4, TFT_RED); //up-left
      break;
    default:
      break;
  }
}
//**********************************************
void bounceCheck() {

  for (int bc = 0; bc < shotCount_p1; bc++) {
    switch (shotRot_p1[bc]) {
      case 0:
        //hit underside
        if ((shotX_p1[bc] > 119) && (shotX_p1[bc] < 203)) {
          if (shotY_p1[bc] == 154) {
            shotRot_p1[bc] = 4;
          }
        }
        break;

      case 1:
        //hit underside
        if ((shotX_p1[bc] > 119) && (shotX_p1[bc] < 203)) {
          if (shotY_p1[bc] == 154) {
            shotRot_p1[bc] = 3;
          }
        }
        //hit left hand side
        if ((shotY_p1[bc] > 87) && (shotY_p1[bc] < 163)) {
          if (shotX_p1[bc] == 118) {
            shotRot_p1[bc] = 7;
          }
        }
        break;

      case 2:
        //hit left hand side
        if ((shotY_p1[bc] > 87) && (shotY_p1[bc] < 163)) {
          if (shotX_p1[bc] == 118) {
            shotRot_p1[bc] = 6;
          }
        }
        break;

      case 3:
        //hit left hand side
        if ((shotY_p1[bc] > 87) && (shotY_p1[bc] < 163)) {
          if (shotX_p1[bc] == 118) {
            shotRot_p1[bc] = 5;
          }
        }
        //hit top
        if ((shotX_p1[bc] > 119) && (shotX_p1[bc] < 203)) {
          if (shotY_p1[bc] == 88) {
            shotRot_p1[bc] = 1;
          }
        }
        break;

      case 4:
        //hit top
        if ((shotX_p1[bc] > 119) && (shotX_p1[bc] < 203)) {
          if (shotY_p1[bc] == 88) {
            shotRot_p1[bc] = 0;
          }
        }
        break;

      case 5:
        //hit top
        if ((shotX_p1[bc] > 119) && (shotX_p1[bc] < 203)) {
          if (shotY_p1[bc] == 88) {
            shotRot_p1[bc] = 7;
          }
        }
        //hit right hand side
        if ((shotY_p1[bc] > 87) && (shotY_p1[bc] < 155)) {
          if (shotX_p1[bc] == 204) {
            shotRot_p1[bc] = 3;
          }
        }
        break;

      case 6:
        //hit right hand side
        if ((shotY_p1[bc] > 87) && (shotY_p1[bc] < 155)) {
          if (shotX_p1[bc] == 204) {
            shotRot_p1[bc] = 2;
          }
        }
        break;

      case 7:
        //hit right hand side
        if ((shotY_p1[bc] > 87) && (shotY_p1[bc] < 155)) {
          if (shotX_p1[bc] == 204) {
            shotRot_p1[bc] = 1;
          }
        }
        //hit underside
        if ((shotX_p1[bc] > 119) && (shotX_p1[bc] < 203)) {
          if (shotY_p1[bc] == 154) {
            shotRot_p1[bc] = 5;
          }
        }
        break;

      default:
        break;
    }
  }

  for (int bc = 0; bc < shotCount_p2; bc++) {
    switch (shotRot_p2[bc]) {
      case 0:
        //hit underside
        if ((shotX_p2[bc] > 119) && (shotX_p2[bc] < 203)) {
          if (shotY_p2[bc] == 154) {
            shotRot_p2[bc] = 4;
          }
        }
        break;

      case 1:
        //hit underside
        if ((shotX_p2[bc] > 119) && (shotX_p2[bc] < 203)) {
          if (shotY_p2[bc] == 154) {
            shotRot_p2[bc] = 3;
          }
        }
        //hit left hand side
        if ((shotY_p2[bc] > 87) && (shotY_p2[bc] < 163)) {
          if (shotX_p2[bc] == 118) {
            shotRot_p2[bc] = 7;
          }
        }
        break;

      case 2:
        //hit left hand side
        if ((shotY_p2[bc] > 87) && (shotY_p2[bc] < 163)) {
          if (shotX_p2[bc] == 118) {
            shotRot_p2[bc] = 6;
          }
        }
        break;

      case 3:
        //hit left hand side
        if ((shotY_p2[bc] > 87) && (shotY_p2[bc] < 163)) {
          if (shotX_p2[bc] == 118) {
            shotRot_p2[bc] = 5;
          }
        }
        //hit top
        if ((shotX_p2[bc] > 119) && (shotX_p2[bc] < 203)) {
          if (shotY_p2[bc] == 88) {
            shotRot_p2[bc] = 1;
          }
        }
        break;

      case 4:
        //hit top
        if ((shotX_p2[bc] > 119) && (shotX_p2[bc] < 203)) {
          if (shotY_p2[bc] == 88) {
            shotRot_p2[bc] = 0;
          }
        }
        break;

      case 5:
        //hit top
        if ((shotX_p2[bc] > 119) && (shotX_p2[bc] < 203)) {
          if (shotY_p2[bc] == 88) {
            shotRot_p2[bc] = 7;
          }
        }
        //hit right hand side
        if ((shotY_p2[bc] > 87) && (shotY_p2[bc] < 155)) {
          if (shotX_p2[bc] == 204) {
            shotRot_p2[bc] = 3;
          }
        }
        break;

      case 6:
        //hit right hand side
        if ((shotY_p2[bc] > 87) && (shotY_p2[bc] < 155)) {
          if (shotX_p2[bc] == 204) {
            shotRot_p2[bc] = 2;
          }
        }
        break;

      case 7:
        //hit right hand side
        if ((shotY_p2[bc] > 87) && (shotY_p2[bc] < 155)) {
          if (shotX_p2[bc] == 204) {
            shotRot_p2[bc] = 1;
          }
        }
        //hit underside
        if ((shotX_p2[bc] > 119) && (shotX_p2[bc] < 203)) {
          if (shotY_p2[bc] == 154) {
            shotRot_p2[bc] = 5;
          }
        }
        break;

      default:
        break;
    }
  }

}
//**********************************************
void shotCollisionDetection(int shotRef_p1, int shotRef_p2) {

  for (int i = 0; i < shotRef_p1; i++) {

    if ((shotX_p1[i] > (x_p2 - 6)) && (shotX_p1[i] < (x_p2 + 6))) {
      if ((shotY_p1[i] > (y_p2 - 6)) && (shotY_p1[i] < (y_p2 + 6))) {
        score_p1++;
        newHit = true;
      }
    }
    if ((shotX_p1[i] > (x_p1 - 6)) && (shotX_p1[i] < (x_p1 + 6))) {
      if ((shotY_p1[i] > (y_p1 - 6)) && (shotY_p1[i] < (y_p1 + 6))) {
        score_p2++;
        newHit = true;
      }
    }
  }


  for (int i = 0; i < shotRef_p2; i++) {

    if ((shotX_p2[i] > (x_p1 - 6)) && (shotX_p2[i] < (x_p1 + 6))) {
      if ((shotY_p2[i] > (y_p1 - 6)) && (shotY_p2[i] < (y_p1 + 6))) {
        newHit = true;
        score_p2++;
      }
    }
    if ((shotX_p2[i] > (x_p2 - 6)) && (shotX_p2[i] < (x_p2 + 6))) {
      if ((shotY_p2[i] > (y_p2 - 6)) && (shotY_p2[i] < (y_p2 + 6))) {
        newHit = true;
        score_p1++;
      }
    }
  }

  if (score_p1 == 10) {
    tft.fillScreen(TFT_BLACK);
    tft.setTextColor(TFT_BLUE);
    tft.drawString(String("GAME OVER"), 80, 100, 4);
    tft.drawString(String("BLUE WINS"), 80, 120, 4);
    while (1);
  }

  if (score_p2 == 10) {
    tft.fillScreen(TFT_BLACK);
    tft.setTextColor(TFT_RED);
    tft.drawString(String("GAME OVER"), 80, 100, 4);
    tft.drawString(String("RED WINS"), 95, 120, 4);
    while (1);
  }

}
//**********************************************
void updateScore() {
  tft.fillRect(121, 91, 39, 49, TFT_BLACK);
  tft.fillRect(161, 91, 39, 49, TFT_BLACK);
  tft.drawString(String(score_p1), 125, 92, 7);
  tft.drawString(String(score_p2), 165, 92, 7);
  
}
//*********************************************

Future Plans

Fair fucks if you’ve scrolled this far.

Some progress has been made for a V2, but don’t hold your breath.


Last updated: 15/07/2023