#include /** * Player 1: x = 0 * Player 2: x = X_MAX-1 */ #define PIN_LED_MATRIX 2 #define PIN_JOYSTICK_1_BUTTON 6 #define PIN_JOYSTICK_2_BUTTON 7 #define PIN_PIEZO 11 #define PIN_JOYSTICK_1_Y A0 #define PIN_JOYSTICK_2_Y A1 #define JOYSTICK_OFFSET_MIN 200 #define JOYSTICK_OFFSET_MAX 700 #define DEBOUNCE_TIME 300 // in ms #define X_MAX 10 #define Y_MAX 20 #define GAME_DELAY 80 // in ms #define BALL_DELAY_MAX 350 // in ms #define BALL_DELAY_MIN 50 // in ms #define BALL_DELAY_STEP 5 // in ms #define PLAYER_AMOUNT 2 #define PLAYER_1 0 #define PLAYER_2 1 #define PADDLE_WIDTH 3 #define PADDLE_MOVE_NONE 0 #define PADDLE_MOVE_UP 1 #define PADDLE_MOVE_DOWN 2 #define LED_TYPE_OFF 1 #define LED_TYPE_PADDLE 2 #define LED_TYPE_BALL 3 #define LED_TYPE_BALL_RED 4 #define TONE_PLAYER 1 #define TONE_WALL 2 #define TONE_BUZZ 3 #define GAME_STATE_RUNNING 1 #define GAME_STATE_END 2 #define GAME_STATE_INIT 3 #include struct Coords { byte x; byte y; }; Adafruit_NeoPixel pixels = Adafruit_NeoPixel(X_MAX * Y_MAX, PIN_LED_MATRIX, NEO_GRB + NEO_KHZ800); bool buttonPressed = false; byte gameState; byte joystickPins[PLAYER_AMOUNT] = {PIN_JOYSTICK_1_Y, PIN_JOYSTICK_2_Y}; Coords paddles[PLAYER_AMOUNT][PADDLE_WIDTH]; Coords ball; int ballMovement[2]; unsigned int ballDelay; unsigned long lastDrawUpdate = 0; unsigned long lastBallUpdate = 0; unsigned long lastButtonClick = 0; void setup() { pinMode(PIN_JOYSTICK_1_Y, INPUT); pinMode(PIN_JOYSTICK_1_BUTTON, INPUT_PULLUP); pinMode(PIN_JOYSTICK_2_Y, INPUT); pinMode(PIN_JOYSTICK_2_BUTTON, INPUT_PULLUP); pixels.begin(); resetLEDs(); gameState = GAME_STATE_END; } void loop() { switch(gameState) { case GAME_STATE_INIT: initGame(); break; case GAME_STATE_RUNNING: updateBall(); updateGame(); break; case GAME_STATE_END: if (isButtonPressed()) { gameState = GAME_STATE_INIT; } break; } } void initGame() { resetLEDs(); lastButtonClick = millis(); ball.x = 1; ball.y = (Y_MAX/2) - (PADDLE_WIDTH/2) + 1; ballMovement[0] = 1; ballMovement[1] = -1; ballDelay = BALL_DELAY_MAX; for(byte i=0; i BALL_DELAY_MIN) { ballDelay -= BALL_DELAY_STEP; } } ball.x += ballMovement[0]; ball.y += ballMovement[1]; if (ball.x <=0 || ball.x >= X_MAX-1) { endGame(); return; } if (ball.y <= 0 || ball.y >= Y_MAX-1) { ballMovement[1] *= -1; playTone(TONE_WALL); } toggleLed(ball.x, ball.y, LED_TYPE_BALL); pixels.show(); } void endGame() { gameState = GAME_STATE_END; toggleLed(ball.x, ball.y, LED_TYPE_BALL_RED); pixels.show(); playTone(TONE_BUZZ); } void updateGame() { if ((millis() - lastDrawUpdate) < GAME_DELAY) { return; } lastDrawUpdate = millis(); // turn off paddle LEDs for(byte p=0; p 0) { for(byte i=0; i JOYSTICK_OFFSET_MAX) { if (playerId == PLAYER_2) { return PADDLE_MOVE_UP; } else { return PADDLE_MOVE_DOWN; } } return PADDLE_MOVE_NONE; } bool isButtonPressed() { if ((millis() - lastButtonClick) < DEBOUNCE_TIME) { return false; } if (digitalRead(PIN_JOYSTICK_1_BUTTON) == LOW) { lastButtonClick = millis(); return true; } if (digitalRead(PIN_JOYSTICK_2_BUTTON) == LOW) { lastButtonClick = millis(); return true; } return false; } void resetLEDs() { for(byte i=0; i