[전시회] 테트리스 게임기

작성자
문종찬 윤지민
작성일
2022-05-20 23:24
조회
309
작은 사이즈의 테트리스 게임기

재료: 아두이노 메가, 입력버튼, 스피커, 3.5인치 tft-lcd

<작품 설명>

tft-lcd와 아두이노를 이용해서 테트리스 게임기를 제작했다. 입력버튼에 따라 블럭은 좌, 우, 아래로 움직이거나 회전하고 나머지 동작은 테트리스와 같다.

게임의 타이틀 화면에서 아무 버튼을 입력하면 게임을 시작하고 게임오버후 스코어 보드를 출력하며 조건에 맞다면 스코어 저장이 가능하다.

사용한 tft-lcd는 아두이노와 8비트 병렬로 데이터를 받으며 mcufriend에서 제공하는 라이브러리를 이용해 lcd를 제어 한다.

아두이노 메가의 타이머 인터럽트와 pwm을 이용해서 음악 파형을 생성하는 방식으로 게임의 BGM을 재생한다.

하이 스코어 정보는 아두이노 메가에 내장되어있는 eeprom에 저장되어있기에 전원을 껐다가 켜도 하이스코어 정보가 유지 된다.



타이틀 화면



게임 화면



게임오버 & 스코어보드



소스코드
#include     // Core graphics library
#include 
#include 
#include 
#include "pitches.h"
#include "music.h"
#define SPEAKER_PIN 12 // OC1B
#define TIMER_BOTTOM 65535-255
#define SAMPLE_SIZE 64
#define SAMPLE_MUL 6
#define TIMER4_FREQ 8000
#define T4_FREQ_MUL 13
#define VOLUME_MAX 64
#define VOLUME_MUL 6
const uint8_t sample1[] = {64,64,64,64,64,64,64,64,
                           64,64,64,64,64,64,64,64,
                           64,64,64,64,64,64,64,64,
                           64,64,64,64,64,64,64,64,
                            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};
const uint8_t sample2[] = {64,64,64,64,64,64,64,64,
                           64,64,64,64,64,64,64,64,
                            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, 0, 0, 0, 0, 0, 0};
const uint8_t sample3[] = {64,64,64,64,64,64,64,64,
                            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, 0, 0, 0, 0, 0, 0,
                            0, 0, 0, 0, 0, 0, 0, 0};
const uint16_t freq[] = {NOTE_E5,  NOTE_F5,  NOTE_FS5, NOTE_G5,
                         NOTE_GS5, NOTE_A5,  NOTE_AS5, NOTE_B5,
                         NOTE_C6,  NOTE_CS6, NOTE_D6,  NOTE_DS6};
uint16_t curs0r = 0;
uint16_t note = 0;
uint16_t pwm_duty = 0;

#define GRAY  0x8410

#define ROTATE_PIN 39
#define DOWN_PIN 37
#define LEFT_PIN 41
#define RIGHT_PIN 35

MCUFRIEND_kbv tft;


uint8_t level, downSet, rotary, nextPiece, Piece, lop, lop2, lop3, lop4, row, column, color;
uint16_t colRow[12][22];
uint16_t Score;
uint16_t HighScore[10] = {5555,10,9,8,7,};
char HighName[][4] = {"AAA","AAA","AAA","AAA","AAA","AAA","AAA","AAA","AAA","AAA"};

bool check, next, win = false;
bool start = false;
unsigned long previousMillis = 0;
unsigned long interval = 500;
const uint16_t colorBlock[8] = {TFT_BLACK, TFT_YELLOW, TFT_GREEN, TFT_PINK, TFT_NAVY, TFT_PURPLE, TFT_BLUE, TFT_ORANGE};
//const uint16_t colorBlock[8] = {TFT_GREEN, TFT_GREEN, TFT_GREEN, TFT_GREEN, TFT_GREEN, TFT_GREEN, TFT_GREEN, TFT_GREEN};
enum Button {NONE ,ROTATE, DOWN, LEFT, RIGHT};
enum Button button = NONE;

