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> | ||