정보나눔

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

수박쨈님 아두이노
최정빈 | 2016-12-09

 

#include <LiquidCrystal.h>
#include <SPI.h>
#include "Tetris.h"
#define SS_PIN 10


void setup() {
  // put your setup code here, to run once:
  lcd.begin(16, 2);
  lcd.print("   Score: 0");
  Serial.begin(9600);
  randomSeed(analogRead(0));
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  Serial.println("Loading ...");
  Dp_Init();
  Te_Init();
  Serial.println(random(9, 15) * (10 + pow(3,1) * 10));
  Serial.println(random(9, 15) * (10 + pow(3,2) * 10));
  Serial.println(random(9, 15) * (10 + pow(3,3) * 10));
  Serial.println(random(9, 15) * (10 + pow(3,4) * 10));
}



byte xC = 0;
byte yC = 0;
long frameCount = 0;

void loop() {
  // put your main code here, to run repeatedly:
  frameCount++;
  Te_Draw();
  Te_Update(frameCount);
  delay(1);
}




#include <LiquidCrystal.h>https://create.arduino.cc/
#include <SPI.h>
#define SS_PIN 10
#define DP_HEIGHT 16
#define DP_WIDTH 10

LiquidCrystal lcd(7, 6, 5, 4, 3, 2);
void Dp_DrawLine(int x, int y, int length, bool hori, bool isSet);

struct ZeichenFlaeche {
  byte grid[8] = {
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000
};
};

ZeichenFlaeche zeichen[2][2]; 

void Dp_Init()
{
  lcd.createChar(0, zeichen[0][0].grid);
  lcd.createChar(1, zeichen[0][1].grid);
  lcd.createChar(2, zeichen[1][0].grid);
  lcd.createChar(3, zeichen[1][1].grid);
  Dp_DrawLine(0,0,10,true,true); // Linie Oben H
  Dp_DrawLine(0,15,10,true,true); // Linie Unten H
  Dp_DrawLine(0,0,16,false,true); // Linie Links V
  Dp_DrawLine(9,0,16,false,true); // Linie Rechts V
}

void Dp_Draw()
{
  lcd.createChar(0, zeichen[0][0].grid);
  lcd.createChar(1, zeichen[0][1].grid);
  lcd.createChar(2, zeichen[1][0].grid);
  lcd.createChar(3, zeichen[1][1].grid);
  lcd.setCursor(0, 0);
  lcd.write(byte(0));
  
  lcd.setCursor(0, 1);
  lcd.write(byte(1));
  
  lcd.setCursor(1, 0);
  lcd.write(byte(2));
  
  lcd.setCursor(1, 1);
  lcd.write(byte(3));
}

void Dp_SetPixel(int x, int y, bool isOn)
{
  if(isOn)
    bitSet  (zeichen[x/5][y/8].grid[y%8],4-x%5);
  else 
    bitClear(zeichen[x/5][y/8].grid[y%8],4-x%5);
}

bool Dp_GetPixel(int x, int y)
{
  return bitRead(zeichen[x/5][y/8].grid[y%8],4-x%5)==1?true:false;
}

void Dp_DrawLine(int x, int y, int length, bool hori, bool isSet)
{
  for(int offset = 0; offset < length; offset++)
  {
    if(hori)
      Dp_SetPixel(x + offset, y, isSet);
    else
      Dp_SetPixel(x, y + offset, isSet);
  }
}


#include "Display.h"

#define TE_WIDTH (DP_WIDTH - 2)
#define TE_HEIGHT (DP_HEIGHT - 2)

enum Stone_Type {
  TStone = 0,
  LStone = 1,
  IStone = 2,
  SStone = 3,
  ZStone = 5,
  OStone = 4,
};

struct Stone {
  byte field[4];
  char x = TE_WIDTH / 2 - 1;
  char y = 1;
  char rot = 0;
  Stone_Type type;
};

Stone St_InitStone();

