#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(¤tStone);
if (St_HitTest(currentStone))
St_BackRotate(¤tStone);
}
}
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개가 작동이 안되어서
헤더파일은 작동하는데 회로도 문제도 아니고 어디서 문제가 되는지 잘모르겠어서 연락드립니다ㅠㅠ
소스부분에서 잘못된것같은데 어디부분을 고쳐야할지..
|