Day4 07-tetris
2024. 2. 4. 15:57ㆍarduino
- OLED와 조이스틱을 이용한 테트리스 게임
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Wire.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
const int restartButtonPin = 2;
const int xPin = A0;
const int yPin = A1;
int xPos = 0;
int yPos = 0;
const int BLOCK_SIZE = 4;
const int BLOCK_TYPES = 9;
const int BOARD_WIDTH = 15;
const int BOARD_HEIGHT = 15;
byte tetrominoes[BLOCK_TYPES][4] = {
{B00001111, B00000000, B00000000, B00000000},
{B00000110, B00000111, B00000000, B00000000},
{B00001100, B00000111, B00000000, B00000000},
{B00001100, B00001100, B00000000, B00000000},
{B00000110, B00001100, B00000000, B00000000},
{B00001100, B00001110, B00000000, B00000000},
{B00000100, B00001111, B00000000, B00000000},
};
int board[BOARD_HEIGHT][BOARD_WIDTH] = {0};
int currentX = BOARD_WIDTH / 2;
int currentY = 0;
int currentBlock = 0;
int rotation = 0;
unsigned long previousMillis = 0;
const long interval = 500;
unsigned long lastRotationTime = 0;
const unsigned long rotationDelay = 200;
int score = 0; // 추가된 부분: 점수 변수
void setup() {
pinMode(restartButtonPin, INPUT_PULLUP);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
randomSeed(analogRead(A3));
newBlock();
}
void loop() {
xPos = analogRead(xPin);
yPos = analogRead(yPin);
handleInput();
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
if (!move(0, 1)) {
updateBoard();
int linesCleared = checkLines(); // 추가된 부분: 지워진 라인 수에 따라 점수 증가
if (linesCleared > 0) {
score += linesCleared * 100;
}
newBlock();
}
}
display.clearDisplay();
drawBoard();
drawBlock();
display.setCursor(65, 0);
display.print("Score:");
display.print(score);
display.display();
}
void handleInput() {
if (analogRead(xPin) < 100) {
move(-1, 0);
} else if (analogRead(xPin) > 900) {
move(1, 0);
}
if (analogRead(yPin) < 100) {
rotateBlock();
} else if (analogRead(yPin) > 900) {
move(0, 1);
}
if (digitalRead(restartButtonPin) == LOW) {
while (move(0, 1));
}
}
bool move(int x, int y) {
if (checkCollision(currentX + x, currentY + y, rotation)) {
return false;
}
currentX += x;
currentY += y;
return true;
}
void rotateBlock() {
unsigned long currentMillis = millis();
if (currentMillis - lastRotationTime >= rotationDelay) {
lastRotationTime = currentMillis;
int newRotation = (rotation + 1) % 4;
if (checkCollision(currentX, currentY, newRotation)) {
return;
}
rotation = newRotation;
}
}
bool checkCollision(int x, int y, int rot) {
for (int row = 0; row < 4; row++) {
for (int col = 0; col < 4; col++) {
if (tetrominoes[currentBlock][rotate(row, col, rot)] &&
(board[y + row][x + col] != 0 || x + col < 0 || x + col >= BOARD_WIDTH || y + row >= BOARD_HEIGHT)) {
return true;
}
}
}
return false;
}
int rotate(int row, int col, int rot) {
switch (rot) {
case 0: return row * 4 + col;
case 1: return 12 + row - col * 4;
case 2: return 15 - row * 4 - col;
case 3: return 3 - row + col * 4;
}
return 0;
}
void updateBoard() {
for (int row = 0; row < 4; row++) {
for (int col = 0; col < 4; col++) {
if (tetrominoes[currentBlock][rotate(row, col, rotation)]) {
board[currentY + row][currentX + col] = currentBlock + 1;
}
}
}
} //스테이지
int checkLines() {
int linesCleared = 0;
for (int row = BOARD_HEIGHT - 1; row >= 0; row--) {
bool lineIsFull = true;
for (int col = 0; col < BOARD_WIDTH; col++) {
if (board[row][col] == 0) {
lineIsFull = false;
break;
}
}
if (lineIsFull) {
linesCleared++;
for (int j = row; j > 0; j--) {
for (int col = 0; col < BOARD_WIDTH; col++) {
board[j][col] = board[j - 1][col];
}
}
for (int col = 0; col < BOARD_WIDTH; col++) {
board[0][col] = 0;
}
}
}
return linesCleared;
}
void newBlock() {
currentX = BOARD_WIDTH / 2;
currentY = 0;
currentBlock = random(0, BLOCK_TYPES);
rotation = 0;
if (checkCollision(currentX, currentY, rotation)) {
for (int row = 0; row < BOARD_HEIGHT; row++) {
for (int col = 0; col < BOARD_WIDTH; col++) {
board[row][col] = 0;
}
}
display.clearDisplay();
display.setCursor(20, 20);
display.print("GAME OVER");
display.display();
while (digitalRead(restartButtonPin) == HIGH); // 재시작 버튼이 눌릴 때까지 대기합니다.
delay(200); // 디바운스를 위해 잠시 딜레이를 추가합니다.
newBlock(); // 새 블록을 생성하여 새 게임을 시작합니다.
}
}
void drawBoard() {
// Draw the border
display.drawRect(0, 0, BOARD_WIDTH * BLOCK_SIZE, BOARD_HEIGHT * BLOCK_SIZE, SSD1306_WHITE);
for (int row = 0; row < BOARD_HEIGHT; row++) {
for (int col = 0; col < BOARD_WIDTH; col++) {
int blockType = board[row][col];
if (blockType > 0) {
display.fillRect(col * BLOCK_SIZE + 1, row * BLOCK_SIZE + 1, BLOCK_SIZE - 2, BLOCK_SIZE - 2, SSD1306_WHITE);
}
}
}
}
void drawBlock() {
for (int row = 0; row < 4; row++) {
for (int col = 0; col < 4; col++) {
if (tetrominoes[currentBlock][rotate(row, col, rotation)]) {
int x = (currentX + col) * BLOCK_SIZE;
int y = (currentY + row) * BLOCK_SIZE;
display.fillRect(x, y, BLOCK_SIZE, BLOCK_SIZE, SSD1306_WHITE);
}
}
}
}
'arduino' 카테고리의 다른 글
Day4 06-joystick (0) | 2024.02.04 |
---|---|
Day4 05-DCmotor, button 2 (0) | 2024.02.04 |
Day4 04-DCmotor, button (0) | 2024.02.04 |
Day4 03-DCmotor (0) | 2024.02.04 |
Day4 02-encoder (0) | 2024.02.04 |