bool St_HitTest(Stone st)
{
  for(char x = 0; x < 5; x++) // Zeilen eines Steins
  {
    for(char y = 0; y < 4; y++) // Spalten eines Steins
    {
      if(bitRead(st.field[y],x) == 1) // Ist der aktuelle Stein Pixel gesetzt?
      {
        char xT = st.x  + x; // Absolute x Position
        char yT = st.y + y;  // Absolute y Position
        if(xT < 1 || xT > TE_WIDTH || yT < 1 || yT > TE_HEIGHT) // Aktueller Stein Pixel aus dem Fenster.
        {
          Serial.print("HIT OUTWINDOW xT=");
          Serial.print(xT, DEC);
          Serial.print(" yT=");
          Serial.println(yT, DEC);
          return true;
        }
        if(Dp_GetPixel(xT,yT)) // Aktueller Stein Pixel auf dem Display ist belegt.
        {
          Serial.print("HIT Pixel xT=");
          Serial.print(xT, DEC);
          Serial.print(" yT=");
          Serial.println(yT, DEC);
          return true;
        }
      }
    }
  }
  return false;
}

void St_Print(Stone st, bool printIt)
{
  for(char x = 0; x < 5; x++)
  {
    for(char y = 0; y < 4; y++)
    {
      if(bitRead(st.field[y],x) == 1)
      {
        char xT = st.x  + x;
        char yT = st.y + y;
        if(xT < 1 || xT > TE_WIDTH || yT < 1 || yT > TE_HEIGHT) // Aktueller Stein Pixel aus dem Fenster.
          continue;
        Dp_SetPixel(xT, yT, printIt);
      }
    }
  }
}

void St_SetRot(Stone *st, char rot)
{
  (*st).rot = rot;
  switch((*st).type)
  {
    case TStone: 
    {
      switch(rot)
      {
        case 0: 
        {
          (*st).field[0] = B00000;
          (*st).field[1] = B00100;
          (*st).field[2] = B01110;
          (*st).field[3] = B00000;
        } break;

        case 1: 
        {
          (*st).field[0] = B00000;
          (*st).field[1] = B00100;
          (*st).field[2] = B00110;
          (*st).field[3] = B00100;
        } break;

        case 2: 
        {
          (*st).field[0] = B00000;
          (*st).field[1] = B00000;
          (*st).field[2] = B01110;
          (*st).field[3] = B00100;
        } break;

        case 3: 
        {
          (*st).field[0] = B00000;
          (*st).field[1] = B00100;
          (*st).field[2] = B01100;
          (*st).field[3] = B00100;
        } break;
      }
    } break;
    
    case LStone: 
    {
      switch(rot)
      {
        case 0: 
        {
          (*st).field[0] = B00000;
          (*st).field[1] = B00010;
          (*st).field[2] = B01110;
          (*st).field[3] = B00000;
        } break;

        case 1: 
        {
          (*st).field[0] = B00000;
          (*st).field[1] = B00100;
          (*st).field[2] = B00100;
          (*st).field[3] = B00110;
        } break;

        case 2: 
        {
          (*st).field[0] = B00000;
          (*st).field[1] = B00000;
          (*st).field[2] = B01110;
          (*st).field[3] = B01000;
        } break;

        case 3: 
        {
          (*st).field[0] = B00000;
          (*st).field[1] = B01100;
          (*st).field[2] = B00100;
          (*st).field[3] = B00100;
        } break;
      }
    } break;
    
    case IStone: 
    {
      switch(rot)
      {
        case 0: 
        case 2: 
        {
          (*st).field[0] = B00100;
          (*st).field[1] = B00100;
          (*st).field[2] = B00100;
          (*st).field[3] = B00100;
        } break;
        
        case 1:
        case 3: 
        {
          (*st).field[0] = B00000;
          (*st).field[1] = B00000;
          (*st).field[2] = B01111;
          (*st).field[3] = B00000;
        } break;
      }
    } break;
    
    case SStone: 
    {
      switch(rot)
      {
        case 0: 
        {
          (*st).field[0] = B00000;
          (*st).field[1] = B01100;
          (*st).field[2] = B00110;
          (*st).field[3] = B00000;
        } break;

        case 1: 
        {
          (*st).field[0] = B00000;
          (*st).field[1] = B00100;
          (*st).field[2] = B01100;
          (*st).field[3] = B01000;
        } break;

        case 2: 
        {
          (*st).field[0] = B00000;
          (*st).field[1] = B01100;
          (*st).field[2] = B00110;
          (*st).field[3] = B00000;
        } break;

        case 3: 
        {
          (*st).field[0] = B00000;
          (*st).field[1] = B00010;
          (*st).field[2] = B00110;
          (*st).field[3] = B00100;
        } break;
      }
    } break;

    case OStone: 
    {
      switch(rot)
      {
        case 0: 
        case 1: 
        case 2: 
        case 3: 
        {
          (*st).field[0] = B00000;
          (*st).field[1] = B01100;
          (*st).field[2] = B01100;
          (*st).field[3] = B00000;
        } break;
      }
    } break;
    
    default: break;
  }
}

