This shows you the differences between two versions of the page.
pm:prj2023:tmiu:pongrecreation [2023/05/30 02:35] Ovidiu.istrate0211 [Software Design] |
pm:prj2023:tmiu:pongrecreation [2023/05/30 18:48] (current) Ovidiu.istrate0211 [Software Design] |
||
---|---|---|---|
Line 40: | Line 40: | ||
*/ | */ | ||
- | #include <SPI.h> | ||
- | #include <Wire.h> | ||
#include <LiquidCrystal_I2C.h> | #include <LiquidCrystal_I2C.h> | ||
- | const int SW_pin = 9; // digital pin connected to switch output | + | LiquidCrystal_I2C lcd(0x27, 16, 2); // Set the LCD address to 0x27 for a 16x2 display |
- | const int leftJoystick = A0; // analog pin connected to Y output of the left joystick | + | |
- | const int rightJoystick = A2; // analog pin connected to Y output of the right joystick | + | |
- | const unsigned long PADDLE_RATE = 45; | + | //---------------------------------------PINS------------------------------------------------ |
- | const unsigned long BALL_RATE = 0; | + | |
- | const uint8_t PADDLE_HEIGHT = 12; | + | |
- | int player1Score = 0; | + | |
- | int player2Score = 0; | + | |
- | int maxScore = 8; | + | |
- | int buzzerPin = 9; | + | |
- | bool resetBall = false; | + | |
- | LiquidCrystal_I2C lcd(0x27, 16, 2); // Set LCD address and dimensions accordingly | + | const int Player_1_moveButton = A0; // Joystick Pin for Player 1 |
+ | const int Player_2_moveButton = A2; // Joystick Pin for Player 2 | ||
+ | const int ScoreBuzzerPin = 9; | ||
- | void drawCourt(); | + | //---------------------------------------CLASSES------------------------------------------------ |
- | void drawScore(); | + | |
- | uint8_t ball_x = 7, ball_y = 1; | + | class Paddle |
- | uint8_t ball_dir_x = 1, ball_dir_y = 1; | + | { |
- | unsigned long ball_update; | + | public: |
+ | int Paddle_X; | ||
+ | int Paddle_Y; | ||
+ | int Paddle_Length; | ||
- | unsigned long paddle_update; | ||
- | const uint8_t PLAYER2_X = 13; | ||
- | uint8_t player2_y = 1; | ||
- | const uint8_t PLAYER_X = 0; | + | Paddle(int x, int y, int length) |
- | uint8_t player1_y = 1; | + | { |
- | + | Paddle_X = x; | |
- | void setup() { | + | Paddle_Y = y; |
- | lcd.begin(16, 2); | + | Paddle_Length = length; |
- | lcd.clear(); | + | } |
- | unsigned long start = millis(); | + | |
- | pinMode(buzzerPin, OUTPUT); | + | |
- | pinMode(SW_pin, INPUT); | + | |
- | digitalWrite(SW_pin, HIGH); | + | |
- | drawCourt(); | + | |
- | drawScore(); | + | |
- | while (millis() - start < 2000); | + | |
- | + | ||
- | ball_update = millis(); | + | |
- | paddle_update = ball_update; | + | |
- | } | + | |
- | + | ||
- | void loop() { | + | |
- | bool update = false; | + | |
- | unsigned long time = millis(); | + | |
- | if (resetBall) { | + | void PrintPaddle() |
- | if (player1Score == maxScore || player2Score == maxScore) { | + | { |
- | gameOver(); | + | for (int i = 0; i < Paddle_Length; i++) |
- | } else { | + | { |
- | lcd.clear(); | + | lcd.setCursor(Paddle_X, Paddle_Y + i); |
- | ball_x = random(2, 15); | + | lcd.write(byte(0)); |
- | ball_y = random(1, 2); | + | |
- | do { | + | |
- | ball_dir_x = random(-1, 2); | + | |
- | } while (ball_dir_x == 0); | + | |
- | + | ||
- | do { | + | |
- | ball_dir_y = random(-1, 2); | + | |
- | } while (ball_dir_y == 0); | + | |
- | + | ||
- | resetBall = false; | + | |
} | } | ||
} | } | ||
- | if (time > ball_update) { | + | void ClearPaddle() |
- | uint8_t new_x = ball_x + ball_dir_x; | + | { |
- | uint8_t new_y = ball_y + ball_dir_y; | + | for (int i = 0; i < Paddle_Length; i++) |
- | + | { | |
- | // Check if we hit the vertical walls | + | lcd.setCursor(Paddle_X, Paddle_Y + i); |
- | if (new_x == 0 || new_x == 15) { | + | lcd.print(" "); |
- | if (new_x == 0) { | + | |
- | player1Score += 1; | + | |
- | lcd.clear(); | + | |
- | soundPoint(); | + | |
- | resetBall = true; | + | |
- | } else if (new_x == 15) { | + | |
- | player2Score += 1; | + | |
- | lcd.clear(); | + | |
- | soundPoint(); | + | |
- | resetBall = true; | + | |
- | } | + | |
- | ball_dir_x = -ball_dir_x; | + | |
- | new_x += ball_dir_x + ball_dir_x; | + | |
} | } | ||
+ | } | ||
- | // Check if we hit the horizontal walls. | + | void MovePaddleUp() |
- | if (new_y == 0 || new_y == 1) { | + | { |
- | soundBounce(); | + | if (Paddle_Y > 0) |
- | ball_dir_y = -ball_dir_y; | + | { |
- | new_y += ball_dir_y + ball_dir_y; | + | ClearPaddle(); |
+ | Paddle_Y--; | ||
+ | PrintPaddle(); | ||
} | } | ||
+ | } | ||
- | // Check if we hit the player 2 paddle | + | void MovePaddleDown() |
- | if (new_x == PLAYER2_X && new_y >= player2_y && new_y <= player2_y + PADDLE_HEIGHT) { | + | { |
- | soundBounce(); | + | if (Paddle_Y < 1) |
- | ball_dir_x = -ball_dir_x; | + | { |
- | new_x += ball_dir_x + ball_dir_x; | + | ClearPaddle(); |
+ | Paddle_Y++; | ||
+ | PrintPaddle(); | ||
} | } | ||
+ | } | ||
+ | }; | ||
- | // Check if we hit the player 1 paddle | + | class Ball |
- | if (new_x == PLAYER_X && new_y >= player1_y && new_y <= player1_y + PADDLE_HEIGHT) { | + | { |
- | soundBounce(); | + | public: |
- | ball_dir_x = -ball_dir_x; | + | int Ball_X; |
- | new_x += ball_dir_x + ball_dir_x; | + | int Ball_Y; |
- | } | + | int Ball_Velocity_X; |
+ | int Ball_Velocity_Y; | ||
- | lcd.setCursor(ball_x, ball_y); | ||
- | lcd.print(' '); | ||
- | lcd.setCursor(new_x, new_y); | ||
- | lcd.print('*'); | ||
- | ball_x = new_x; | ||
- | ball_y = new_y; | ||
- | ball_update += BALL_RATE; | + | Ball(int x, int y, int velocityX, int velocityY) |
+ | { | ||
+ | Ball_X = x; | ||
+ | Ball_Y = y; | ||
+ | Ball_Velocity_X = velocityX; | ||
+ | Ball_Velocity_Y = velocityY; | ||
+ | } | ||
- | update = true; | + | void PrintBall() |
+ | { | ||
+ | lcd.setCursor(Ball_X, Ball_Y); | ||
+ | lcd.write(byte(1)); | ||
} | } | ||
- | if (time > paddle_update) { | + | void ClearBall() |
- | paddle_update += PADDLE_RATE; | + | { |
+ | lcd.setCursor(Ball_X, Ball_Y); | ||
+ | lcd.print(" "); | ||
+ | } | ||
- | // Player 2 paddle | + | void moveDiagonal() |
- | lcd.setCursor(PLAYER2_X, player2_y); | + | { |
- | lcd.write(0b11111); // Custom character for paddle | + | ClearBall(); |
- | if (analogRead(rightJoystick) < 475) { | + | Ball_X += Ball_Velocity_X; |
- | player2_y -= 1; | + | Ball_Y += Ball_Velocity_Y; |
- | } | + | PrintBall(); |
- | if (analogRead(rightJoystick) > 550) { | + | |
- | player2_y += 1; | + | |
- | } | + | |
- | if (player2_y < 1) player2_y = 1; | + | |
- | if (player2_y + PADDLE_HEIGHT > 2) player2_y = 2 - PADDLE_HEIGHT; | + | |
- | // Player 1 paddle | + | if (Ball_Y == 0 || Ball_Y == 1) |
- | lcd.setCursor(PLAYER_X, player1_y); | + | { |
- | lcd.write(0b11111); // Custom character for paddle | + | Ball_Velocity_Y *= -1; |
- | if (analogRead(leftJoystick) < 475) { | + | |
- | player1_y -= 1; | + | |
} | } | ||
- | if (analogRead(leftJoystick) > 550) { | ||
- | player1_y += 1; | ||
- | } | ||
- | if (player1_y < 1) player1_y = 1; | ||
- | if (player1_y + PADDLE_HEIGHT > 2) player1_y = 2 - PADDLE_HEIGHT; | ||
- | |||
- | update = true; | ||
} | } | ||
+ | }; | ||
- | if (update) { | + | //---------------------------------------OBJECTS------------------------------------------------ |
- | if (player1Score > 0 || player2Score > 0) { | + | |
- | drawScore(); | + | Paddle player1(0, 0, 2); // Creating Object for Player 1 Paddle |
- | } | + | Paddle player2(0, 1, 2); // Creating Object for Player 2 Paddle |
- | if (player1Score == maxScore || player2Score == maxScore) { | + | Ball ball(7, 1, 1, 1); // Creating Object for Ball |
- | gameOver(); | + | |
- | } | + | //---------------------------------------SETUP------------------------------------------------ |
- | } | + | |
+ | void setup() { | ||
+ | lcd.init(); // Initialize the LCD | ||
+ | lcd.backlight(); // Turn on the backlight | ||
+ | |||
+ | pinMode(Player_1_moveButton, INPUT); | ||
+ | pinMode(Player_2_moveButton, INPUT); | ||
+ | pinMode(ScoreBuzzerPin, OUTPUT); | ||
+ | |||
+ | player1.PrintPaddle(); | ||
+ | player2.PrintPaddle(); | ||
+ | ball.PrintBall(); | ||
+ | |||
+ | ShowStartingScreen(); | ||
} | } | ||
- | void drawCourt() { | + | //---------------------------------------SCOREBOARD------------------------------------------------ |
+ | |||
+ | void PrintScoreboard(int player1Score, int player2Score) | ||
+ | { | ||
+ | lcd.clear(); | ||
lcd.setCursor(0, 0); | lcd.setCursor(0, 0); | ||
- | lcd.print("|"); | + | lcd.print("P1: "); |
- | lcd.setCursor(0, 1); | + | lcd.print(player1Score); |
- | lcd.print("|"); | + | |
- | lcd.setCursor(15, 0); | + | |
- | lcd.print("|"); | + | |
- | lcd.setCursor(15, 1); | + | |
- | lcd.print("|"); | + | |
- | } | + | |
- | void drawScore() { | ||
lcd.setCursor(6, 0); | lcd.setCursor(6, 0); | ||
+ | lcd.print("P2: "); | ||
lcd.print(player2Score); | lcd.print(player2Score); | ||
- | lcd.setCursor(9, 0); | + | |
- | lcd.print("-"); | + | delay(500); // Display the scoreboard for 0.5 seconds |
- | lcd.setCursor(12, 0); | + | lcd.clear(); |
- | lcd.print(player1Score); | + | |
} | } | ||
- | void gameOver() { | + | //---------------------------------------SCREENS------------------------------------------------ |
+ | |||
+ | void ShowStartingScreen() | ||
+ | { | ||
lcd.clear(); | lcd.clear(); | ||
- | if (player1Score > player2Score) { | + | lcd.setCursor(3, 0); |
- | lcd.setCursor(2, 0); | + | lcd.print("Pong Game"); |
- | lcd.print("Player 1 won"); | + | |
- | } else { | + | |
- | lcd.setCursor(2, 0); | + | |
- | lcd.print("Player 2 won"); | + | |
- | } | + | |
delay(2000); | delay(2000); | ||
- | player2Score = player1Score = 0; | + | lcd.clear(); |
- | + | ||
- | unsigned long start = millis(); | + | |
- | while (millis() - start < 2000); | + | |
- | ball_update = millis(); | + | |
- | paddle_update = ball_update; | + | |
- | resetBall = true; | + | |
} | } | ||
- | void soundBounce() { | + | void ShowGameOverScreen() |
- | tone(buzzerPin, 1000, 20); | + | { |
+ | lcd.clear(); | ||
+ | lcd.setCursor(4, 0); | ||
+ | lcd.print("Game Over"); | ||
+ | delay(2000); | ||
+ | lcd.clear(); | ||
+ | } | ||
+ | void PlayScoreSound() { | ||
+ | tone(ScoreBuzzerPin, 1000, 200); // Play a sound for 200ms at a frequency of 1000Hz | ||
+ | delay(200); // Wait for 200ms to avoid overlapping sounds | ||
} | } | ||
- | void soundPoint() { | + | //---------------------------------------LOOP------------------------------------------------ |
- | tone(buzzerPin, 1500, 200); | + | |
- | delay(200); | + | void loop() |
- | tone(buzzerPin, 2000, 200); | + | { |
- | delay(200); | + | // Player 1 controls |
- | tone(buzzerPin, 2500, 200); | + | if (analogRead(Player_1_moveButton) < 500) |
- | delay(200); | + | { |
+ | player1.MovePaddleUp(); | ||
+ | } | ||
+ | else if (analogRead(Player_1_moveButton) > 1500) | ||
+ | { | ||
+ | player1.MovePaddleDown(); | ||
+ | } | ||
+ | |||
+ | // Player 2 controls | ||
+ | if (analogRead(Player_2_moveButton) < 500) | ||
+ | { | ||
+ | player2.MovePaddleUp(); | ||
+ | } | ||
+ | else if (analogRead(Player_2_moveButton) > 1500) | ||
+ | { | ||
+ | player2.MovePaddleDown(); | ||
+ | } | ||
+ | |||
+ | // Ball movement | ||
+ | ball.moveDiagonal(); | ||
+ | |||
+ | // Check if a point is scored | ||
+ | static int player1Score = 0; | ||
+ | static int player2Score = 0; | ||
+ | |||
+ | if (ball.Ball_X == 15) // Replace with actual condition for player 1 scoring | ||
+ | { | ||
+ | player1Score++; | ||
+ | PrintScoreboard(player1Score, player2Score); | ||
+ | |||
+ | if (player1Score >= 8 || player2Score >= 8) | ||
+ | { | ||
+ | |||
+ | ShowGameOverScreen(); | ||
+ | player1Score = 0; | ||
+ | player2Score = 0; | ||
+ | ball.ClearBall(); | ||
+ | ball = Ball(7, 1, 1, 1); // Reset the ball position | ||
+ | ball.PrintBall(); | ||
+ | ShowStartingScreen(); | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | PlayScoreSound(); | ||
+ | ball.ClearBall(); | ||
+ | ball = Ball(7, 1, 1, 1); // Reset the ball position | ||
+ | ball.PrintBall(); | ||
+ | } | ||
+ | } | ||
+ | else if (ball.Ball_X == 0) // Replace with actual condition for player 2 scoring | ||
+ | { | ||
+ | player2Score++; | ||
+ | PrintScoreboard(player1Score, player2Score); | ||
+ | |||
+ | if (player1Score >= 8 || player2Score >= 8) | ||
+ | { | ||
+ | PlayScoreSound(); | ||
+ | ShowGameOverScreen(); | ||
+ | player1Score = 0; | ||
+ | player2Score = 0; | ||
+ | ball.ClearBall(); | ||
+ | ball = Ball(7, 1, 1, 1); // Reset the ball position | ||
+ | ball.PrintBall(); | ||
+ | ShowStartingScreen(); | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | ball.ClearBall(); | ||
+ | ball = Ball(7, 1, 1, 1); // Reset the ball position | ||
+ | ball.PrintBall(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | // Delay for smoother gameplay | ||
+ | delay(150); | ||
} | } | ||
+ | |||
</note> | </note> |