- // TETRIS
- #include <FastLED.h>
- #include <LEDMatrix.h>
- #include <LEDSprites.h>
- #include <LEDText.h>
- #include <FontMatrise.h>
- #include "BluetoothSerial.h"
- #define LED_PIN 15
- #define COLOR_ORDER GRB
- #define CHIPSET WS2812B
- #define MATRIX_WIDTH 30
- #define MATRIX_HEIGHT 15
- #define MATRIX_TYPE HORIZONTAL_MATRIX
- // NOTE the '-' sign before the width, this is due to my leds matrix origin being on the right hand side
- cLEDMatrix<MATRIX_WIDTH, -MATRIX_HEIGHT, MATRIX_TYPE> leds;
- BluetoothSerial SerialBT;
- #define TARGET_FRAME_TIME 15 // Desired update rate, though if too many leds it will just run as fast as it can!
- #define INITIAL_DROP_FRAMES 20 // Start of game block drop delay in frames
- // Bluetooth input
- enum btnInput {NONE, ROTATE, DOWN, LEFT, RIGHT};
- btnInput currentInput = NONE;
- const uint8_t TetrisIData[] =
- {
- // Frame 1
- B8_3BIT(00000000),
- B8_3BIT(00000000),
- B8_3BIT(00000000),
- B8_3BIT(11110000),
- // Frame 2
- B8_3BIT(10000000),
- B8_3BIT(10000000),
- B8_3BIT(10000000),
- B8_3BIT(10000000),
- // Frame 3
- B8_3BIT(00000000),
- B8_3BIT(00000000),
- B8_3BIT(00000000),
- B8_3BIT(11110000),
- // Frame 4
- B8_3BIT(10000000),
- B8_3BIT(10000000),
- B8_3BIT(10000000),
- B8_3BIT(10000000)
- };
- const uint8_t TetrisIMask[] =
- {
- // Frame 1
- B8_1BIT(00000000),
- B8_1BIT(00000000),
- B8_1BIT(00000000),
- B8_1BIT(11110000),
- // Frame 2
- B8_1BIT(10000000),
- B8_1BIT(10000000),
- B8_1BIT(10000000),
- B8_1BIT(10000000),
- // Frame 3
- B8_1BIT(00000000),
- B8_1BIT(00000000),
- B8_1BIT(00000000),
- B8_1BIT(11110000),
- // Frame 4
- B8_1BIT(10000000),
- B8_1BIT(10000000),
- B8_1BIT(10000000),
- B8_1BIT(10000000)
- };
- const uint8_t TetrisJData[] =
- {
- // Frame 1
- B8_3BIT(00000000),
- B8_3BIT(00000000),
- B8_3BIT(22200000),
- B8_3BIT(00200000),
- // Frame 2
- B8_3BIT(00000000),
- B8_3BIT(02000000),
- B8_3BIT(02000000),
- B8_3BIT(22000000),
- // Frame 3
- B8_3BIT(00000000),
- B8_3BIT(00000000),
- B8_3BIT(20000000),
- B8_3BIT(22200000),
- // Frame 4
- B8_3BIT(00000000),
- B8_3BIT(22000000),
- B8_3BIT(20000000),
- B8_3BIT(20000000)
- };
- const uint8_t TetrisJMask[] =
- {
- // Frame 1
- B8_1BIT(00000000),
- B8_1BIT(00000000),
- B8_1BIT(11100000),
- B8_1BIT(00100000),
- // Frame 2
- B8_1BIT(00000000),
- B8_1BIT(01000000),
- B8_1BIT(01000000),
- B8_1BIT(11000000),
- // Frame 3
- B8_1BIT(00000000),
- B8_1BIT(00000000),
- B8_1BIT(10000000),
- B8_1BIT(11100000),
- // Frame 4
- B8_1BIT(00000000),
- B8_1BIT(11000000),
- B8_1BIT(10000000),
- B8_1BIT(10000000)
- };
- const uint8_t TetrisLData[] =
- {
- // Frame 1
- B8_3BIT(00000000),
- B8_3BIT(00000000),
- B8_3BIT(33300000),
- B8_3BIT(30000000),
- // Frame 2
- B8_3BIT(00000000),
- B8_3BIT(33000000),
- B8_3BIT(03000000),
- B8_3BIT(03000000),
- // Frame 3
- B8_3BIT(00000000),
- B8_3BIT(00000000),
- B8_3BIT(00300000),
- B8_3BIT(33300000),
- // Frame 4
- B8_3BIT(00000000),
- B8_3BIT(30000000),
- B8_3BIT(30000000),
- B8_3BIT(33000000)
- };
- const uint8_t TetrisLMask[] =
- {
- // Frame 1
- B8_1BIT(00000000),
- B8_1BIT(00000000),
- B8_1BIT(11100000),
- B8_1BIT(10000000),
- // Frame 2
- B8_1BIT(00000000),
- B8_1BIT(11000000),
- B8_1BIT(01000000),
- B8_1BIT(01000000),
- // Frame 3
- B8_1BIT(00000000),
- B8_1BIT(00000000),
- B8_1BIT(00100000),
- B8_1BIT(11100000),
- // Frame 4
- B8_1BIT(00000000),
- B8_1BIT(10000000),
- B8_1BIT(10000000),
- B8_1BIT(11000000)
- };
- const uint8_t TetrisOData[] =
- {
- // Frame 1
- B8_3BIT(00000000),
- B8_3BIT(00000000),
- B8_3BIT(44000000),
- B8_3BIT(44000000),
- // Frame 2
- B8_3BIT(00000000),
- B8_3BIT(00000000),
- B8_3BIT(44000000),
- B8_3BIT(44000000),
- // Frame 3
- B8_3BIT(00000000),
- B8_3BIT(00000000),
- B8_3BIT(44000000),
- B8_3BIT(44000000),
- // Frame 4
- B8_3BIT(00000000),
- B8_3BIT(00000000),
- B8_3BIT(44000000),
- B8_3BIT(44000000)
- };
- const uint8_t TetrisOMask[] =
- {
- // Frame 1
- B8_1BIT(00000000),
- B8_1BIT(00000000),
- B8_1BIT(11000000),
- B8_1BIT(11000000),
- // Frame 2
- B8_1BIT(00000000),
- B8_1BIT(00000000),
- B8_1BIT(11000000),
- B8_1BIT(11000000),
- // Frame 3
- B8_1BIT(00000000),
- B8_1BIT(00000000),
- B8_1BIT(11000000),
- B8_1BIT(11000000),
- // Frame 4
- B8_1BIT(00000000),
- B8_1BIT(00000000),
- B8_1BIT(11000000),
- B8_1BIT(11000000)
- };
- const uint8_t TetrisSData[] =
- {
- // Frame 1
- B8_3BIT(00000000),
- B8_3BIT(00000000),
- B8_3BIT(05500000),
- B8_3BIT(55000000),
- // Frame 2
- B8_3BIT(00000000),
- B8_3BIT(50000000),
- B8_3BIT(55000000),
- B8_3BIT(05000000),
- // Frame 3
- B8_3BIT(00000000),
- B8_3BIT(00000000),
- B8_3BIT(05500000),
- B8_3BIT(55000000),
- // Frame 4
- B8_3BIT(00000000),
- B8_3BIT(50000000),
- B8_3BIT(55000000),
- B8_3BIT(05000000)
- };
- const uint8_t TetrisSMask[] =
- {
- // Frame 1
- B8_1BIT(00000000),
- B8_1BIT(00000000),
- B8_1BIT(01100000),
- B8_1BIT(11000000),
- // Frame 2
- B8_1BIT(00000000),
- B8_1BIT(10000000),
- B8_1BIT(11000000),
- B8_1BIT(01000000),
- // Frame 3
- B8_1BIT(00000000),
- B8_1BIT(00000000),
- B8_1BIT(01100000),
- B8_1BIT(11000000),
- // Frame 4
- B8_1BIT(00000000),
- B8_1BIT(10000000),
- B8_1BIT(11000000),
- B8_1BIT(01000000)
- };
- const uint8_t TetrisTData[] =
- {
- // Frame 1
- B8_3BIT(00000000),
- B8_3BIT(00000000),
- B8_3BIT(66600000),
- B8_3BIT(06000000),
- // Frame 2
- B8_3BIT(00000000),
- B8_3BIT(06000000),
- B8_3BIT(66000000),
- B8_3BIT(06000000),
- // Frame 3
- B8_3BIT(00000000),
- B8_3BIT(00000000),
- B8_3BIT(06000000),
- B8_3BIT(66600000),
- // Frame 4
- B8_3BIT(00000000),
- B8_3BIT(60000000),
- B8_3BIT(66000000),
- B8_3BIT(60000000)
- };
- const uint8_t TetrisTMask[] =
- {
- // Frame 1
- B8_1BIT(00000000),
- B8_1BIT(00000000),
- B8_1BIT(11100000),
- B8_1BIT(01000000),
- // Frame 2
- B8_1BIT(00000000),
- B8_1BIT(01000000),
- B8_1BIT(11000000),
- B8_1BIT(01000000),
- // Frame 3
- B8_1BIT(00000000),
- B8_1BIT(00000000),
- B8_1BIT(01000000),
- B8_1BIT(11100000),
- // Frame 4
- B8_1BIT(00000000),
- B8_1BIT(10000000),
- B8_1BIT(11000000),
- B8_1BIT(10000000)
- };
- const uint8_t TetrisZData[] =
- {
- // Frame 1
- B8_3BIT(00000000),
- B8_3BIT(00000000),
- B8_3BIT(77000000),
- B8_3BIT(07700000),
- // Frame 2
- B8_3BIT(00000000),
- B8_3BIT(07000000),
- B8_3BIT(77000000),
- B8_3BIT(70000000),
- // Frame 3
- B8_3BIT(00000000),
- B8_3BIT(00000000),
- B8_3BIT(77000000),
- B8_3BIT(07700000),
- // Frame 4
- B8_3BIT(00000000),
- B8_3BIT(07000000),
- B8_3BIT(77000000),
- B8_3BIT(70000000)
- };
- const uint8_t TetrisZMask[] =
- {
- // Frame 1
- B8_1BIT(00000000),
- B8_1BIT(00000000),
- B8_1BIT(11000000),
- B8_1BIT(01100000),
- // Frame 2
- B8_1BIT(00000000),
- B8_1BIT(01000000),
- B8_1BIT(11000000),
- B8_1BIT(10000000),
- // Frame 3
- B8_1BIT(00000000),
- B8_1BIT(00000000),
- B8_1BIT(11000000),
- B8_1BIT(01100000),
- // Frame 4
- B8_1BIT(00000000),
- B8_1BIT(01000000),
- B8_1BIT(11000000),
- B8_1BIT(10000000)
- };
- #define TETRIS_SPR_WIDTH 4
- #define TETRIS_SPR_HEIGHT 4
- const uint8_t *TetrisSprData[] = { TetrisIData, TetrisJData, TetrisLData, TetrisOData, TetrisSData, TetrisTData, TetrisZData };
- const uint8_t *TetrisSprMask[] = { TetrisIMask, TetrisJMask, TetrisLMask, TetrisOMask, TetrisSMask, TetrisTMask, TetrisZMask};
- const struct CRGB TetrisColours[] = { CRGB(0, 255, 255), CRGB(0, 0, 255), CRGB(255, 165, 0), CRGB(255, 255, 0), CRGB(50, 205, 50), CRGB(255, 0, 255), CRGB(255, 0, 0) };
- uint8_t PlayfieldData[MATRIX_HEIGHT * ((MATRIX_WIDTH + 7) / 8) * _3BIT];
- uint8_t PlayfieldMask[MATRIX_HEIGHT * ((MATRIX_WIDTH + 7) / 8) * _1BIT];
- uint8_t CompletedLinesData[TETRIS_SPR_HEIGHT * ((MATRIX_WIDTH + 7) / 8) * _1BIT];
- const struct CRGB CompletedLinesColour[] = { CRGB(255, 255, 255) };
- cSprite Playfield, CompletedLines, CurrentBlock;
- cLEDSprites Sprites(&leds);
- unsigned char AttractMsg[144], GameOverMsg[88];
- char BlankMsg[32];
- cLEDText TetrisMsg;
- uint8_t DropDelay;
- boolean AttractMode, NextBlock;
- int16_t TotalLines;
- unsigned int HighScore = 0, LastScore;
- uint16_t PlasmaTime, PlasmaShift;
- uint32_t LoopDelayMS, LastLoop;
- void setup()
- {
- Serial.begin(115200);
- SerialBT.begin("ESP32Tetris");
-
- FastLED.addLeds<CHIPSET, LED_PIN, COLOR_ORDER>(leds[0], leds.Size());
- FastLED.setBrightness(200);
- FastLED.clear(true);
- FastLED.show();
- memset(PlayfieldData, 0, sizeof(PlayfieldData));
- memset(PlayfieldMask, 0, sizeof(PlayfieldMask));
- Playfield.Setup(leds.Width(), leds.Height(), PlayfieldData, 1, _3BIT, TetrisColours, PlayfieldMask);
- Playfield.SetPositionFrameMotionOptions(0, 0, 0, 0, 0, 0, 0, 0, 0);
- Sprites.AddSprite(&Playfield);
- memset(CompletedLinesData, 0, sizeof(CompletedLinesData));
- CompletedLines.Setup(leds.Width(), TETRIS_SPR_HEIGHT, CompletedLinesData, 1, _1BIT, CompletedLinesColour, CompletedLinesData);
- CompletedLines.SetPositionFrameMotionOptions(0, 0, 0, 0, 0, 0, 0, 0, 0);
- TetrisMsg.SetFont(MatriseFontData);
- sprintf((char *)BlankMsg, "%.*s", _min(((leds.Height() + TetrisMsg.FontHeight()) / (TetrisMsg.FontHeight() + 1)), (int)sizeof(BlankMsg) - 1), " ");
- sprintf((char *)AttractMsg, "%sTETRIS%sSCORE %u%sHIGH %u%sANY BUTTON TO START%s", BlankMsg, BlankMsg, LastScore, BlankMsg, (int)HighScore, BlankMsg, BlankMsg);
- TetrisMsg.Init(&leds, TetrisMsg.FontWidth() + 1, leds.Height(), (leds.Width() - TetrisMsg.FontWidth()) / 2, 0);
- TetrisMsg.SetBackgroundMode(BACKGND_LEAVE);
- TetrisMsg.SetScrollDirection(SCROLL_UP);
- TetrisMsg.SetTextDirection(CHAR_UP);
- TetrisMsg.SetFrameRate(1);
- TetrisMsg.SetOptionsChangeMode(INSTANT_OPTIONS_MODE);
- TetrisMsg.SetText(AttractMsg, strlen((const char *)AttractMsg));
- AttractMode = true;
- LoopDelayMS = TARGET_FRAME_TIME;
- LastLoop = millis() - LoopDelayMS;
- PlasmaShift = (random8(0, 5) * 32) + 64;
- PlasmaTime = 0;
- }
- void loop()
- {
- if (abs(millis() - LastLoop) >= LoopDelayMS)
- {
- LastLoop = millis();
- FastLED.clear();
- // Fill background with dim plasma
- #define PLASMA_X_FACTOR 24
- #define PLASMA_Y_FACTOR 24
- for (int16_t x=0; x<MATRIX_WIDTH; x++)
- {
- for (int16_t y=0; y<MATRIX_HEIGHT; y++)
- {
- int16_t r = sin16(PlasmaTime) / 256;
- int16_t h = sin16(x * r * PLASMA_X_FACTOR + PlasmaTime) + cos16(y * (-r) * PLASMA_Y_FACTOR + PlasmaTime) + sin16(y * x * (cos16(-PlasmaTime) / 256) / 2);
- leds(x, y) = CHSV((uint8_t)((h / 256) + 128), 255, 64);
- }
- }
- uint16_t OldPlasmaTime = PlasmaTime;
- PlasmaTime += PlasmaShift;
- if (OldPlasmaTime > PlasmaTime)
- PlasmaShift = (random8(0, 5) * 32) + 64;
- if (AttractMode)
- {
- if (currentInput != NONE)
- {
- AttractMode = false;
- memset(PlayfieldData, 0, sizeof(PlayfieldData));
- memset(PlayfieldMask, 0, sizeof(PlayfieldMask));
- Sprites.RemoveSprite(&CurrentBlock);
- LastScore = 0;
- TotalLines = 0;
- DropDelay = INITIAL_DROP_FRAMES;
- CurrentBlock.SetXChange(-1);
- NextBlock = true;
- currentInput = NONE;
- }
- }
- else
- {
- if (Sprites.IsSprite(&CompletedLines)) // We have highlighted complete lines, delay for visual effect
- {
- if (CompletedLines.GetXCounter() > 0)
- CompletedLines.SetXCounter(CompletedLines.GetXCounter() - 1);
- else
- {
- Sprites.RemoveSprite(&CompletedLines);
- // Remove completed lines from playfield sprite
- uint8_t *Data = PlayfieldData;
- uint8_t *Mask = PlayfieldMask;
- uint16_t Mbpl = (MATRIX_WIDTH + 7) / 8;
- uint16_t Dbpl = Mbpl * _3BIT;
- int16_t k;
- for (int16_t i=(MATRIX_HEIGHT-1)*Dbpl,j=(MATRIX_HEIGHT-1)*Mbpl; i>=0; i-=Dbpl,j-=Mbpl)
- {
- for (k=0; k<MATRIX_WIDTH; k+=8)
- {
- if ((uint8_t)(0xff00 >> _min(MATRIX_WIDTH - k, 8)) != Mask[j + (k / 8)])
- break;
- }
- if (k >= MATRIX_WIDTH)
- {
- memmove(&Data[Dbpl], &Data[0], i);
- memset(&Data[0], 0, Dbpl);
- memmove(&Mask[Mbpl], &Mask[0], j);
- memset(&Mask[0], 0, Mbpl);
- i+=Dbpl;
- j+=Mbpl;
- }
- }
- }
- }
- else
- {
- if (CurrentBlock.GetXChange() >= 0) // We have a current block
- {
- // Check for user input
- if ( currentInput == ROTATE )
- {
- currentInput = NONE;
- if ((CurrentBlock.GetCurrentFrame() % 2) == 1)
- {
- if (CurrentBlock.GetXChange() == 0)
- CurrentBlock.m_X = _min(CurrentBlock.m_X, MATRIX_WIDTH - TETRIS_SPR_WIDTH);
- else if ((CurrentBlock.GetXChange() != 3) && (CurrentBlock.GetFlags() & SPRITE_EDGE_X_MAX))
- --CurrentBlock.m_X;
- }
- CurrentBlock.IncreaseFrame();
- Sprites.DetectCollisions(&CurrentBlock);
- if (CurrentBlock.GetFlags() & SPRITE_COLLISION)
- CurrentBlock.DecreaseFrame();
- }
-
- if ( currentInput == LEFT && (! (CurrentBlock.GetFlags() & SPRITE_EDGE_X_MIN)) )
- {
- currentInput = NONE;
- CurrentBlock.m_X--;
- Sprites.DetectCollisions(&CurrentBlock);
- if (CurrentBlock.GetFlags() & SPRITE_COLLISION)
- CurrentBlock.m_X++;
- }
-
- else if ( currentInput == RIGHT && (! (CurrentBlock.GetFlags() & SPRITE_EDGE_X_MAX)) )
- {
- currentInput = NONE;
- CurrentBlock.m_X++;
- Sprites.DetectCollisions(&CurrentBlock);
- if (CurrentBlock.GetFlags() & SPRITE_COLLISION)
- CurrentBlock.m_X--;
- }
-
- if ( currentInput == DOWN )
- {
- currentInput = NONE;
- CurrentBlock.SetYCounter(1);
- }
-
- // Do block checks for bottom or collision
- if (CurrentBlock.GetYCounter() <= 1)
- {
- if (CurrentBlock.GetFlags() & SPRITE_EDGE_Y_MIN)
- NextBlock = true;
- else
- {
- --CurrentBlock.m_Y;
- Sprites.DetectCollisions(&CurrentBlock);
- ++CurrentBlock.m_Y;
- if (CurrentBlock.GetFlags() & SPRITE_COLLISION)
- {
- // Block has collided check for game over
- int16_t MaxY = MATRIX_HEIGHT - 2;
- if ((CurrentBlock.GetCurrentFrame() % 2) == 1)
- {
- if (CurrentBlock.GetXChange() == 0)
- MaxY -= 2;
- else if (CurrentBlock.GetXChange() != 3)
- MaxY -= 1;
- }
- else if (CurrentBlock.GetXChange() == 0)
- ++MaxY;
- if (CurrentBlock.m_Y < MaxY)
- NextBlock = true;
- else
- {
- // Game over
- CurrentBlock.SetYCounter(2); // Stop last block moving down!
- AttractMode = true;
- if (LastScore > HighScore)
- {
- HighScore = LastScore;
- sprintf((char *)GameOverMsg, "%sGAME OVER%sNEW HIGH SCORE %u%s", BlankMsg, BlankMsg, LastScore, BlankMsg);
- }
- else
- sprintf((char *)GameOverMsg, "%sGAME OVER%sSCORE %u%s", BlankMsg, BlankMsg, LastScore, BlankMsg);
- sprintf((char *)AttractMsg, "%sTETRIS%sSCORE %u%sHIGH %u%sANY BUTTON TO START%s", BlankMsg, BlankMsg, LastScore, BlankMsg, HighScore, BlankMsg, BlankMsg);
- TetrisMsg.SetText(GameOverMsg, strlen((char *)GameOverMsg));
- TetrisMsg.SetBackgroundMode(BACKGND_DIMMING, 0x40);
- }
- }
- }
- }
- }
- if (NextBlock) // Start new block
- {
- if (CurrentBlock.GetXChange() >= 0) // We have a current block so add to playfield before creating new block
- {
- Playfield.Combine(CurrentBlock.m_X, CurrentBlock.m_Y, &CurrentBlock);
- Sprites.RemoveSprite(&CurrentBlock);
- // Make completed lines highlight sprite & score
- memset(CompletedLinesData, 0, sizeof(CompletedLinesData));
- CompletedLines.m_Y = -1;
- uint8_t *Mask = PlayfieldMask;
- uint16_t Mbpl = (MATRIX_WIDTH + 7) / 8;
- int16_t j, numlines = 0;
- for (int16_t i=(MATRIX_HEIGHT-1)*Mbpl, y=0; i>=0; i-=Mbpl,++y)
- {
- for (j=0; j<MATRIX_WIDTH; j+=8)
- {
- if ((uint8_t)(0xff00 >> _min(MATRIX_WIDTH - j, 8)) != Mask[i + (j / 8)])
- break;
- }
- if (j >= MATRIX_WIDTH)
- {
- if (CompletedLines.m_Y == -1)
- CompletedLines.m_Y = y;
- memset(&CompletedLinesData[((TETRIS_SPR_HEIGHT - 1) - (y - CompletedLines.m_Y)) * Mbpl], 0xff, Mbpl);
- numlines++;
- }
- }
- if (numlines > 0)
- {
- CompletedLines.SetXCounter(15); // Set delay for highlight display to 15 loops
- Sprites.AddSprite(&CompletedLines);
- }
- LastScore += 1;
- if (numlines == 1)
- LastScore += 4;
- else if (numlines == 2)
- LastScore += 12;
- else if (numlines == 3)
- LastScore += 20;
- else if (numlines == 4)
- LastScore += 40;
- TotalLines += numlines;
- DropDelay = _max(1, INITIAL_DROP_FRAMES - (TotalLines / 5));
- }
- // Start new block
- uint8_t j = random8(sizeof(TetrisSprData) / sizeof(TetrisSprData[0]));
- CurrentBlock.Setup(TETRIS_SPR_WIDTH, TETRIS_SPR_WIDTH, TetrisSprData[j], 4, _3BIT, TetrisColours, TetrisSprMask[j]);
- CurrentBlock.SetPositionFrameMotionOptions((MATRIX_WIDTH/2)-1, MATRIX_HEIGHT, 0, 0, 0, 0, -1, DropDelay, SPRITE_DETECT_COLLISION | SPRITE_DETECT_EDGE);
- CurrentBlock.SetXChange(j);
- Sprites.AddSprite(&CurrentBlock);
- NextBlock = false;
- }
- Sprites.UpdateSprites();
- }
- }
- Sprites.RenderSprites();
- if (AttractMode)
- {
- if (TetrisMsg.UpdateText() == -1)
- {
- TetrisMsg.SetText(AttractMsg, strlen((char *)AttractMsg));
- TetrisMsg.SetBackgroundMode(BACKGND_LEAVE);
- Sprites.RemoveSprite(&CurrentBlock);
- memset(PlayfieldData, 0, sizeof(PlayfieldData));
- memset(PlayfieldMask, 0, sizeof(PlayfieldMask));
- }
- }
- FastLED.show();
- }
- if(SerialBT.available()){
- char keyPress = (char)SerialBT.read();
- switch(keyPress) {
- case 'w':
- currentInput = ROTATE;
- break;
- case 'a':
- currentInput = LEFT;
- break;
- case 's':
- currentInput = DOWN;
- break;
- case 'd':
- currentInput = RIGHT;
- break;
- }
- Serial.println(currentInput);
- }
- }