const bool piece[20][16] = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  { 0, 1, 0, 0,  //1
    0, 1, 0, 0,
    0, 1, 0, 0,
    0, 1, 0, 0
  },

  { 0, 0, 0, 0,  //2
    0, 0, 0, 0,
    1, 1, 0, 0,
    1, 1, 0, 0
  },

  { 0, 0, 0, 0,  //3
    1, 0, 0, 0,
    1, 0, 0, 0,
    1, 1, 0, 0
  },

  { 0, 0, 0, 0,  //4
    0, 1, 0, 0,
    0, 1, 0, 0,
    1, 1, 0, 0
  },

  { 0, 0, 0, 0,  //5
    0, 0, 0, 0,
    0, 1, 0, 0,
    1, 1, 1, 0
  },

  { 0, 0, 0, 0,  //6
    0, 0, 0, 0,
    0, 1, 1, 0,
    1, 1, 0, 0
  },

  { 0, 0, 0, 0,  //7
    0, 0, 0, 0,
    1, 1, 0, 0,
    0, 1, 1, 0
  },

  { 0, 0, 0, 0,  //8
    0, 0, 0, 0,
    0, 0, 0, 0,
    1, 1, 1, 1
  },

  { 0, 0, 0, 0,  //9
    0, 0, 0, 0,
    0, 0, 1, 0,
    1, 1, 1, 0
  },

  { 0, 0, 0, 0,  //10
    1, 1, 0, 0,
    0, 1, 0, 0,
    0, 1, 0, 0
  },

  { 0, 0, 0, 0,  //11
    0, 0, 0, 0,
    1, 1, 1, 0,
    1, 0, 0, 0
  },

  { 0, 0, 0, 0,  //12
    0, 0, 0, 0,
    1, 1, 1, 0,
    0, 0, 1, 0
  },

  { 0, 0, 0, 0,  //13
    1, 1, 0, 0,
    1, 0, 0, 0,
    1, 0, 0, 0
  },

  { 0, 0, 0, 0,  //14
    0, 0, 0, 0,
    1, 0, 0, 0,
    1, 1, 1, 0
  },

  { 0, 0, 0, 0,  //15
    0, 1, 0, 0,
    1, 1, 0, 0,
    0, 1, 0, 0
  },

  { 0, 0, 0, 0,  //16
    0, 0, 0, 0,
    1, 1, 1, 0,
    0, 1, 0, 0
  },

  { 0, 0, 0, 0,  //17
    1, 0, 0, 0,
    1, 1, 0, 0,
    1, 0, 0, 0
  },

  { 0, 0, 0, 0,  //18
    1, 0, 0, 0,
    1, 1, 0, 0,
    0, 1, 0, 0
  },

  { 0, 0, 0, 0,  //19
    0, 1, 0, 0,
    1, 1, 0, 0,
    1, 0, 0, 0
  }
};

void setup() {
  noInterrupts();
  
  pinMode(ROTATE_PIN, INPUT_PULLUP);
  pinMode(DOWN_PIN, INPUT_PULLUP);
  pinMode(LEFT_PIN, INPUT_PULLUP);
  pinMode(RIGHT_PIN, INPUT_PULLUP);
  pinMode(SPEAKER_PIN, OUTPUT);
  
  // Timer 4, 8Khz
  TCCR4A = 0;
  TCCR4B = 0;
  TCNT4 = TIMER_BOTTOM;  // count from 0 to 235
  TCCR4B |= (1 << CS41); // 010 16Mhz/8
  TIMSK4 |= (1 << TOIE4); // ovf enabled

  // Timer 1, 64khz
  TCCR1A = 0;
  TCCR1B = 0;
  // fast pwm mode, TOP = OCR1A
  TCCR1A |= (1 << WGM11) | (1 << WGM10);
  TCCR1B |= (1 << WGM12) | (1 << WGM13);
  TCCR1A |= (1 << COM1B1); // non-inverting mode B
  TCCR1B |= (1 << CS10); // 16Mhz
  OCR1A = 255; // count from 0 to 255
  
  interrupts(); 
  sei();
  tft.reset();
  tft.begin(tft.readID());
  tft.setRotation(0);
  randomSeed(A4); //없으면?
}

