Initial Version
This commit is contained in:
parent
57963ca706
commit
e29a23cc02
3 changed files with 363 additions and 0 deletions
46
VSCode/README
Normal file
46
VSCode/README
Normal file
|
@ -0,0 +1,46 @@
|
|||
|
||||
This directory is intended for project specific (private) libraries.
|
||||
PlatformIO will compile them to static libraries and link into executable file.
|
||||
|
||||
The source code of each library should be placed in a an own separate directory
|
||||
("lib/your_library_name/[here are source files]").
|
||||
|
||||
For example, see a structure of the following two libraries `Foo` and `Bar`:
|
||||
|
||||
|--lib
|
||||
| |
|
||||
| |--Bar
|
||||
| | |--docs
|
||||
| | |--examples
|
||||
| | |--src
|
||||
| | |- Bar.c
|
||||
| | |- Bar.h
|
||||
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
|
||||
| |
|
||||
| |--Foo
|
||||
| | |- Foo.c
|
||||
| | |- Foo.h
|
||||
| |
|
||||
| |- README --> THIS FILE
|
||||
|
|
||||
|- platformio.ini
|
||||
|--src
|
||||
|- main.c
|
||||
|
||||
and a contents of `src/main.c`:
|
||||
```
|
||||
#include <Foo.h>
|
||||
#include <Bar.h>
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
PlatformIO Library Dependency Finder will find automatically dependent
|
||||
libraries scanning project source files.
|
||||
|
||||
More information about PlatformIO Library Dependency Finder
|
||||
- https://docs.platformio.org/page/librarymanager/ldf.html
|
302
VSCode/main.cpp
Normal file
302
VSCode/main.cpp
Normal file
|
@ -0,0 +1,302 @@
|
|||
#include <Arduino.h>
|
||||
|
||||
/**
|
||||
* 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 <Adafruit_NeoPixel.h>
|
||||
|
||||
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<PADDLE_WIDTH; i++) {
|
||||
paddles[PLAYER_1][i].x = 0;
|
||||
paddles[PLAYER_1][i].y = (Y_MAX/2) - (PADDLE_WIDTH/2) + i;
|
||||
paddles[PLAYER_2][i].x = X_MAX - 1;
|
||||
paddles[PLAYER_2][i].y = paddles[PLAYER_1][i].y;
|
||||
}
|
||||
|
||||
gameState = GAME_STATE_RUNNING;
|
||||
}
|
||||
|
||||
void updateBall()
|
||||
{
|
||||
bool hitBall = false;
|
||||
if ((millis() - lastBallUpdate) < ballDelay) {
|
||||
return;
|
||||
}
|
||||
lastBallUpdate = millis();
|
||||
toggleLed(ball.x, ball.y, LED_TYPE_OFF);
|
||||
|
||||
// collision detection for player 1
|
||||
if (ballMovement[0] == -1 && ball.x == 1) {
|
||||
for(byte i=0; i<PADDLE_WIDTH; i++) {
|
||||
if (paddles[PLAYER_1][i].y == ball.y) {
|
||||
hitBall = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// collision detection for player 2
|
||||
if (ballMovement[0] == 1 && ball.x == X_MAX-2) {
|
||||
for(byte i=0; i<PADDLE_WIDTH; i++) {
|
||||
if (paddles[PLAYER_2][i].y == ball.y) {
|
||||
hitBall = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hitBall == true) {
|
||||
ballMovement[0] *= -1;
|
||||
playTone(TONE_PLAYER);
|
||||
if (ballDelay > 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<PLAYER_AMOUNT; p++) {
|
||||
for(byte i=0; i<PADDLE_WIDTH; i++) {
|
||||
toggleLed(paddles[p][i].x, paddles[p][i].y, LED_TYPE_OFF);
|
||||
}
|
||||
}
|
||||
|
||||
// move paddles
|
||||
for(byte p=0; p<PLAYER_AMOUNT; p++) {
|
||||
byte movement = getPlayerMovement(p);
|
||||
if (movement == PADDLE_MOVE_UP && paddles[p][PADDLE_WIDTH-1].y < (Y_MAX-1)) {
|
||||
for(byte i=0; i<PADDLE_WIDTH; i++) {
|
||||
paddles[p][i].y++;
|
||||
}
|
||||
}
|
||||
if (movement == PADDLE_MOVE_DOWN && paddles[p][0].y > 0) {
|
||||
for(byte i=0; i<PADDLE_WIDTH; i++) {
|
||||
paddles[p][i].y--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// show paddle LEDs
|
||||
for(byte p=0; p<PLAYER_AMOUNT; p++) {
|
||||
for(byte i=0; i<PADDLE_WIDTH; i++) {
|
||||
toggleLed(paddles[p][i].x, paddles[p][i].y, LED_TYPE_PADDLE);
|
||||
}
|
||||
}
|
||||
pixels.show();
|
||||
}
|
||||
|
||||
byte getPlayerMovement(byte playerId)
|
||||
{
|
||||
int value = analogRead(joystickPins[playerId]);
|
||||
if (value < JOYSTICK_OFFSET_MIN) {
|
||||
if (playerId == PLAYER_2) {
|
||||
return PADDLE_MOVE_DOWN;
|
||||
} else {
|
||||
return PADDLE_MOVE_UP;
|
||||
}
|
||||
} else if (value > 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<X_MAX*Y_MAX; i++) {
|
||||
pixels.setPixelColor(i, pixels.Color(0, 0, 0));
|
||||
}
|
||||
pixels.show();
|
||||
}
|
||||
|
||||
void toggleLed(byte x, byte y, byte type)
|
||||
{
|
||||
byte ledIndex = y * X_MAX + x;
|
||||
uint32_t color;
|
||||
|
||||
switch(type) {
|
||||
case LED_TYPE_PADDLE:
|
||||
color = pixels.Color(0, 8, 8);
|
||||
break;
|
||||
case LED_TYPE_BALL_RED:
|
||||
color = pixels.Color(12, 0, 0);
|
||||
break;
|
||||
case LED_TYPE_BALL:
|
||||
color = pixels.Color(0, 10, 0);
|
||||
break;
|
||||
case LED_TYPE_OFF:
|
||||
color = pixels.Color(0, 0, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
pixels.setPixelColor(ledIndex, color);
|
||||
}
|
||||
|
||||
void playTone(byte type)
|
||||
{
|
||||
switch(type) {
|
||||
case TONE_PLAYER:
|
||||
tone(PIN_PIEZO, 440, 50);
|
||||
break;
|
||||
case TONE_WALL:
|
||||
tone(PIN_PIEZO, 550, 50);
|
||||
break;
|
||||
case TONE_BUZZ:
|
||||
for(byte i=0; i<20; i++) {
|
||||
tone(PIN_PIEZO, 220-i*10, 50);
|
||||
delay(50);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
15
VSCode/platformio.ini
Normal file
15
VSCode/platformio.ini
Normal file
|
@ -0,0 +1,15 @@
|
|||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[env:uno]
|
||||
platform = atmelavr
|
||||
board = uno
|
||||
framework = arduino
|
||||
lib_deps = adafruit/Adafruit NeoPixel@^1.10.4
|
Loading…
Reference in a new issue