void St_Rotate(Stone *st)
{
  St_SetRot(st, ((*st).rot+1)%4);
}

void St_BackRotate(Stone *st)
{
  char rot = (*st).rot - 1;
  if(rot == -1)
  rot = 3;
  St_SetRot(st, rot);
}

Stone St_InitStone()
{
  Stone st;
  st.type = (Stone_Type)random(0,5);
  St_SetRot(&st, 0);
  return st;
}

#include "Stone.h"

#define BUTTON_LEFT 13
#define BUTTON_RIGHT 12
#define BUTTON_ROT 11
#define BUTTON_DOWN 10

bool BUTTON_LEFT_LAST = false;
bool BUTTON_RIGHT_LAST = false;
bool BUTTON_ROT_LAST = false;
bool BUTTON_DOWN_LAST = false;
long points = 0;

Stone currentStone;

void Te_Init()
{
  currentStone = St_InitStone();
  pinMode(BUTTON_LEFT, INPUT);
  pinMode(BUTTON_RIGHT, INPUT);
  pinMode(BUTTON_DOWN, INPUT);  

}

void Te_Draw()
{
  St_Print(currentStone, true);
  Dp_Draw();
  St_Print(currentStone, false);
}

void Te_AddPoints(long p)
{
  points += p;
  lcd.setCursor(10, 0);
  lcd.print(points);
}

void Te_DeleteRow(int row)
{
  bool sw = true;
  for (int i = 0; i < 15; i++)
  {
    Dp_DrawLine(1, row, 8, true, sw);
    Dp_DrawLine(0,0,10,true,!sw); // Linie Oben H
    Dp_DrawLine(0,15,10,true,!sw); // Linie Unten H
    Dp_DrawLine(0,0,16,false,!sw); // Linie Links V
    Dp_DrawLine(9,0,16,false,!sw); // Linie Rechts V
    Dp_Draw();
    delay(90);
    sw = sw ? false : true;
  }
  Dp_DrawLine(1, row, 8, true, false);
  Dp_DrawLine(0,0,10,true,true); // Linie Oben H
  Dp_DrawLine(0,15,10,true,true); // Linie Unten H
  Dp_DrawLine(0,0,16,false,true); // Linie Links V
  Dp_DrawLine(9,0,16,false,true); // Linie Rechts V
  Dp_Draw();
  for (int zeile = row; zeile > 2; zeile--)
  {
    for (int x = 1; x < TE_WIDTH + 1; x++)
    {
      Dp_SetPixel(x, zeile, Dp_GetPixel(x, zeile - 1));
    }
  }
}

void Te_CheckRows()
{
  byte rowWins = 0;
  for (int zeile = TE_HEIGHT; zeile > 0; zeile--)
  {
    bool zeileVoll = true;
    for (int x = 1; x < TE_WIDTH; x++)
    {
      if (!Dp_GetPixel(x, zeile)) // Ist noch ein Stück frei in der aktuellen Zeile?
      {
        zeileVoll = false;
        break;
      }
    }
    if (zeileVoll) // Ist die aktuelle Zeile voll?
    {
      rowWins++;
      Te_DeleteRow(zeile);
      zeile++;
    }
  }
  if (rowWins > 0)
    Te_AddPoints(random(9, 15) * (10 + pow(3,rowWins) * 10));
}