ISR(TIMER4_OVF_vect){
  TCCR4B &= ~(1 << CS41);
  TCNT4 = TIMER_BOTTOM;
  if(curs0r < (note_length-1)){ uint8_t play1 = (freq[note1[note]]*curs0r)>>(octave1[note]+T4_FREQ_MUL-SAMPLE_MUL-1)&(SAMPLE_SIZE-1);
    uint8_t play2 = (freq[note2[note]]*curs0r)>>(octave2[note]+T4_FREQ_MUL-SAMPLE_MUL-1)&(SAMPLE_SIZE-1);
    uint8_t play3 = (freq[note3[note]]*curs0r)>>(octave3[note]+T4_FREQ_MUL-SAMPLE_MUL-1)&(SAMPLE_SIZE-1);
    pwm_duty = (
       (sample3[play1]*volume1[note]>>VOLUME_MUL)
      +(sample1[play2]*volume2[note]>>VOLUME_MUL)
      +(sample2[play3]*volume3[note]>>VOLUME_MUL)
      ); // 만약 이거도 계산이 느리다고 하면
         // note랑 octave도 하나로 합치기
         // 계산하는거 귀찮아서 못합치겠음
         // 일일이 128개 다 수정 못해
    OCR1B = pwm_duty;
    curs0r++;
  }
  else{
    curs0r = 0;
    if(note < (song_length-1)){
      note++;
    }
    else{
      note = 0;
    }
  }
  TCCR4B |= (1 << CS41);
  // 이 모든게 125마이크로초 안에 끝나야됨
  // 테트리스코드 실행할 시간도 있어야됨
  // 택도 없음을 확인함. 코드 실행 중에 타이머를 꺼봤는데
  // 속도가 확 주는거 봐서 이거 타이머 엄청 씹힌다
  // 1khz로 바꿔볼까
  // ㄴㄴ 8khz가 마지노선임 4랑 2일때 음악 다 박살난다
  // 참고로 이거 실행할때 타이머 꺼버리는 이유는
  // 조금이나마 코드 실행할 여지를 주기 위해서임
}

