#define MATRIX_A 0
#define MATRIX_B 1
// Matrix
#define PIN_DATAIN 3
#define PIN_CLK 2
#define PIN_LOAD 4
// Accelerometer
#define PIN_X A6
#define PIN_Y A7
// 시간 정하기
long setTime = 18000;
int interval = setTime/64;
int dir[2];
int dotMatrix[8][8];
int dotX[8][8];
int dotY[8][8];
bool dotState[2][8][8];
int space = 8;
bool dropDot = false;
unsigned long startMills;
LedControl lc = LedControl(PIN_DATAIN, PIN_CLK, PIN_LOAD, 2);
void setup(){
Serial.begin(9600);
lc.shutdown(0,false);
lc.shutdown(1,false);
lc.setIntensity(0,2);
lc.setIntensity(1,2);
Serial.begin(9600);
startMills = millis();
// 위의 도트 채우기 & 각 도트의 state 설정
for(int i = 0;i<8;i++){
for(int j = 0;j<8;j++){
dotMatrix[i][j] = 1;
dotX[i][j] = i;
dotY[i][j] = j;
lc.setLed(1,i,j,true);
dotState[1][i][j] = true;
dotState[0][i][j] = false;
}
}
}
void loop(){
for(int i =0;i<8;i++){
for(int j = 0;j<8;j++){
Move(i,j);
}
}
unsigned long time = millis();
if((time-startMills) > interval){
dropDot = true;
startMills = time;
}
}
void Move(int i,int j){
// 자이로센서의 값 반영하여 도트의 x, y의 방향 정하기
GetDirection();
int currentX = dotX[i][j];
int currentY = dotY[i][j];
int currentMatrix = dotMatrix[i][j];
int newX = currentX + dir[0];
int newY = currentY + dir[1];
int newMatrix;
// 도트가 다른 도트매트릭스로 떨어질때 x,y 새로 정하기
if(currentMatrix == 0 && newX == -1 && newY == 8 && dropDot){
newMatrix = 1;
newX =7;
newY=0;
} else if(currentMatrix == 1 && newX == 8 && newY == -1 && dropDot){
newMatrix = 0;
newX = 0;
newY = 7;
} else {
newMatrix = currentMatrix;
}
// 다음 위치의 도트가 차있을때 (return 값 false일때)
if(!IsMovable(newMatrix,newX,newY)){ // IsMovable(newMatrix,newX,newY) == true
// 도트매트릭스의 번호가 바뀌었을때 (위에서 다음 도트의 x,y 정해줬으니 pass)
if(newMatrix != currentMatrix){
return;
}
// 왼쪽으로 갈지 오른쪽으로 갈지 정하기
bool isLeftMovable = IsMovable(newMatrix,currentX,newY);
bool isRightMovable = IsMovable(newMatrix,newX,currentY);
// 둘다 도트가 차있으면
if(!isLeftMovable && !isRightMovable){
return;
}
// 둘다 비어있으면
if(isLeftMovable && isRightMovable){
if(rand()>16383){
isLeftMovable = false;
}else{
isRightMovable = false;
}
}
// 도트의 방향 정하기
if(isLeftMovable){
newX =currentX;
}else if(isRightMovable){
newY = currentY;
}
}
// 현재 도트값 끄기 및 상태 false로 저장
lc.setLed(currentMatrix,currentX,currentY,false);
dotState[currentMatrix][currentX][currentY] = false;
// 다음 위치의 도트값 켜기 및 상태 true로 저장
lc.setLed(newMatrix,newX,newY,true);
dotState[newMatrix][newX][newY] = true;
// 만약 도트매트릭스가 바뀌었다면 (떨어지는 도트가 있었다면)
if(currentMatrix != newMatrix && dropDot){
// 다음 도트 떨어질때 까지 기다리기
dropDot = false;
}
// 현재 도트의 위치에 다음 도트의 위치 넣기
dotMatrix[i][j] = newMatrix;
dotX[i][j] = newX;
dotY[i][j] = newY;
}
// 도트의 true false 확인하기
bool IsMovable(int matrix, int x, int y){
// 도트매트릭스의 범위 벗어났을때
if(x>=space || y>=space || x<0 || y<0){
return false;
}
// 현재 도트의 state 반댓값 return
//( 도트 상태가 true면 false / 도트 상태가 false면 true )
return !dotState[matrix][x][y];
}
void GetDirection(){
int x;
int y;
// 자이로센서 값 반영하여 x,y 위치 정하기
x = ChangeValue(analogRead(PIN_X)-330);
y = ChangeValue(analogRead(PIN_Y)-330);
if(x==1){
if(y==1){
dir[0]=0;
dir[1]=1;
}else if(y==-1){
dir[0]=-1;
dir[1]=0;
}else{
dir[0]=-1;
dir[1]=1;
}
}else if(x==-1){
if(y==1){
dir[0]=1;
dir[1]=0;
}else if(y==-1){
dir[0]=0;
dir[1]=-1;
}else{
dir[0]=1;
dir[1]=-1;
}
}else{
if(y==1){
dir[0]=1;
dir[1]=1;
}else if(y==-1){
dir[0]=-1;
dir[1]=-1;
}else{
dir[0]=0;
dir[1]=0;
}
}
}
//
int ChangeValue(int value){
if(value<40 && value>-40){
return 0;
}else if(value>=40){
return 1;
}else{
return -1;
}
}