void Te_Reload()
{
  for (int row = 1; row < TE_HEIGHT + 1; row++)
  {
    Dp_DrawLine(1, row, 8, true, true);
    Dp_Draw();
    delay(60);
  }
  delay(400);
  for (int row = TE_HEIGHT; row >= 1 ; row--)
  {
    Dp_DrawLine(1, row, 8, true, false);
    Dp_Draw();
    delay(60);
  }
  currentStone = St_InitStone();
  points = 0;
  lcd.setCursor(10, 0);
  lcd.print("0     ");
  lcd.setCursor(3, 1);
  lcd.print("             ");
}

void Te_Update(long frameCount)
{
  if (frameCount % 40  == 0)
  {
    currentStone.y++;
    if (St_HitTest(currentStone)) // Stein ist unten Angekommen.
    {
      currentStone.y--;
      for(int i = 0; i < 5; i++)
      {
        St_Print(currentStone, true);
        Dp_Draw();
        delay(60);
        St_Print(currentStone, false);
        Dp_Draw();
        delay(60);
      }
      St_Print(currentStone, true);
      currentStone = St_InitStone();
      Dp_Draw();
      if (St_HitTest(currentStone))
      {
        lcd.setCursor(3, 1);
        lcd.write("Game Over!");
        delay(1000);
        while (!digitalRead(BUTTON_LEFT) || !digitalRead(BUTTON_RIGHT));
        Te_Reload();
      }
      Te_AddPoints(random(1, 4) * 10);
      Te_CheckRows();
      return;
    }
  }

  if(frameCount % 10) // Nach Unten Schieben frei geben (Damit man den Knopf gedrückt lassen kann)
  {
    BUTTON_DOWN_LAST=false;
  }


  if (digitalRead(BUTTON_LEFT))
  {
    if (!BUTTON_LEFT_LAST)
    {
      BUTTON_LEFT_LAST = true;

      // Versuche Stein zu verschieben
      currentStone.x--;
      if (St_HitTest(currentStone))
        currentStone.x++;
    }
  }
  else BUTTON_LEFT_LAST = false;

  if (digitalRead(BUTTON_RIGHT))
  {
    if (!BUTTON_RIGHT_LAST)
    {
      BUTTON_RIGHT_LAST = true;

      // Versuche Stein zu verschieben
      currentStone.x++;
      if (St_HitTest(currentStone))
        currentStone.x--;
    }
  }
  else BUTTON_RIGHT_LAST = false;

  if (digitalRead(BUTTON_ROT))
  {
    if (!BUTTON_ROT_LAST)
    {
      BUTTON_ROT_LAST = true;

      // Versuche Stein zu verschieben
      St_Rotate(&currentStone);
      if (St_HitTest(currentStone))
        St_BackRotate(&currentStone);
    }
  }
  else BUTTON_ROT_LAST = false;

  if (digitalRead(BUTTON_DOWN))
  {
    if (!BUTTON_DOWN_LAST)
    {
      BUTTON_DOWN_LAST = true;

      // Versuche Stein zu verschieben
      currentStone.y++;
      if (St_HitTest(currentStone))
        currentStone.y--;
    }
  }
  else BUTTON_DOWN_LAST = false;
}



http://www.kocoafab.cc/make/view/691

프로젝트에서 초소형 테트리스를 보고 구현해보았는데 스위치가 맨왼쪽을 제외하고 3개가 작동이 안되어서

헤더파일은 작동하는데 회로도 문제도 아니고 어디서 문제가 되는지 잘모르겠어서 연락드립니다ㅠㅠ

소스부분에서 잘못된것같은데 어디부분을 고쳐야할지..

이전글   |    아두이노 문의 Klant님 답변 부탁드립니다!!! ... 2016-12-09
다음글   |    아두이노 Grove 지문인식 사용 질문합니다! 2016-12-09