void loop() {
  title();
  for (lop = 1; lop < 11; lop++) {
    for (lop2 = 1; lop2 < 21; lop2++) {
      colRow[lop][lop2] = 0;
    }
  }
  for (lop = 0; lop < 22; lop++) { colRow[0][lop] = 21; colRow[11][lop] = 21; } gameStart(); newBlock(); previousMillis = millis(); do { if (millis() - previousMillis > interval) {
      previousMillis = millis();
      row += 1;
      check = true;
      checkDown();
      if (check == false) newBlock();
      else {
        delPiece(column,row,Piece);
        setPiece(column,row,Piece);
      }
    }
    //readTouch(); // 터치스크린 관련
    readButton();
    if (button != NONE) { 
      if ((button == ROTATE) && (rotary==0)) { //블럭 회전
        switch(Piece){
        case 1:
          rotaryBlock(1, 8);
          break;
        case 8:
          rotaryBlock(8, 1);
         break;
        case 3:
          rotaryBlock(3, 9);
         break;
        case 9:
          rotaryBlock(9, 10);
        break;
        case 10:
        rotaryBlock(10, 11);
        break;
        case 11:
          rotaryBlock(11, 3);
        break;
        case 4:
          rotaryBlock(4, 12);
        break;
        case 12:
          rotaryBlock(12, 13);
        break;
        case 13:
        rotaryBlock(13, 14);
        break;
        case 14:
          rotaryBlock(14, 4);
        break;
        case 5:
          rotaryBlock(5, 15);
        break;
        case 15:
          rotaryBlock(15, 16);
        break;
        case 16:
          rotaryBlock(16, 17);
        break;
        case 17:
          rotaryBlock(17, 5);
        break;
        case 6:
          rotaryBlock(6, 18);
        break;
        case 18:
        rotaryBlock(18, 6);
        break;
        case 7:
          rotaryBlock(7, 19);
        break;
        case 19:
          rotaryBlock(19, 7);
        break;
        }
        rotary = 0;
        delay(50);
        }
      if (button == DOWN) {
        row += 1;
        check = true;
        checkDown();
        if (check == false) newBlock();
        else {
          delPiece(column,row,Piece);
          setPiece(column,row,Piece);
          }
      }
      if (button == RIGHT) {
        column += 1;
        check = true;
        checkDown();
        if (check == false) column -= 1;
        else {
          column -= 1;
          row += 1;
          delPiece(column,row,Piece);
          column += 1;
          row -= 1;
          setPiece(column,row,Piece);
        }
      }
      if (button == LEFT) {
        column -= 1;
        check = true;
        checkDown();
        if (check == false) column += 1;
        else {
          column += 1;
          row += 1;
          delPiece(column,row,Piece);
          column -= 1;
          row -= 1;
          setPiece(column,row,Piece);
        }
      }
      delay(100);
    }
  } while (!win);
delay(1000);
start=true;
win=false;
}

void title()
{
  tft.fillScreen(TFT_BLACK);
  tft.setTextSize(4);
  tft.setCursor(30, 200);
  tft.setTextColor(TFT_GREEN);
  tft.print("T E T R I S\n\n");
  tft.setTextSize(2);
  tft.print("     press any button \n          to start");
  while(1)
  {
    readButton();
    if(button != NONE)
    {
      break;
    }
  }
  tft.fillScreen(TFT_BLACK);
  start = false;
}

void gameover()
{
  tft.fillScreen(TFT_BLACK);
  tft.setTextSize(4);
  tft.setCursor(30, 200);
  tft.setTextColor(TFT_GREEN);
  tft.print(" GAME OVER!");
  delay(3000);
}

