정보나눔

오픈소스하드웨어 프로젝트에 대한 다양한 정보를 나누는 공간입니다.

문제점 및 궁금점 문의드립니다!
장호근 | 2016-12-14
#define GRID_W           (8)
#define GRID_H           (8)
// max size of each tetris piece
#define PIECE_W          (4)
#define PIECE_H          (4)
#define JOYSTICK_DEAD_ZONE  (10)
// a list of anode pins, sorted by top to bottom of the grid
const int anode[8] = { 8, 13, 7, 11, 0, 6, 1, 4 };
// a list of cathode pins, sorted by left to right of the grid
const int cathode[8] = { 12, 2, 3, 9, 5, 10, 14, 15 };
// translate the pins on the LED panel to pins on the Arduino
const int arduino_to_grid[16] = {5, 4, 3, 2, 14, 15, 16, 17, 13, 12, 11, 10, 9, 8, 7, 6};
int led = 1; 
//
// 1 color drawings of each piece in each rotation.
// Each piece is max 4 wide, 4 tall, and 4 rotations.
const char piece_I[] = {
  0, 0, 0, 0,
  0, 0, 0, 0,
  0, 0, 0, 0,
  1, 1, 1, 1,
  0, 1, 0, 0,
  0, 1, 0, 0,
  0, 1, 0, 0,
  0, 1, 0, 0,

  0, 0, 0, 0,
  0, 0, 0, 0,
  0, 0, 0, 0,
  1, 1, 1, 1,
  0, 1, 0, 0,
  0, 1, 0, 0,
  0, 1, 0, 0,
  0, 1, 0, 0,
};
const char piece_L1[] = {
  0, 1, 0, 0,
  0, 1, 0, 0,
  0, 1, 1, 0,
  0, 0, 0, 0,
  0, 0, 0, 0,
  1, 1, 1, 0,
  1, 0, 0, 0,
  0, 0, 0, 0,

  1, 1, 0, 0,
  0, 1, 0, 0,
  0, 1, 0, 0,
  0, 0, 0, 0,
  0, 0, 1, 0,
  1, 1, 1, 0,
  0, 0, 0, 0,
  0, 0, 0, 0,
};
const char piece_L2[] = {
  0, 1, 0, 0,
  0, 1, 0, 0,
  1, 1, 0, 0,
  0, 0, 0, 0,
  0, 0, 0, 0,
  1, 0, 0, 0,
  1, 1, 1, 0,
  0, 0, 0, 0,

  0, 1, 1, 0,
  0, 1, 0, 0,
  0, 1, 0, 0,
  0, 0, 0, 0,
  0, 0, 0, 0,
  1, 1, 1, 0,
  0, 0, 1, 0,
  0, 0, 0, 0,
};
const char piece_T[] = {
  0, 0, 0, 0,
  1, 1, 1, 0,
  0, 1, 0, 0,
  0, 0, 0, 0,
  0, 1, 0, 0,
  1, 1, 0, 0,
  0, 1, 0, 0,
  0, 0, 0, 0,
  0, 0, 0, 0,
  0, 1, 0, 0,
  1, 1, 1, 0,
  0, 0, 0, 0,
  0, 1, 0, 0,
  0, 1, 1, 0,
  0, 1, 0, 0,
  0, 0, 0, 0,
};
const char piece_S1[] = {
  1, 0, 0, 0,
  1, 1, 0, 0,
  0, 1, 0, 0,
  0, 0, 0, 0,
  0, 0, 0, 0,
  0, 1, 1, 0,
  1, 1, 0, 0,
  0, 0, 0, 0,
  1, 0, 0, 0,
  1, 1, 0, 0,
  0, 1, 0, 0,
  0, 0, 0, 0,
  0, 0, 0, 0,
  0, 1, 1, 0,
  1, 1, 0, 0,
  0, 0, 0, 0,
};
const char piece_S2[] = {
  0, 1, 0, 0,
  1, 1, 0, 0,
  1, 0, 0, 0,
  0, 0, 0, 0,
  0, 0, 0, 0,
  1, 1, 0, 0,
  0, 1, 1, 0,
  0, 0, 0, 0,

  0, 1, 0, 0,
  1, 1, 0, 0,
  1, 0, 0, 0,
  0, 0, 0, 0,
  0, 0, 0, 0,
  1, 1, 0, 0,
  0, 1, 1, 0,
  0, 0, 0, 0,
};
const char piece_O[] = {
  1, 1, 0, 0,
  1, 1, 0, 0,
  0, 0, 0, 0,
  0, 0, 0, 0,

  1, 1, 0, 0,
  1, 1, 0, 0,
  0, 0, 0, 0,
  0, 0, 0, 0,

  1, 1, 0, 0,
  1, 1, 0, 0,
  0, 0, 0, 0,
  0, 0, 0, 0,

  1, 1, 0, 0,
  1, 1, 0, 0,
  0, 0, 0, 0,
  0, 0, 0, 0,
};