void ScoreBoard()
{
  for(int i=0; i<10; i++)
  {
    HighScore[i] = eeprom_read_word(eeprom_read_word(2*i)+3);
    eeprom_read_block((void *)HighName[i],(void *)eeprom_read_word(2*i), 3);
  }
  tft.setCursor(32, 15);
  tft.setTextColor(TFT_GREEN);
  tft.setTextSize(2);
  tft.print("SCORE BOARD\n"); 
  tft.setTextSize(2);
  for(int i = 0; i < 10; i++) { tft.print(String(HighScore[i])); tft.print(HighName[i]); tft.print("\n"); } delay(1000); if (1) { WriteName(); } } void checkDown() { if (row > 20){ 
    check = false;}
  if (check == true){
    if(row>0){ 
    if((colRow[column + 3][row] > 20 && piece[Piece][15]) ||
       (colRow[column + 2][row] > 20 && piece[Piece][14]) ||
       (colRow[column + 1][row] > 20 && piece[Piece][13]) ||
       (colRow[column + 0][row] > 20 && piece[Piece][12]))check = false;
    }
    if(row>1){
     if((colRow[column + 3][row - 1] > 20 && piece[Piece][11]) ||
       (colRow[column + 2][row - 1] > 20 && piece[Piece][10]) ||
       (colRow[column + 1][row - 1] > 20 && piece[Piece][9]) ||
       (colRow[column + 0][row - 1] > 20 && piece[Piece][8]))check = false;
    }
    if(row>2){
     if((colRow[column + 3][row - 2] > 20 && piece[Piece][7]) ||
       (colRow[column + 2][row - 2] > 20 && piece[Piece][6]) ||
       (colRow[column + 1][row - 2] > 20 && piece[Piece][5]) ||
       (colRow[column + 0][row - 2] > 20 && piece[Piece][4]))check = false;
    }
     if(row>3){
     if((colRow[column + 3][row - 3] > 20 && piece[Piece][3]) ||
       (colRow[column + 2][row - 3] > 20 && piece[Piece][2]) ||
       (colRow[column + 1][row - 3] > 20 && piece[Piece][1]) ||
       (colRow[column + 0][row - 3] > 20 && piece[Piece][0]))check = false;
}
}
if(check==false && row==1){
  start=true;
  gameover();
  ScoreBoard();
  loop(); //restart
}
}
void rotaryBlock(uint8_t oldPice, uint8_t newPice) {
  Piece = newPice;
  check = true;
  checkDown();
  if (check == false) Piece = oldPice;
  else {
    Piece = oldPice;
    row += 1;
    delPiece(column,row,Piece);
    row -= 1;
    Piece = newPice;
    setPiece(column,row,Piece);
  } rotary = 1;
}
void setPiece(uint8_t xx,uint8_t yy, uint8_t zz){
  color=zz;
  if(color==8) color=1;
  if(color>8 && color<12) color=3; if(color>11 && color <15) color=4; if(color>14 && color <18) color=5; if(color==18) color=6; if(color==19) color=7; if(yy>0){
      if(piece[zz][15]) setBlock(xx + 3, yy,color+downSet);
      if(piece[zz][14]) setBlock(xx + 2,yy,color+downSet);
      if(piece[zz][13]) setBlock(xx + 1, yy,color+downSet);
      if(piece[zz][12]) setBlock(xx + 0,yy,color+downSet);
      }
      if(yy>1){
      //if(piece[zz][11]) setBlock(xx + 3, yy-1,color+downSet);
      if(piece[zz][10]) setBlock(xx + 2,yy-1,color+downSet);
      if(piece[zz][9]) setBlock(xx + 1, yy-1,color+downSet);
      if(piece[zz][8]) setBlock(xx + 0,yy-1,color+downSet);
      }
      if(yy>2){
      //if(piece[zz][7]) setBlock(xx + 3, yy-2,color+downSet);
      if(piece[zz][6]) setBlock(xx + 2,yy-2,color+downSet);
      if(piece[zz][5]) setBlock(xx + 1, yy-2,color+downSet);
      if(piece[zz][4]) setBlock(xx + 0,yy-2,color+downSet);
      }
      if(yy>3){
      //if(piece[zz][3]) setBlock(xx + 3, yy-3,color+downSet);
      if(piece[zz][2]) setBlock(xx + 2,yy-3,color+downSet);
      if(piece[zz][1]) setBlock(xx + 1, yy-3,color+downSet);
      if(piece[zz][0]) setBlock(xx + 0,yy-3,color+downSet);
      }
}
void delPiece(uint8_t xxx,uint8_t yyy, uint8_t zzz){
  if(yyy>1){
      if(piece[zzz][15]) delBlock(xxx + 3, yyy-1);
      if(piece[zzz][14]) delBlock(xxx + 2,yyy-1);
      if(piece[zzz][13]) delBlock(xxx + 1, yyy-1);
      if(piece[zzz][12]) delBlock(xxx + 0,yyy-1);
      }
      if(yyy>2){
      //if(piece[zzz][11]) delBlock(xxx + 3, yyy-2);
      if(piece[zzz][10]) delBlock(xxx + 2,yyy-2);
      if(piece[zzz][9]) delBlock(xxx + 1, yyy-2);
      if(piece[zzz][8]) delBlock(xxx + 0,yyy-2);
      }
      if(yyy>3){
      //if(piece[zzz][7]) delBlock(xxx + 3, yyy-3);
      if(piece[zzz][6]) delBlock(xxx + 2,yyy-3);
      if(piece[zzz][5]) delBlock(xxx + 1, yyy-3);
      if(piece[zzz][4]) delBlock(xxx + 0,yyy-3);
      }
      if(yyy>4){
      //if(piece[zzz][3]) delBlock(xxx + 3, yyy-4);
      if(piece[zzz][2]) delBlock(xxx + 2,yyy-4);
      if(piece[zzz][1]) delBlock(xxx + 1, yyy-4);
      if(piece[zzz][0]) delBlock(xxx + 0,yyy-4);
      }
}
void delBlock(uint8_t x, uint8_t y) {
  tft.fillRect(x * 20, y * 20 + 40, 18, 18, colorBlock[0]);
  if(!start) colRow[x][y] = 0;
}
void setBlock(uint8_t x, uint8_t y, uint8_t z) {
  {
    tft.fillRect(x * 20 + 1 , y * 20 + 41, 16, 16, colorBlock[z-downSet]);
    tft.drawRect(x * 20 , (y + 2) * 20 , 18, 18,  TFT_BLACK);
  }
  if(!start) colRow[x][y] = z;
}
void newBlock() {
  Score+=4;
  downSet=20;
  row-=1;
  setPiece(column,row,Piece);
  for (lop4 = 0; lop4 < 4; lop4++) { lop = 21; do { lop -= 1; if (colRow[1][lop] > 20 && colRow[2][lop] > 20 && colRow[3][lop] > 20 && colRow[4][lop] > 20 && colRow[5][lop] > 20
          && colRow[6][lop] > 20 && colRow[7][lop] > 20 && colRow[8][lop] > 20 && colRow[9][lop] > 20 && colRow[10][lop] > 20) {
            Score+=10;
        for (lop2 = 1; lop2 < 11; lop2++) { delBlock(lop2, lop); lop3 = lop; do { lop3 -= 1; if (colRow[lop2][lop3] > 0) {
              setBlock(lop2, lop3 + 1, colRow[lop2][lop3]);
            } else {
              delBlock(lop2, lop3 + 1);
            }
          } while (lop3 > 0);
         }
        lop = 0;
      }
    } while (lop > 0);
  }
  downSet=0;
  tft.fillRect(240,90,60,14,TFT_BLACK); //score
  tft.setTextSize(2);
  tft.setCursor(240, 90);
  tft.setTextColor(TFT_GREEN);
  if(Score<10) {level=1;tft.print("0000"+String(Score));}
  if(Score<100 && Score >9) {level=2;interval=400;tft.print("000"+String(Score));}
  if(Score<1000 && Score >99) {level=3;interval=300;tft.print("00"+String(Score));}
  if(Score<10000 && Score >999) {level=4; interval=200;tft.print("0"+String(Score));}
  if(Score<100000 && Score >9999) {level=5;interval=100;tft.print(Score);}
  tft.fillRect(265,140,14,14,TFT_BLACK); //level
  tft.setCursor(265, 140);
  tft.print(level);
  Piece=nextPiece;
  tft.fillRect(240,200,80,80,TFT_BLACK); //Next_block
  tft.drawRect(219,178,100,115,TFT_GREEN);//Next_block
  tft.drawRect(219,58,100,120,TFT_GREEN); //score
  nextPiece=random(1,20);
  start=true;
  setPiece(12,11,nextPiece);
  start=false;
  column = 6;
  row = 0;
  }