// how many kinds of pieces
#define NUM_PIECE_TYPES  (7)
// An array of pointers!
const char *pieces[NUM_PIECE_TYPES] = {
  piece_S1,
  piece_S2,
  piece_L1,
  piece_L2,
  piece_O,
  piece_T,
  piece_I,
};
// length of the chances array
#define MAX_CHANCES (13)
// chances[12] is 6,
// pieces[chances[12]] is piece_I,
// pieces[chances[12]][8] is 1.
const char chances[MAX_CHANCES] = {
  0, 0,
  1, 1,
  2, 2,
  3, 3,
  4, 4,
  5, 5,
  6,  // 1 in 13 chance of an I piece
};
//--------------------------------------------------------------------------------
// GLOBALS
//--------------------------------------------------------------------------------
// this is how arduino remembers what the button was doing in the past,
// so arduino can tell when it changes.
int old_button = 0;
// so arduino can tell when user moves sideways
int old_px = 0;
// so arduino can tell when user tries to turn
int old_i_want_to_turn = 0;
// this is how arduino remembers the falling piece.
int piece_id;
int piece_rotation;
int piece_x;
int piece_y;
// this controls how fast the player can move.
long last_move;
long move_delay = 100; // 100ms = 5 times a second
// this controls when the piece automatically falls.
long last_drop;
long drop_delay = 1500; // 500ms = 2 times a second
// this is how arduino remembers where pieces are on the grid.
char grid[8 * 8];
//--------------------------------------------------------------------------------
// METHODS
//--------------------------------------------------------------------------------
// I want to turn on the column N from the left.
// this figures out which pin on the LED that is,
// then figures out which pin on the arduino matches that LED pin.
// two translations!
int out(int x) {
  return arduino_to_grid[anode[x]];
}
// I want to turn on the row N from the top.
// this figures out which pin on the LED that is,
// then figures out which pin on the arduino matches that LED pin.
// two translations!
int in(int y) {
  return arduino_to_grid[cathode[y]];
}
// I want to turn on point P(x,y), which is X from the left and Y from the top.
// I might also want to hold it on for us microseconds.
void p(int x, int y, int us) {
  // don't try to turn on a light that doesn't exist
  //if(x<0 || x>GRID_W) return;
  //if(y<0 || y>GRID_H) return;

  // now light it
  digitalWrite(out(x), HIGH);
  digitalWrite(in(y), LOW);
  delayMicroseconds(us);
  digitalWrite(in(y), HIGH);
  digitalWrite(out(x), LOW);
}
// grid contains the arduino's memory of the game board, including the piece that is falling.
void draw_grid() {
  int x, y;
  for (y = 0; y < GRID_H; ++y) {
    for (x = 0; x < GRID_W; ++x) {
      if ( grid[y * GRID_W + x] != 0 ) {
        p(x, y, 150);
      }
    }
  }
}
void choose_new_piece() {
  // make the chances array longer to change the odds of different pieces appearing.
  piece_id = chances[rand() % MAX_CHANCES];
  // always start the piece top center.
  piece_y = -4; // -4 squares off the top of the screen.
  piece_x = 3;
  // always start in the same orientation.
  piece_rotation = 0;
}
void erase_piece_from_grid() {
  int x, y;

  const char *piece = pieces[piece_id] + (piece_rotation * PIECE_H * PIECE_W);

  for (y = 0; y < PIECE_H; ++y) {
    for (x = 0; x < PIECE_W; ++x) {
      int nx = piece_x + x;
      int ny = piece_y + y;
      if (ny < 0 || ny > GRID_H) continue;
      if (nx < 0 || nx > GRID_W) continue;
      if (piece[y * PIECE_W + x] == 1) {
        grid[ny * GRID_W + nx] = 0; // zero erases the grid location.
      }
    }
  }
}
void add_piece_to_grid() {
  int x, y;

  const char *piece = pieces[piece_id] + (piece_rotation * PIECE_H * PIECE_W);

  for (y = 0; y < PIECE_H; ++y) {
    for (x = 0; x < PIECE_W; ++x) {
      int nx = piece_x + x;
      int ny = piece_y + y;
      if (ny < 0 || ny > GRID_H) continue;
      if (nx < 0 || nx > GRID_W) continue;
      if (piece[y * PIECE_W + x] == 1) {
        grid[ny * GRID_W + nx] = 1; // zero erases the grid location.
      }
    }
  }
}
// Move everything down 1 space, destroying the old row number y in the process.
void delete_row(int y) {
  int x;
  for (; y > 0; --y) {
    for (x = 0; x < GRID_W; ++x) {
      grid[y * GRID_W + x] = grid[(y - 1) * GRID_W + x];
    }
  }
  // everything moved down 1, so the top row must be empty or the game would be over.
  for (x = 0; x < GRID_W; ++x) {
    grid[x] = 0;
  }
}
void remove_full_rows() {
  int x, y, c;
  for (y = 0; y < GRID_H; ++y) {
    // count the full spaces in this row
    c = 0;
    for (x = 0; x < GRID_W; ++x) {
      if ( grid[y * GRID_W + x] > 0 ) c++;
    }
    if (c == GRID_W) {
      // row full!
      delete_row(y);
    }
  }
}
void try_to_move_piece_sideways() {
  // what does the joystick angle say
  int dx = map(analogRead(4), 0, 1023, 500, -500);
  Serial.print(dx);
  int new_px = 0;
  // is the joystick really being pushed?
  if (dx > JOYSTICK_DEAD_ZONE) {
    new_px = 1;
  }
  if (dx < -JOYSTICK_DEAD_ZONE) {
    new_px = -1;
  }
  if (new_px != old_px && piece_can_fit(piece_x + new_px, piece_y, piece_rotation) == 1) {
    piece_x += new_px;
  }
  old_px = new_px;
}
void try_to_rotate_piece() {
  int i_want_to_turn = 0;

  // what does the joystick button say
  int new_button = digitalRead(1);
  // if the button state has just changed AND it is being let go,
  if ( new_button > 0 && old_button != new_button ) {
    i_want_to_turn = 1;
  }
  old_button = new_button;

  // up on joystick to rotate
  int dy = map(analogRead(5), 0, 1023, -500, 500);
  if (dy < -JOYSTICK_DEAD_ZONE) i_want_to_turn = 1;

  if (i_want_to_turn == 1 && i_want_to_turn != old_i_want_to_turn) {
    // figure out what it will look like at that new angle
    int new_pr = ( piece_rotation + 1 ) % 4;
    // if it can fit at that new angle (doesn't bump anything)
    if (piece_can_fit(piece_x, piece_y, new_pr)) {
      // then make the turn.
      piece_rotation = new_pr;
    }
  }
  old_i_want_to_turn = i_want_to_turn;
}
// can the piece fit in this new location?
int piece_can_fit(int px, int py, int pr) {
  if ( piece_off_edge(px, py, pr) ) return 0;
  if ( piece_hits_rubble(px, py, pr) ) return 0;
  return 1;
}
int piece_off_edge(int px, int py, int pr) {
  int x, y;
  const char *piece = pieces[piece_id] + (pr * PIECE_H * PIECE_W);

  for (y = 0; y < PIECE_H; ++y) {
    for (x = 0; x < PIECE_W; ++x) {
      int nx = px + x;
      int ny = py + y;
      if (ny < 0) continue; // off top, don't care
      if (piece[y * PIECE_W + x] > 0) {
        if (nx < 0) return 1; // yes: off left side
        if (nx >= GRID_W ) return 1; // yes: off right side
      }
    }
  }

  return 0;  // inside limits
}
int piece_hits_rubble(int px, int py, int pr) {
  int x, y;
  const char *piece = pieces[piece_id] + (pr * PIECE_H * PIECE_W);

  for (y = 0; y < PIECE_H; ++y) {
    int ny = py + y;
    if (ny < 0) continue;
    for (x = 0; x < PIECE_W; ++x) {
      int nx = px + x;
      if (piece[y * PIECE_W + x] > 0) {
        if (ny >= GRID_H ) return 1; // yes: goes off bottom of grid
        if (grid[ny * GRID_W + nx] == 1 ) return 1; // yes: grid already full in this space
      }
    }
  }

  return 0;  // doesn't hit
}
void game_over() {
  int x, y;
  while (1) {
    // Your homework: add a 'game over' animation here, then film it and tweet it to @marginallyc.
    for (x = 0; x < GRID_W; ++x) {
      for (y = 0; y < GRID_H; ++y) {
        p(x, y, 150);
      }
    }

    // click the button?
    if (digitalRead(1) == 0) {
      // restart!
      setup();
      return;
    }
  }
}
void try_to_drop_piece() {
  erase_piece_from_grid();
  if (piece_can_fit(piece_x, piece_y + 1, piece_rotation)) {
    piece_y++;  // move piece down
    add_piece_to_grid();
  } else {
    // hit something!
    // put it back
    add_piece_to_grid();
    remove_full_rows();
    if (game_is_over() == 1) {
      game_over();
    }
    // game isn't over, choose a new piece
    choose_new_piece();
  }
}