void gameStart() {
  nextPiece=random(1,20);
  Score=-4;
  if(!start){
  tft.fillScreen(TFT_BLACK); //전체화면
  tft.setTextSize(4);
  tft.setCursor(32, 15);
  tft.setTextColor(TFT_GREEN);
  tft.print("T E T R I S");
  tft.setCursor(30, 12);
  //tft.setTextColor(TFT_BLACK);
  //tft.print("T E T R I S");
  tft.fillRect(20, 60, 200, 400, TFT_BLACK); //block내부
  tft.drawRect(18 , 58 , 202, 402,  TFT_GREEN); 
  tft.setTextSize(2);
  tft.setCursor(240, 70);
  tft.setTextColor(TFT_GREEN);
  tft.print("Score");
  tft.setCursor(240, 90);
  tft.print("00000");
  tft.setCursor(240, 120);
  tft.print("Level");
  
  }
rollo();
}

void readButton()
{
  if(digitalRead(ROTATE_PIN) == LOW)
  {
    button =ROTATE;
  }
  else if(digitalRead(DOWN_PIN) == LOW)
  {
    button = DOWN;
  }
  else if(digitalRead(LEFT_PIN) == LOW)
  {
    button = LEFT;
  }
  else if(digitalRead(RIGHT_PIN) == LOW)
  {
    button = RIGHT;
  }
  else
  {
    button = NONE;
  }
  
}
uint16_t unused_mem_finder()
{
    while(1)
    {
        uint16_t addr = random(0x03ff);
        for(int i=0;i<10;i++)
        {
            if(addr == (eeprom_read_word(2*i)))
            {
                break;
            }
            else
            {
                return addr;
            }
        }
    }
}
void rollo(){
    start=true;
  for(lop=1;lop<21;lop++){
  for(lop2=1;lop2<11;lop2++){ setBlock(lop2, lop,2); } } delay(250); for(lop=20;lop>0;lop--){
  for(lop2=10;lop2>0;lop2--){
  delBlock(lop2, lop);
  }
    start=false;
    delay(20);
  }
}
void WriteName()
{
    int NameCursor = 0;
    int BlankCursor = 0;
    tft.setTextSize(2);
    tft.fillScreen(TFT_BLACK);
    tft.setCursor(5, 10);
    char MyName[3] = "AAA";
    int N = 0;
    tft.print(MyName[N]);
    while(1)
    {
        readButton();
        if(button == NONE)
        {
          readButton();
          if(button == ROTATE)
        {
            tft.setCursor(5 + (NameCursor*15), 10);
            tft.fillRect(5 + (BlankCursor * 5), 10, 15, 15, TFT_BLACK);
            if(MyName[N] < 'Z') { MyName[N] = MyName[0] + 1; } else { MyName[N] = 'A'; } tft.print(MyName[N]); } else if(button == DOWN) { tft.setCursor(5 + (NameCursor*15), 10); tft.fillRect(5 + (BlankCursor * 5), 10, 15, 15, TFT_BLACK); if(MyName[N] > 'A')
             MyName[N] = MyName[0] - 1;
           else
              MyName[N] = "Z";
            tft.print(MyName[N]);
        }
        else if(button == RIGHT)
        {
            if(N < 2)
            {
                N = N + 1;
                NameCursor += 1;
                BlankCursor += 5;
            }
            else
            {
                N = 0;
                NameCursor = 0;
                BlankCursor = 0;
            }
            tft.setCursor(5 + (NameCursor*15), 10);
            tft.print(MyName[N]);
        }
        else if(button == LEFT)
        {
            break;
        }       
    }
    // 여기부터 sorting있음
    uint16_t *place;
    place = (uint16_t)16; // 9등의 주소
    for(int x=1;x<10;x++) { if(Score > eeprom_read_word(eeprom_read_word(place)+3))
        {
            eeprom_update_word(place+2, eeprom_read_word(place));
            if(place > 0)
            {
                place = (uint16_t)(place - 2);
            }
            else
            {
                break;
            }
        }
        else
        {
            break;
        }
    }
    uint16_t last_known_blank = (uint16_t)20;
    last_known_blank = unused_mem_finder();
    eeprom_update_block(MyName, last_known_blank, 3);
    eeprom_update_word(last_known_blank+3, Score);
    eeprom_update_word(place+2, last_known_blank);
}
}
소스코드는 해당 주소에 있는 코드를 활용한 것이다.
https://create.arduino.cc/projecthub/rom3/tetris-clone-for-arduino-uno-with-touchscreen-and-sound-e99d4a
전체 0