void try_to_drop_faster() {
  int y = analogRead(5);

  if(y == 0){
    try_to_drop_piece();
  }
  /*
  int y = map(analogRead(5), 1023, 0, -500, 500);
  if (y < JOYSTICK_DEAD_ZONE) {
    // player is holding joystick down, drop a little faster.
    try_to_drop_piece();
  }
  */
}

void react_to_player() {
  erase_piece_from_grid();
  try_to_move_piece_sideways();
  try_to_rotate_piece();
  add_piece_to_grid();

  try_to_drop_faster();
}
// can the piece fit in this new location
int game_is_over() {
  int x, y;
  const char *piece = pieces[piece_id] + (piece_rotation * PIECE_H * PIECE_W);

  for (y = 0; y < PIECE_H; ++y) {
    for (x = 0; x < PIECE_W; ++x) {
      int ny = piece_y + y;
      int nx = piece_x + x;
      if (piece[y * PIECE_W + x] > 0) {
        if (ny < 0) return 1; // yes: off the top!
      }
    }
  }

  return 0;  // not over yet...
}
// called once when arduino res
void setup() {
  int i;
  // set all the pins to output.
  for (i = 0; i < 16; ++i) {
    pinMode(arduino_to_grid[i], OUTPUT);
  }
  // turn on all resistors, should produce no light
  for (i = 0; i < 8; ++i) {
    digitalWrite(out(i), LOW);
    digitalWrite(in(i), HIGH);
  }

  // set up joystick button
  pinMode(1, INPUT);
  digitalWrite(1, HIGH);


  // make sure arduino knows the grid is empty.
  for (i = 0; i < GRID_W * GRID_H; ++i) {
    grid[i] = 0;

    pinMode(led, OUTPUT);
  }

  // make the game a bit more random - pull a number from space and use it to 'seed' a crop of random numbers.
  randomSeed(analogRead(4));

  // get ready to start the game.
  choose_new_piece();

  // start the game clock after everything else is ready.
  last_move = millis();
  last_drop = last_move;
Serial.begin(9600);
// called over and over after setup()
}
void loop() {
    digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);              // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(3000);              // wait for a second
  
  Serial.println(analogRead(5));

  // the game plays at one speed,
  if (millis() - last_move > move_delay ) {
    last_move = millis();
    react_to_player();
  }

  // ...and drops the falling block at a different speed.
  if (millis() - last_drop > drop_delay ) {
    last_drop = millis();
    try_to_drop_piece();
  }

  // when it isn't doing those two things, it's redrawing the grid.
  draw_grid();
}

 

현재 진행중인 테트리스 프로젝트인데 led매트릭스외에  led 전구를 를 꽂았을때 불빛을 들어오는데 켜지기만하고 loop 설정값대로 작동이 되지않는데 무엇이 문제인지 알 수 있을까요 ? 

저번에 답변주신 drop_delay 를 사용하여 속도를 빠르게 내려가게 하는건 터득을 하였는데

시간이 지날수록 점점 빨리지게 하고싶은데 이떄 사용해야하는 함수나 간단한 예제가 있으면 알려주실수 있을까요 ?

프로필사진

Klant 2016-12-15 16:37:56

안녕하십니까? 장호근님.

 

millis 함수를 통해 게임 시작 되었을 때(loop문이 시작되었을 때)부터의 시간을 측정한 뒤 조건문을 통해 millis 값이 특정 값보다 높아지면 drop_delay의 값을 차감해주는 방식으로 구현하시면 될 것 같습니다 ;)

이전글   |    시리얼통신 2016-12-14
다음글   |    앱인벤터와 아두이노 측정값에 따른 알람에 대해 문의드립니다!... 2016-12-15