Files
2026-04-13 14:29:21 +00:00

2362 lines
86 KiB
C++

#include <iostream>
#include <string>
#include <conio.h>
#include <thread>
#include <chrono>
#include <fstream>
#include <windows.h>
#include <cmath>
#include <vector>
#include <ctime>
#include <iomanip>
#include <mmsystem.h>
#pragma comment(lib, "winmm.lib")
using namespace std;
// ==================== ثابت‌های بازی ====================
const int BOARD_WIDTH = 51;
const int BOARD_HEIGHT = 25;
const int BRICK_ROWS = 5;
const int BRICK_COLS = 10;
const float BALL_SPEED = 0.5f;
const float PADDLE_SPEED = 4.0f;
const int MAX_POWERUPS = 10;
const float POWERUP_SPEED = 0.2f;
const float MIN_PADDLE_WIDTH = 2.0f;
const float MAX_PADDLE_WIDTH = 20.0f;
const float PADDLE_CHANGE = 2.0f;
const float INITIAL_PADDLE_Y = BOARD_HEIGHT - 2.0f;
const float INITIAL_PADDLE_X = BOARD_WIDTH / 2.0f - 5.0f;
const float INITIAL_BALL_X = INITIAL_PADDLE_X + 5.0f;
const float INITIAL_BALL_Y = INITIAL_PADDLE_Y - 0.5f;
// حالت‌های بازی
const int GAME_MODE_SIMPLE = 0;
const int GAME_MODE_ADVANCED = 1;
// انواع پاورآپ
const int POWERUP_BOMB = 0;
const int POWERUP_HEART = 1;
// ==================== رنگ‌های ANSI ====================
const string RESET = "\033[0m";
const string BOLD = "\033[1m";
const string BLUE = "\033[34m";
const string RED = "\033[31m";
const string WHITE = "\033[37m";
const string GOLD = "\033[93m";
const string YELLOW = "\033[33m";
const string GREEN = "\033[32m";
const string MAGENTA = "\033[35m";
const string CYAN = "\033[36m";
const string BRIGHT_RED = "\033[91m";
const string BRIGHT_GREEN = "\033[92m";
const string BRIGHT_YELLOW = "\033[93m";
const string BRIGHT_BLUE = "\033[94m";
const string BRIGHT_MAGENTA = "\033[95m";
const string BRIGHT_CYAN = "\033[96m";
const string PURPLE = "\033[38;5;129m";
const string ORANGE = "\033[38;5;208m";
const string PINK = "\033[38;5;201m";
const string BROWN = "\033[38;5;94m";
// رنگ‌های آجرها
const string BRICK_COLOR_RED = "\033[38;5;196m";
const string BRICK_COLOR_ORANGE = "\033[38;5;208m";
const string BRICK_COLOR_YELLOW = "\033[38;5;226m";
const string BRICK_COLOR_GREEN = "\033[38;5;46m";
const string BRICK_COLOR_BLUE = "\033[38;5;27m";
const string BRICK_COLOR_PURPLE = "\033[38;5;129m";
const string BRICK_COLOR_PINK = "\033[38;5;201m";
const string BRICK_COLOR_CYAN = "\033[38;5;51m";
// ==================== ساختارهای بازی ====================
struct Ball
{
float x, y;
float vx, vy;
float radius;
};
struct Paddle
{
float x, y;
float width, height;
float speed;
};
struct Brick
{
float x, y;
float width, height;
bool visible;
};
struct Powerup
{
float x, y;
float vy;
int type;
bool active;
bool collected;
};
struct GameRecord
{
string playerName;
string score;
string gameModeStr;
string result;
string Date;
string Time;
};
// ==================== متغیرهای سراسری ====================
Ball ball;
Paddle paddle;
Brick bricks[BRICK_ROWS][BRICK_COLS];
Powerup powerups[MAX_POWERUPS];
int score = 0;
int lives = 3;
int gameMode = GAME_MODE_SIMPLE;
bool gameOver = false;
bool gameStarted = false;
bool isPaused = false;
string currentPlayerName = "";
vector<string> screenBuffer;
// ==================== متغیرهای منو ====================
int currentOption = 0;
int currentSettingsOption = 0;
int currentHelpOption = 0;
int currentBallOption = 0;
int currentPaddleOption = 0;
string selectedBallType = "●";
string selectedPaddleType = "■";
bool inBallSettings = false;
bool inPaddleSettings = false;
// ==================== آرایه‌های منو ====================
string mainMenuOptions[] = {"NEW GAME", "LOAD GAME", "HELP", "GAME HISTORY", "SETTINGS", "EXIT"};
string pauseMenuOptions[] = {"RESUME", "RESTART", "MENU"};
string settingsOptions[] = {"BALL TYPE", "PADDLE TYPE", "BACK TO MENU"};
string helpOptions[] = {"CONTROLS", "ABOUT GAME", "BACK TO MENU"};
string ballTypes[] = {"◉", "✿", "✪", "✷", "✯", "✧", "●", "◍"};
string paddleTypes[] = {"✷", "❥", "▼", "▽", "□", "■", "◗", "●"};
// ==================== متغیرهای صدا ====================
bool soundsLoaded = false;
// ==================== اعلان توابع مدیریت صدا ====================
void preloadSounds();
void playSound(const string &filename);
void playBrickSound();
void playWallSound();
void playVictorySound();
void playGameOverSound();
void playLoseBallSound();
// ==================== اعلان توابع اصلی بازی ====================
void runGame();
void newGame();
void loadGame();
void saveGame();
void clearSavedGame();
void initializeBricks();
void resetBallAndPaddle();
void updateBall(float deltaTime);
void checkPaddleCollision();
void checkBrickCollision();
void checkWallCollision();
void activatePowerUps(float deltaTime);
void powerUp(float x, float y);
// ==================== اعلان توابع رندر و نمایش ====================
void initScreenBuffer();
void clearScreenBuffer();
void renderToBuffer();
void renderWithColorsOptimized();
void setCursorPosition(int x, int y);
void hideCursor();
void clearMenuArea();
// ==================== اعلان توابع منو ====================
void printMenu();
void menuMove();
void pauseMenu();
void pauseMove();
void resume();
void restart();
void showSettings();
void settingsMove();
void showBallSettings();
void ballSettingsMove();
void showPaddleSettings();
void paddleSettingsMove();
void selectGameMode();
void printLoading();
void showHelp();
void helpMove();
void aboutGame();
void controls();
// ==================== اعلان توابع UI و گرافیک ====================
void printVictory();
void printGameOver();
void printExit(int selected);
void exitMove();
void showGameHistory();
void saveGameHistory(const string &result);
// ==================== اعلان توابع تنظیمات ====================
void saveSettings();
void loadSettings();
// ==================== توابع مدیریت صدا ====================
void preloadSounds()
{
if (soundsLoaded)
return;
string sounds[] = {
"brick.wav",
"wall.wav",
"loseball.wav",
"Victory.wav",
"GameOver.wav"};
for (int i = 0; i < 5; i++)
{
PlaySound(sounds[i].c_str(), NULL, SND_FILENAME | SND_ASYNC | SND_NOSTOP);
Sleep(20);
}
PlaySound(NULL, NULL, 0);
soundsLoaded = true;
}
void playSound(const string &filename)
{
PlaySound(filename.c_str(), NULL, SND_FILENAME | SND_ASYNC | SND_NODEFAULT);
}
void playBrickSound() { playSound("brick.wav"); }
void playWallSound() { playSound("wall.wav"); }
void playVictorySound() { playSound("Victory.wav"); }
void playGameOverSound() { playSound("GameOver.wav"); }
void playLoseBallSound() { playSound("loseball.wav"); }
// ==================== توابع اصلی بازی ====================
void initializeBricks()
{
for (int i = 0; i < BRICK_ROWS; i++)
{
for (int j = 0; j < BRICK_COLS; j++)
{
bricks[i][j].x = 1.0f + j * 5.0f; // فاصله افقی آجرها
bricks[i][j].y = 1.0f + i * 2.0f; // فاصله عمودی آجرها
bricks[i][j].width = 4.0f;
bricks[i][j].height = 1.0f;
bricks[i][j].visible = true;
}
}
}
void resetBallAndPaddle()
{
paddle.x = INITIAL_PADDLE_X;
paddle.y = INITIAL_PADDLE_Y;
ball.x = INITIAL_BALL_X;
ball.y = INITIAL_BALL_Y;
ball.vx = BALL_SPEED;
ball.vy = -BALL_SPEED;
}
void updateBall(float deltaTime)
{
ball.x += ball.vx * deltaTime * 15.0f; // 15 ضریب برای بهتر شدن سرعت در کنسول
ball.y += ball.vy * deltaTime * 15.0f;
float maxSpeed = BALL_SPEED * 2.0f;
float currentSpeed = sqrt(ball.vx * ball.vx + ball.vy * ball.vy);
// ایجاد محدودیت برای سرعت توپ به منظور کنترل بهتر
if (currentSpeed > maxSpeed)
{
float scale = maxSpeed / currentSpeed;
ball.vx *= scale;
ball.vy *= scale;
}
float minSpeed = BALL_SPEED * 0.8f;
if (currentSpeed < minSpeed && currentSpeed > 0)
{
float scale = minSpeed / currentSpeed;
ball.vx *= scale;
ball.vy *= scale;
}
}
void checkPaddleCollision()
{
bool isInVerticalRange = (ball.y + ball.radius >= paddle.y) &&
(ball.y - ball.radius <= paddle.y + paddle.height);
bool isInHorizontalRange = (ball.x >= paddle.x) &&
(ball.x <= paddle.x + paddle.width);
if (isInVerticalRange && isInHorizontalRange)
{
float relativeHitPoint = (ball.x - paddle.x) / paddle.width;
const float MAX_ANGLE = 0.7854f; // 45 درجه
float angle = (relativeHitPoint - 0.5f) * MAX_ANGLE * 2.0f;
float totalSpeed = sqrt(ball.vx * ball.vx + ball.vy * ball.vy);
if (totalSpeed < BALL_SPEED)
{
totalSpeed = BALL_SPEED;
}
ball.vx = totalSpeed * sin(angle);
ball.vy = -abs(totalSpeed * cos(angle));
ball.y = paddle.y - ball.radius - 0.1f;
playWallSound();
}
}
void checkBrickCollision()
{
for (int i = 0; i < BRICK_ROWS; i++)
{
for (int j = 0; j < BRICK_COLS; j++)
{
if (!bricks[i][j].visible)
continue;
Brick &brick = bricks[i][j];
bool overlapX = (ball.x + ball.radius >= brick.x) &&
(ball.x - ball.radius <= brick.x + brick.width);
bool overlapY = (ball.y + ball.radius >= brick.y) &&
(ball.y - ball.radius <= brick.y + brick.height);
if (overlapX && overlapY)
{
brick.visible = false;
score += 10;
playBrickSound();
if (gameMode == GAME_MODE_ADVANCED && (rand() % 100) < 70) // احتمال 70 درصد
{
// ایجاد پاورآپ
for (int k = 0; k < MAX_POWERUPS; k++)
{
if (!powerups[k].active)
{
powerups[k].x = brick.x + brick.width / 2;
powerups[k].y = brick.y + brick.height / 2;
powerups[k].vy = POWERUP_SPEED;
powerups[k].type = rand() % 2; // بمب یا قلب
powerups[k].active = true;
powerups[k].collected = false;
break;
}
}
}
// بررسی عمق و جهت برخورد توپ با آجر
float overlapLeft = (ball.x + ball.radius) - brick.x;
float overlapRight = (brick.x + brick.width) - (ball.x - ball.radius);
float overlapTop = (ball.y + ball.radius) - brick.y;
float overlapBottom = (brick.y + brick.height) - (ball.y - ball.radius);
float minOverlapX = min(overlapLeft, overlapRight);
float minOverlapY = min(overlapTop, overlapBottom);
if (minOverlapX < minOverlapY)
{
ball.vx = -ball.vx;
if (overlapLeft < overlapRight)
{
ball.x = brick.x - ball.radius - 0.1f; // 0.1 برای ایجاد فاصله بین توپ و آجر و جلوگیری از همپوشانی آنها در فریم بعدی
}
else
{
ball.x = brick.x + brick.width + ball.radius + 0.1f;
}
}
else
{
ball.vy = -ball.vy;
if (overlapTop < overlapBottom)
{
ball.y = brick.y - ball.radius - 0.1f;
}
else
{
ball.y = brick.y + brick.height + ball.radius + 0.1f;
}
}
float speedIncrease = 1.01f;
ball.vx *= speedIncrease;
ball.vy *= speedIncrease;
}
}
}
}
void checkWallCollision()
{
// دیوار چپ
if (ball.x - ball.radius <= 1.0f)
{
ball.vx = abs(ball.vx);
ball.x = 1.0f + ball.radius + 0.1f;
playWallSound();
}
// دیوار راست
if (ball.x + ball.radius >= BOARD_WIDTH - 1.0f)
{
ball.vx = -abs(ball.vx);
ball.x = BOARD_WIDTH - 1.0f - ball.radius - 0.1f;
playWallSound();
}
// دیوار بالا
if (ball.y - ball.radius <= 1.0f)
{
ball.vy = abs(ball.vy);
ball.y = 1.0f + ball.radius + 0.1f;
playWallSound();
}
// دیوار پایین
if (ball.y > BOARD_HEIGHT)
{
lives--;
playLoseBallSound();
if (lives > 0)
{
resetBallAndPaddle();
gameStarted = false;
}
else
{
gameOver = true;
}
}
}
void activatePowerUps(float deltaTime)
{
for (int i = 0; i < MAX_POWERUPS; i++)
{
if (powerups[i].active && !powerups[i].collected)
{
powerups[i].y += powerups[i].vy;
bool hitPaddle = (powerups[i].y >= paddle.y) &&
(powerups[i].y <= paddle.y + paddle.height) &&
(powerups[i].x >= paddle.x) &&
(powerups[i].x <= paddle.x + paddle.width);
if (hitPaddle)
{
powerups[i].collected = true;
if (powerups[i].type == POWERUP_BOMB)
{
paddle.width = max(MIN_PADDLE_WIDTH, paddle.width - PADDLE_CHANGE); // برای کنترل طول راکت محدوده ای در نظر گرفته شده
}
else if (powerups[i].type == POWERUP_HEART)
{
paddle.width = min(MAX_PADDLE_WIDTH, paddle.width + PADDLE_CHANGE);
}
}
if (powerups[i].y > BOARD_HEIGHT)
{
powerups[i].active = false;
}
}
}
}
// ==================== توابع رندر ====================
void initScreenBuffer()
{
screenBuffer.resize(BOARD_HEIGHT + 3);
for (int i = 0; i < screenBuffer.size(); i++)
{
screenBuffer[i].resize(BOARD_WIDTH, ' ');
}
}
void clearScreenBuffer()
{
for (int i = 0; i < screenBuffer.size(); i++)
{
for (int j = 0; j < BOARD_WIDTH; j++)
{
screenBuffer[i][j] = ' ';
}
}
}
void setCursorPosition(int x, int y)
{
COORD coord;
coord.X = x;
coord.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
void hideCursor()
{
CONSOLE_CURSOR_INFO cursorInfo;
GetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursorInfo);
cursorInfo.bVisible = false;
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursorInfo);
}
void renderToBuffer()
{
clearScreenBuffer();
// کادر
for (int i = 0; i < BOARD_WIDTH; i++)
{
screenBuffer[0][i] = '-';
screenBuffer[BOARD_HEIGHT - 1][i] = '-';
}
for (int i = 1; i < BOARD_HEIGHT - 1; i++)
{
screenBuffer[i][0] = '|';
screenBuffer[i][BOARD_WIDTH - 1] = '|';
}
// راکت
int paddleYPos = (int)paddle.y;
if (paddleYPos >= 0 && paddleYPos < BOARD_HEIGHT)
{
int paddleStart = max(1, (int)paddle.x);
int paddleEnd = min(BOARD_WIDTH - 2, (int)(paddle.x + paddle.width));
for (int i = paddleStart; i <= paddleEnd; i++)
{
if (i >= 1 && i < BOARD_WIDTH - 1)
{
screenBuffer[paddleYPos][i] = '=';
}
}
}
// توپ
int ballX = (int)ball.x;
int ballY = (int)ball.y;
if (ballX >= 1 && ballX < BOARD_WIDTH - 1 && ballY >= 1 && ballY < BOARD_HEIGHT - 1)
{
screenBuffer[ballY][ballX] = 'O';
}
// آجرها
for (int i = 0; i < BRICK_ROWS; i++)
{
for (int j = 0; j < BRICK_COLS; j++)
{
if (bricks[i][j].visible)
{
int brickX = (int)bricks[i][j].x;
int brickY = (int)bricks[i][j].y;
int brickWidth = (int)bricks[i][j].width;
brickX = max(1, brickX);
brickY = max(1, brickY);
for (int k = 0; k < brickWidth && brickX + k < BOARD_WIDTH - 1; k++)
{
if (brickY >= 1 && brickY < BOARD_HEIGHT - 1)
{
screenBuffer[brickY][brickX + k] = 'B';
}
}
}
}
}
// پاورآپ‌ها
if (gameMode == GAME_MODE_ADVANCED)
{
for (int i = 0; i < MAX_POWERUPS; i++)
{
if (powerups[i].active && !powerups[i].collected)
{
int px = (int)powerups[i].x;
int py = (int)powerups[i].y;
if (px >= 1 && px < BOARD_WIDTH - 1 && py >= 1 && py < BOARD_HEIGHT - 1)
{
if (powerups[i].type == POWERUP_BOMB)
{
screenBuffer[py][px] = 'X';
}
else
{
screenBuffer[py][px] = '+';
}
}
}
}
}
}
void renderWithColorsOptimized()
{
if (!isPaused)
{
setCursorPosition(0, 0);
}
string fullFrame;
fullFrame.reserve(BOARD_HEIGHT * (BOARD_WIDTH + 20));
for (int i = 0; i < BOARD_HEIGHT; i++)
{
if (i < screenBuffer.size())
{
for (int j = 0; j < BOARD_WIDTH; j++)
{
char ch = screenBuffer[i][j];
if (ch == 'B')
{
bool isBrick = false;
int brickRow = -1, brickCol = -1;
for (int r = 0; r < BRICK_ROWS; r++)
{
bool foundInThisRow = false;
for (int c = 0; c < BRICK_COLS; c++)
{
if (bricks[r][c].visible)
{
int brickX = (int)bricks[r][c].x;
int brickY = (int)bricks[r][c].y;
int brickWidth = (int)bricks[r][c].width;
if (i == brickY && j >= brickX && j < brickX + brickWidth)
{
isBrick = true;
brickRow = r;
brickCol = c;
foundInThisRow = true;
break;
}
}
}
if (foundInThisRow)
break;
}
if (isBrick)
{
int colorIndex = (brickRow * BRICK_COLS + brickCol) % 8;
switch (colorIndex)
{
case 0:
fullFrame += BRICK_COLOR_RED;
break;
case 1:
fullFrame += BRICK_COLOR_ORANGE;
break;
case 2:
fullFrame += BRICK_COLOR_YELLOW;
break;
case 3:
fullFrame += BRICK_COLOR_GREEN;
break;
case 4:
fullFrame += BRICK_COLOR_BLUE;
break;
case 5:
fullFrame += BRICK_COLOR_PURPLE;
break;
case 6:
fullFrame += BRICK_COLOR_PINK;
break;
case 7:
fullFrame += BRICK_COLOR_CYAN;
break;
}
fullFrame += "█";
fullFrame += RESET;
}
else
{
fullFrame += ' ';
}
}
else if (ch == '=')
{
fullFrame += CYAN;
fullFrame += selectedPaddleType;
fullFrame += RESET;
}
else if (ch == 'O')
{
fullFrame += GOLD;
fullFrame += selectedBallType;
fullFrame += RESET;
}
else if (ch == 'X')
{
fullFrame += RED;
fullFrame += "⊙";
fullFrame += RESET;
}
else if (ch == '+')
{
fullFrame += PINK;
fullFrame += "♡";
fullFrame += RESET;
}
else
{
fullFrame += ch;
}
}
}
fullFrame += '\n';
}
cout << fullFrame;
// اطلاعات بازی
if (!isPaused)
{
cout << "Player: " << BRIGHT_CYAN << currentPlayerName << RESET << " | ";
cout << "Score: " << BRIGHT_YELLOW << score << RESET << endl;
cout << "Lives: " << BRIGHT_RED;
for (int i = 0; i < lives; i++)
cout << "❤️";
cout << RESET;
cout << " | Mode: " << (gameMode == GAME_MODE_SIMPLE ? PINK : BRIGHT_MAGENTA)
<< (gameMode == GAME_MODE_SIMPLE ? "Simple " : "Advanced ") << RESET;
cout << endl;
if (!gameStarted && !gameOver)
{
cout << BRIGHT_GREEN << "Press SPACE to start or continue the game " << RESET;
cout << endl;
}
else
{
cout << CYAN << "Use A/D to move paddle, P to pause " << RESET;
cout << endl;
}
}
}
// ==================== تابع کمکی برای منوها ====================
void clearMenuArea()
{
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(hConsole, &csbi);
COORD topLeft = {0, 0};
DWORD written;
DWORD cellCount = csbi.dwSize.X * csbi.dwSize.Y;
FillConsoleOutputCharacter(hConsole, ' ', cellCount, topLeft, &written);
FillConsoleOutputAttribute(hConsole, csbi.wAttributes, cellCount, topLeft, &written);
SetConsoleCursorPosition(hConsole, topLeft);
}
// ==================== توابع منو ====================
void printMenu()
{
COORD pos = {0, 0};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
cout << "\n\n\n\n";
cout << " ╔════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╗";
cout << "\n\n\n\n";
cout << " ██████╗ ██████╗ ███████╗ █████╗ ██╗ ██╗ ██████╗ ██╗ ██╗ ████████╗\n";
cout << " ██╔══██╗ ██╔══██╗ ██╔════╝ ██╔══██╗ ██║ ██╔╝ ██╔═══██╗ ██║ ██║ ╚══██╔══╝\n";
cout << " ██║ ██║ ██║ ██║ █████╗ ███████║ █████╔╝ ██║ ██║ ██║ ██║ ██║ \n";
cout << " ██████╔╝ ██████╔╝ ██╔══╝ ██╔══██║ ██╔═██╗ ██║ ██║ ██║ ██║ ██║ \n";
cout << " ██╔══██╗ ██╔══██╗ ███████╗ ██║ ██║ ██║ ██╗ ╚██████╔╝ ╚██████╔╝ ██║ \n";
cout << " ██████╔╝ ██║ ██║ ╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ \n";
cout << endl
<< endl;
int boxWidth = 18;
cout << BOLD << WHITE << " ╔════════════════════════╗" << RESET << "\n";
for (int i = 0; i < 6; i++)
{
string boxColor;
if (i == currentOption)
boxColor = BLUE;
else
boxColor = WHITE;
string textColor;
if (i == currentOption)
textColor = BLUE;
else if (mainMenuOptions[i] == "EXIT")
textColor = RED;
else
textColor = WHITE;
cout << BOLD << WHITE << " ║ " << RESET;
cout << BOLD << boxColor << "╔";
for (int j = 0; j < boxWidth; j++)
cout << "═";
cout << "╗" << RESET;
cout << BOLD << WHITE << " ║" << RESET << "\n";
cout << BOLD << WHITE << " ║ " << RESET;
cout << BOLD << boxColor << "║ " << RESET;
if (i == currentOption)
cout << BOLD << BLUE << "➤ " << RESET;
else
cout << " ";
cout << BOLD << textColor << mainMenuOptions[i] << " " << RESET;
cout << string(boxWidth - (mainMenuOptions[i].length() + 4), ' ');
cout << BOLD << boxColor << "║" << RESET;
cout << BOLD << WHITE << " ║" << RESET << "\n";
cout << BOLD << WHITE << " ║ " << RESET;
cout << BOLD << boxColor << "╚";
for (int j = 0; j < boxWidth; j++)
cout << "═";
cout << "╝" << RESET;
cout << BOLD << WHITE << " ║" << RESET << "\n";
}
cout << BOLD << WHITE << " ╚════════════════════════╝" << RESET << "\n\n\n";
cout << " ╚════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╝";
pos = {0, 0};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
}
void menuMove()
{
clearMenuArea();
printMenu();
int previousOption = -1;
while (true)
{
if (previousOption != currentOption)
{
printMenu();
previousOption = currentOption;
}
if (_kbhit())
{
char ch = _getch();
if (ch == 'w' || ch == 'W')
{
if (currentOption > 0)
currentOption--;
}
else if (ch == 's' || ch == 'S')
{
if (currentOption < 5)
currentOption++;
}
else if (ch == '\r')
{
switch (currentOption)
{
case 0:
printLoading();
newGame();
clearMenuArea();
printMenu();
previousOption = -1;
break;
case 1:
clearMenuArea();
printLoading();
loadGame();
clearMenuArea();
printMenu();
previousOption = -1;
break;
case 2:
printLoading();
clearMenuArea();
helpMove();
clearMenuArea();
printMenu();
previousOption = -1;
break;
case 3:
printLoading();
clearMenuArea();
showGameHistory();
clearMenuArea();
printMenu();
previousOption = -1;
break;
case 4:
printLoading();
clearMenuArea();
settingsMove();
clearMenuArea();
printMenu();
previousOption = -1;
break;
case 5:
system("cls");
exitMove();
clearMenuArea();
printMenu();
previousOption = -1;
break;
}
}
}
Sleep(50);
}
}
void pauseMenu()
{
COORD pos = {40, 14};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
string menu = BOLD + WHITE + " ╔════════════════════════╗" + RESET + "\n";
for (int i = 0; i < 3; i++)
{
string boxColor = (i == currentOption) ? BLUE : WHITE;
menu += BOLD + WHITE + " ║ " + RESET;
menu += BOLD + boxColor + "╔══════════════════╗" + RESET;
menu += BOLD + WHITE + " ║" + RESET + "\n";
menu += BOLD + WHITE + " ║ " + RESET;
menu += BOLD + boxColor + "║ ";
if (i == currentOption)
menu += "➤ ";
else
menu += " ";
menu += pauseMenuOptions[i];
int totalWidth = 16; // عرض کل کادر داخلی
int usedWidth = pauseMenuOptions[i].length() + ((i == currentOption) ? 2 : 2);
int spaces = totalWidth - usedWidth;
if (spaces > 0)
menu += string(spaces, ' ');
menu += "║" + RESET;
menu += BOLD + WHITE + " ║" + RESET + "\n";
menu += BOLD + WHITE + " ║ " + RESET;
menu += BOLD + boxColor + "╚══════════════════╝" + RESET;
menu += BOLD + WHITE + " ║" + RESET + "\n";
}
menu += BOLD + WHITE + " ╚════════════════════════╝" + RESET;
cout << menu;
}
void pauseMove()
{
clearMenuArea();
currentOption = 0;
pauseMenu();
int previousOption = -1;
while (isPaused)
{
if (previousOption != currentOption)
{
pauseMenu();
previousOption = currentOption;
}
if (_kbhit())
{
char a = _getch();
if (a == 'w' || a == 'W')
{
if (currentOption > 0)
currentOption--;
}
else if (a == 's' || a == 'S')
{
if (currentOption < 2)
currentOption++;
}
else if (a == '\r')
{
switch (currentOption)
{
case 0:
isPaused = false;
clearMenuArea();
return;
case 1:
restart();
return;
case 2:
saveGame();
gameOver = true;
isPaused = false;
menuMove();
return;
}
}
}
Sleep(50);
}
}
void resume()
{
isPaused = false;
clearMenuArea();
}
void restart()
{
isPaused = false;
score = 0;
lives = 3;
gameOver = false;
gameStarted = false;
initializeBricks();
paddle.x = INITIAL_PADDLE_X;
paddle.y = INITIAL_PADDLE_Y;
paddle.width = 10.0f;
paddle.height = 1.0f;
paddle.speed = PADDLE_SPEED;
ball.x = INITIAL_BALL_X;
ball.y = INITIAL_BALL_Y;
ball.vx = BALL_SPEED;
ball.vy = -BALL_SPEED;
ball.radius = 0.5f;
if (gameMode == GAME_MODE_ADVANCED)
{
for (int i = 0; i < MAX_POWERUPS; i++)
{
powerups[i].active = false;
powerups[i].collected = false;
}
}
resetBallAndPaddle();
clearMenuArea();
}
// ==================== توابع راهنما ====================
void showHelp()
{
COORD pos = {0, 0};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
cout << "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
int boxWidth = 18;
cout << BOLD << WHITE << " ╔════════════════════════╗" << RESET << "\n";
cout << BOLD << WHITE << " ║ ║" << RESET << "\n";
cout << BOLD << WHITE << " ║ " << BOLD << BLUE << " HELP MENU" << BOLD << WHITE << " ║" << RESET << "\n";
cout << BOLD << WHITE << " ║ ║" << RESET << "\n";
cout << BOLD << WHITE << " ╠════════════════════════╣" << RESET << "\n";
for (int i = 0; i < 3; i++)
{
string boxColor;
if (i == currentHelpOption)
boxColor = BLUE;
else
boxColor = WHITE;
string textColor;
if (i == currentHelpOption)
textColor = BLUE;
else
textColor = WHITE;
cout << BOLD << WHITE << " ║ " << RESET;
cout << BOLD << boxColor << "╔";
for (int j = 0; j < boxWidth; j++)
cout << "═";
cout << "╗" << RESET;
cout << BOLD << WHITE << " ║" << RESET << "\n";
cout << BOLD << WHITE << " ║ " << RESET;
cout << BOLD << boxColor << "║ " << RESET;
if (i == currentHelpOption)
cout << BOLD << BLUE << "➤ " << RESET;
else
cout << " ";
cout << BOLD << textColor << helpOptions[i] << " " << RESET;
cout << string(boxWidth - (helpOptions[i].length() + 4), ' ');
cout << BOLD << boxColor << "║" << RESET;
cout << BOLD << WHITE << " ║" << RESET << "\n";
cout << BOLD << WHITE << " ║ " << RESET;
cout << BOLD << boxColor << "╚";
for (int j = 0; j < boxWidth; j++)
cout << "═";
cout << "╝" << RESET;
cout << BOLD << WHITE << " ║" << RESET << "\n";
}
cout << BOLD << WHITE << " ╚════════════════════════╝" << RESET << "\n";
pos = {0, 0};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
}
void helpMove()
{
currentHelpOption = 0;
clearMenuArea();
showHelp();
int previousOption = -1;
while (true)
{
if (previousOption != currentHelpOption)
{
showHelp();
previousOption = currentHelpOption;
}
if (_kbhit())
{
char ch = _getch();
if (ch == 'w' || ch == 'W')
{
if (currentHelpOption > 0)
currentHelpOption--;
}
else if (ch == 's' || ch == 'S')
{
if (currentHelpOption < 2)
currentHelpOption++;
}
else if (ch == '\r')
{
switch (currentHelpOption)
{
case 0:
controls();
clearMenuArea();
showHelp();
previousOption = -1;
break;
case 1:
aboutGame();
clearMenuArea();
showHelp();
previousOption = -1;
break;
case 2:
return;
}
}
else if (ch == 27)
{
return;
}
}
Sleep(50);
}
}
void controls()
{
system("cls");
cout << "\n\n\n\n\n\n\n\n\n\n\n\n";
cout << BOLD << GOLD << " ╔════════════════════════════════════════════════╗\n";
cout << " ║ HELP ║\n";
cout << " ╠════════════════════════════════════════════════╣\n";
cout << " ║ ║\n";
cout << " ║ Goal: Break all bricks with the ball ║\n";
cout << " ║ ║\n";
cout << " ║ Controls: ║\n";
cout << " ║ A : Move paddle left ║\n";
cout << " ║ D : Move paddle right ║\n";
cout << " ║ P : Pause/Resume ║\n";
cout << " ║ HEART : Increase length of paddle ║\n";
cout << " ║ BOMB : Decrease length of paddle ║\n";
cout << " ║ ║\n";
cout << " ║ You have 3 lives. Don't let ball fall! ║\n";
cout << " ║ ║\n";
cout << " ╚════════════════════════════════════════════════╝\n"
<< RESET;
cout << " Press any key to return...";
_getch();
}
void aboutGame()
{
system("cls");
ifstream file("aboutgame.txt");
if (!file.is_open())
{
cout << RED << "Nothing has found :(" << RESET << endl;
return;
}
string line;
while (getline(file, line))
{
cout << line << endl;
}
file.close();
cout << endl;
cout << BOLD << BRIGHT_RED << "Press any key to return..." << RESET;
_getch();
}
// ==================== توابع تنظیمات ====================
void saveSettings()
{
ofstream file("settings.txt");
if (file.is_open())
{
file << selectedBallType << endl;
file << selectedPaddleType << endl;
file.close();
}
}
void loadSettings()
{
ifstream file("settings.txt");
if (file.is_open())
{
file >> selectedBallType;
file >> selectedPaddleType;
file.close();
}
}
void showSettings()
{
COORD pos = {0, 0};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
cout << "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
int boxWidth = 18;
cout << BOLD << WHITE << " ╔════════════════════════╗" << RESET << "\n";
cout << BOLD << WHITE << " ║ ║" << RESET << "\n";
cout << BOLD << WHITE << " ║ " << BOLD << BLUE << "SETTINGS MENU" << BOLD << WHITE << " ║" << RESET << "\n";
cout << BOLD << WHITE << " ║ ║" << RESET << "\n";
cout << BOLD << WHITE << " ╠════════════════════════╣" << RESET << "\n";
for (int i = 0; i < 3; i++)
{
string boxColor;
if (i == currentSettingsOption)
boxColor = BLUE;
else
boxColor = WHITE;
string textColor;
if (i == currentSettingsOption)
textColor = BLUE;
else
textColor = WHITE;
cout << BOLD << WHITE << " ║ " << RESET;
cout << BOLD << boxColor << "╔";
for (int j = 0; j < boxWidth; j++)
cout << "═";
cout << "╗" << RESET;
cout << BOLD << WHITE << " ║" << RESET << "\n";
cout << BOLD << WHITE << " ║ " << RESET;
cout << BOLD << boxColor << "║ " << RESET;
if (i == currentSettingsOption)
cout << BOLD << BLUE << "➤ " << RESET;
else
cout << " ";
cout << BOLD << textColor << settingsOptions[i] << " " << RESET;
cout << string(boxWidth - (settingsOptions[i].length() + 4), ' ');
cout << BOLD << boxColor << "║" << RESET;
cout << BOLD << WHITE << " ║" << RESET << "\n";
cout << BOLD << WHITE << " ║ " << RESET;
cout << BOLD << boxColor << "╚";
for (int j = 0; j < boxWidth; j++)
cout << "═";
cout << "╝" << RESET;
cout << BOLD << WHITE << " ║" << RESET << "\n";
}
cout << BOLD << WHITE << " ╚════════════════════════╝" << RESET << "\n";
pos = {0, 0};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
}
void settingsMove()
{
currentSettingsOption = 0;
clearMenuArea();
showSettings();
int previousOption = -1;
while (true)
{
if (previousOption != currentSettingsOption)
{
showSettings();
previousOption = currentSettingsOption;
}
if (_kbhit())
{
char ch = _getch();
if (ch == 'w' || ch == 'W')
{
if (currentSettingsOption > 0)
currentSettingsOption--;
}
else if (ch == 's' || ch == 'S')
{
if (currentSettingsOption < 2)
currentSettingsOption++;
}
else if (ch == '\r')
{
switch (currentSettingsOption)
{
case 0:
inBallSettings = true;
ballSettingsMove();
clearMenuArea();
showSettings();
previousOption = -1;
break;
case 1:
inPaddleSettings = true;
paddleSettingsMove();
clearMenuArea();
showSettings();
previousOption = -1;
break;
case 2:
return;
}
}
}
Sleep(50);
}
}
void showBallSettings()
{
COORD pos = {0, 0};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
cout << "\n\n\n\n\n";
int boxWidth = 25;
cout << BOLD << WHITE << " ╔═══════════════════════════════╗" << RESET << "\n";
cout << BOLD << WHITE << " ║ ║" << RESET << "\n";
cout << BOLD << WHITE << " ║ " << BOLD << BLUE << "BALL SETTINGS" << BOLD << WHITE << " ║" << RESET << "\n";
cout << BOLD << WHITE << " ║ ║" << RESET << "\n";
cout << BOLD << WHITE << " ╠═══════════════════════════════╣" << RESET << "\n";
for (int i = 0; i < 8; i++)
{
string boxColor;
if (i == currentBallOption)
boxColor = BLUE;
else
boxColor = WHITE;
string textColor;
if (i == currentBallOption)
textColor = BLUE;
else
textColor = WHITE;
cout << BOLD << WHITE << " ║ " << RESET;
cout << BOLD << boxColor << "╔";
for (int j = 0; j < boxWidth; j++)
cout << "═";
cout << "╗" << RESET;
cout << BOLD << WHITE << " ║" << RESET << "\n";
cout << BOLD << WHITE << " ║ " << RESET;
cout << BOLD << boxColor << "║ " << RESET;
if (i == currentBallOption)
cout << BOLD << BLUE << "➤ " << RESET;
else
cout << " ";
cout << BOLD << textColor << ballTypes[i] << " " << RESET;
cout << string(boxWidth - (ballTypes[i].length() + 2), ' ');
cout << BOLD << boxColor << "║" << RESET;
cout << BOLD << WHITE << " ║" << RESET << "\n";
cout << BOLD << WHITE << " ║ " << RESET;
cout << BOLD << boxColor << "╚";
for (int j = 0; j < boxWidth; j++)
cout << "═";
cout << "╝" << RESET;
cout << BOLD << WHITE << " ║" << RESET << "\n";
}
// گزینه بازگشت
string backOption = "BACK TO SETTINGS";
string backBoxColor = (currentBallOption == 8) ? BLUE : WHITE;
string backTextColor = (currentBallOption == 8) ? BLUE : WHITE;
cout << BOLD << WHITE << " ║ " << RESET;
cout << BOLD << backBoxColor << "╔";
for (int j = 0; j < boxWidth; j++)
cout << "═";
cout << "╗" << RESET;
cout << BOLD << WHITE << " ║" << RESET << "\n";
cout << BOLD << WHITE << " ║ " << RESET;
cout << BOLD << backBoxColor << "║ " << RESET;
if (currentBallOption == 8)
cout << BOLD << BLUE << "➤ " << RESET;
else
cout << " ";
cout << BOLD << backTextColor << backOption << " " << RESET;
cout << string(boxWidth - (backOption.length() + 4), ' ');
cout << BOLD << backBoxColor << "║" << RESET;
cout << BOLD << WHITE << " ║" << RESET << "\n";
cout << BOLD << WHITE << " ║ " << RESET;
cout << BOLD << backBoxColor << "╚";
for (int j = 0; j < boxWidth; j++)
cout << "═";
cout << "╝" << RESET;
cout << BOLD << WHITE << " ║" << RESET << "\n";
cout << BOLD << WHITE << " ╚═══════════════════════════════╝" << RESET << "\n";
pos = {0, 0};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
}
void ballSettingsMove()
{
int previousOption = -1;
clearMenuArea();
showBallSettings();
while (inBallSettings)
{
if (previousOption != currentBallOption)
{
showBallSettings();
previousOption = currentBallOption;
}
if (_kbhit())
{
char ch = _getch();
if (ch == 'w' || ch == 'W')
{
if (currentBallOption > 0)
currentBallOption--;
}
else if (ch == 's' || ch == 'S')
{
if (currentBallOption < 8)
currentBallOption++;
}
else if (ch == '\r')
{
if (currentBallOption == 8)
{
inBallSettings = false;
}
else
{
selectedBallType = ballTypes[currentBallOption];
saveSettings();
system("cls");
COORD pos = {0, 20};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
cout << BOLD << WHITE << " ╔════════════════════════╗" << RESET << "\n";
cout << BOLD << WHITE << " ║ ║" << RESET << "\n";
cout << BOLD << WHITE << " ║ " << BOLD << GREEN << "SETTING SAVED!" << BOLD << WHITE << " ║" << RESET << "\n";
cout << BOLD << WHITE << " ║ ║" << RESET << "\n";
cout << BOLD << WHITE << " ╚════════════════════════╝" << RESET << "\n";
this_thread::sleep_for(chrono::seconds(2));
clearMenuArea();
showBallSettings();
previousOption = -1;
}
}
}
Sleep(50);
}
}
void showPaddleSettings()
{
COORD pos = {0, 0};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
cout << "\n\n\n\n\n";
int boxWidth = 27;
cout << BOLD << WHITE << " ╔═════════════════════════════════╗" << RESET << "\n";
cout << BOLD << WHITE << " ║ ║" << RESET << "\n";
cout << BOLD << WHITE << " ║ " << BOLD << BLUE << "PADDLE SETTINGS" << BOLD << WHITE << " ║" << RESET << "\n";
cout << BOLD << WHITE << " ║ ║" << RESET << "\n";
cout << BOLD << WHITE << " ╠═════════════════════════════════╣" << RESET << "\n";
for (int i = 0; i < 8; i++)
{
string boxColor;
if (i == currentPaddleOption)
boxColor = BLUE;
else
boxColor = WHITE;
string textColor;
if (i == currentPaddleOption)
textColor = BLUE;
else
textColor = WHITE;
cout << BOLD << WHITE << " ║ " << RESET;
cout << BOLD << boxColor << "╔";
for (int j = 0; j < boxWidth; j++)
cout << "═";
cout << "╗" << RESET;
cout << BOLD << WHITE << " ║" << RESET << "\n";
cout << BOLD << WHITE << " ║ " << RESET;
cout << BOLD << boxColor << "║ " << RESET;
if (i == currentPaddleOption)
cout << BOLD << BLUE << "➤ " << RESET;
else
cout << " ";
cout << BOLD << textColor << paddleTypes[i] << " " << RESET;
cout << string(boxWidth - (paddleTypes[i].length() + 2), ' ');
cout << BOLD << boxColor << "║" << RESET;
cout << BOLD << WHITE << " ║" << RESET << "\n";
cout << BOLD << WHITE << " ║ " << RESET;
cout << BOLD << boxColor << "╚";
for (int j = 0; j < boxWidth; j++)
cout << "═";
cout << "╝" << RESET;
cout << BOLD << WHITE << " ║" << RESET << "\n";
}
// گزینه بازگشت
string backOption = "BACK TO SETTINGS";
string backBoxColor = (currentPaddleOption == 8) ? BLUE : WHITE;
string backTextColor = (currentPaddleOption == 8) ? BLUE : WHITE;
cout << BOLD << WHITE << " ║ " << RESET;
cout << BOLD << backBoxColor << "╔";
for (int j = 0; j < boxWidth; j++)
cout << "═";
cout << "╗" << RESET;
cout << BOLD << WHITE << " ║" << RESET << "\n";
cout << BOLD << WHITE << " ║ " << RESET;
cout << BOLD << backBoxColor << "║ " << RESET;
if (currentPaddleOption == 8)
cout << BOLD << BLUE << "➤ " << RESET;
else
cout << " ";
cout << BOLD << backTextColor << backOption << " " << RESET;
cout << string(boxWidth - (backOption.length() + 4), ' ');
cout << BOLD << backBoxColor << "║" << RESET;
cout << BOLD << WHITE << " ║" << RESET << "\n";
cout << BOLD << WHITE << " ║ " << RESET;
cout << BOLD << backBoxColor << "╚";
for (int j = 0; j < boxWidth; j++)
cout << "═";
cout << "╝" << RESET;
cout << BOLD << WHITE << " ║" << RESET << "\n";
cout << BOLD << WHITE << " ╚═════════════════════════════════╝" << RESET << "\n";
pos = {0, 0};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
}
void paddleSettingsMove()
{
int previousOption = -1;
clearMenuArea();
showPaddleSettings();
while (inPaddleSettings)
{
if (previousOption != currentPaddleOption)
{
showPaddleSettings();
previousOption = currentPaddleOption;
}
if (_kbhit())
{
char ch = _getch();
if (ch == 'w' || ch == 'W')
{
if (currentPaddleOption > 0)
currentPaddleOption--;
}
else if (ch == 's' || ch == 'S')
{
if (currentPaddleOption < 8)
currentPaddleOption++;
}
else if (ch == '\r')
{
if (currentPaddleOption == 8)
{
inPaddleSettings = false;
break;
}
else
{
selectedPaddleType = paddleTypes[currentPaddleOption];
saveSettings();
system("cls");
COORD pos = {0, 20};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
cout << BOLD << WHITE << " ╔════════════════════════╗" << RESET << "\n";
cout << BOLD << WHITE << " ║ ║" << RESET << "\n";
cout << BOLD << WHITE << " ║ " << BOLD << GREEN << "SETTING SAVED!" << BOLD << WHITE << " ║" << RESET << "\n";
cout << BOLD << WHITE << " ║ ║" << RESET << "\n";
cout << BOLD << WHITE << " ╚════════════════════════╝" << RESET << "\n";
this_thread::sleep_for(chrono::seconds(2));
clearMenuArea();
showPaddleSettings();
previousOption = -1;
}
}
else if (ch == 27)
{
inPaddleSettings = false;
break;
}
}
Sleep(50);
}
}
// ==================== توابع UI ====================
void printVictory()
{
system("cls");
cout << "\n\n\n\n\n\n\n\n\n\n\n\n";
playVictorySound();
cout << GOLD;
cout << " ██╗ ██╗ ██╗ ██████╗ ████████╗ ██████╗ ██████╗ ██╗ ██╗\n";
cout << " ██║ ██║ ██║ ██╔════╝ ╚══██╔══╝ ██╔═══██╗ ██╔══██╗ ╚██╗ ██╔╝\n";
cout << " ██║ ██║ ██║ ██║ ██║ ██║ ██║ ██████╔╝ ╚████╔╝ \n";
cout << " ╚██╗ ██╔╝ ██║ ██║ ██║ ██║ ██║ ██╔══██╗ ╚██╔╝ \n";
cout << " ╚████╔╝ ██║ ╚██████╗ ██║ ╚██████╔╝ ██║ ██║ ██║ \n";
cout << " ╚═══╝ ╚═╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ \n\n";
cout << " ██╗██████████████████╔██\n";
cout << " ╚═╝ ████████████████ ╚═╝\n";
cout << " ██████████████\n";
cout << " ████████████\n";
cout << " ██████████\n";
cout << " ████████\n";
cout << " ██████\n";
cout << " ████\n";
cout << " ██\n";
cout << " ██\n";
cout << " ████████\n";
cout << " ████████\n";
cout << RESET;
Sleep(2000);
}
void printGameOver()
{
system("cls");
playGameOverSound();
cout << "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
cout << RED;
cout << " ██████╗ █████╗ ███╗ ███╗ ███████╗ ██████╗ ██╗ ██╗ ███████╗ ██████╗ \n";
cout << " ██╔════╝ ██╔══██╗ ████╗ ████║ ██╔════╝ ██╔═══██╗ ██║ ██║ ██╔════╝ ██╔══██╗\n";
cout << " ██║ ███╗ ███████║ ██╔████╔██║ █████╗ ██║ ██║ ██║ ██║ █████╗ ██████\n";
cout << " ██║ ██║ ██╔══██║ ██║╚██╔╝██║ ██╔══╝ ██║ ██║ ╚██╗ ██╔╝ ██╔══╝ ██╔══██╗\n";
cout << " ╚██████╔╝ ██║ ██║ ██║ ╚═╝ ██║ ███████╗ ╚██████╔╝ ╚████╔╝ ███████╗ ██║ ██║\n";
cout << " ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝ ╚═════╝ ╚═══╝ ╚══════╝ ╚═╝ ╚═╝\n";
cout << RESET;
Sleep(2000);
}
void printExit(int selected)
{
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
COORD topLeft = {51, 18}; // موقعیت وسط صفحه
DWORD written;
// پاک کردن 5 خط
for (int i = 0; i < 5; i++)
{
FillConsoleOutputCharacter(hConsole, ' ', 50, topLeft, &written);
topLeft.Y++;
}
// رفتن به موقعیت شروع
COORD pos = {51, 18};
SetConsoleCursorPosition(hConsole, pos);
cout << BOLD << " ╔════════════════════════════════════════╗" << endl;
// رفتن به خط دوم
pos.Y++;
SetConsoleCursorPosition(hConsole, pos);
cout << " ║" << RED << " Are you sure you want to quit? " << RESET << BOLD << " ║" << endl;
// رفتن به خط سوم
pos.Y++;
SetConsoleCursorPosition(hConsole, pos);
cout << " ╠═══════════════════╦════════════════════╣" << endl;
// رفتن به خط چهارم
pos.Y++;
SetConsoleCursorPosition(hConsole, pos);
// کل خط چهارم رو یکجا چاپ کن
cout << " ║";
if (selected == 0)
{
cout << BLUE << BOLD << " ➤ YES " << RESET << BOLD;
}
else
{
cout << " YES ";
}
cout << "║";
if (selected == 1)
{
cout << BLUE << BOLD << " ➤ NO " << RESET << BOLD;
}
else
{
cout << " NO ";
}
cout << "║" << endl;
// رفتن به خط پنجم
pos.Y++;
SetConsoleCursorPosition(hConsole, pos);
cout << " ╚═══════════════════╩════════════════════╝" << RESET;
// برگرداندن مکان‌نما به ابتدای منو
pos.X = 51;
pos.Y = 18;
SetConsoleCursorPosition(hConsole, pos);
}
void exitMove()
{
int selected = 0;
printExit(selected);
while (true)
{
// فقط وقتی که گزینه تغییر کرده
static int lastSelected = -1;
if (lastSelected != selected)
{
// فقط خط چهارم رو به‌روز کن (جایی که YES/NO هست)
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos = {51, 21}; // خط چهارم
SetConsoleCursorPosition(hConsole, pos);
// خط چهارم رو دوباره بکش
cout << " ║";
if (selected == 0)
{
cout << BLUE << BOLD << " YES " << RESET << BOLD;
}
else
{
cout << " YES ";
}
cout << "║";
if (selected == 1)
{
cout << BLUE << BOLD << " NO " << RESET << BOLD;
}
else
{
cout << " NO ";
}
cout << "║";
// فضای اضافی رو پاک کن
cout << " ";
// برگرد به موقعیت
pos.X = 51;
pos.Y = 21;
SetConsoleCursorPosition(hConsole, pos);
lastSelected = selected;
}
if (_kbhit())
{
char a = _getch();
if (a == 'a' || a == 'A')
{
selected = 0;
}
else if (a == 'd' || a == 'D')
{
selected = 1;
}
else if (a == '\r')
{
if (selected == 0)
{
clearMenuArea();
exit(0);
}
else
{
return;
}
}
}
Sleep(50);
}
}
void printLoading()
{
system("cls");
hideCursor();
cout << "\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
cout << " ██╗ " << " ██████╗ " << " █████╗ " << " ██████╗ " << " ██╗" << " ███╗ ██╗" << " ██████╗ \n";
cout << " ██║ " << " ██╔═══██╗" << " ██╔══██╗ " << " ██╔══██╗ " << " ██║" << " ████╗ ██║" << " ██ \n";
cout << " ██║ " << " ██║ ██║" << " ███████║ " << " ██║ ██║ " << " ██║" << " ██╔██╗ ██║" << " ██║ ███║\n";
cout << " ██║ " << " ██║ ██║" << " ██╔══██║ " << " ██║ ██║ " << " ██║" << " ██║╚██╗██║" << " ██║ ██║\n";
cout << " ███████╗" << " ╚██████╔╝" << " ██║ ██║ " << " ██████╔╝ " << " ██║" << " ██║ ╚████║" << " ╚██████╔╝\n";
cout << " ╚══════╝" << " ╚═════╝ " << " ╚═╝ ╚═╝ " << " ╚═════╝ " << " ╚═╝" << " ╚═╝ ╚═══╝" << " ╚═════╝ \n\n";
string spinner = "|/-\\";
for (int i = 0; i < 30; i++)
{
cout << BOLD << WHITE << "\r LOADING " << spinner[i % spinner.size()] << flush;
this_thread::sleep_for(chrono::milliseconds(200));
}
}
void selectGameMode()
{
string modes[] = {"SIMPLE GAME", "ADVANCED GAME"};
int selectedMode = 0;
int previousMode = -1;
clearMenuArea();
while (true)
{
if (previousMode != selectedMode)
{
COORD pos = {0, 0};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
cout << "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
cout << BOLD << WHITE << " ╔════════════════════════╗" << RESET << "\n";
for (int i = 0; i < 2; i++)
{
string boxColor = (i == selectedMode) ? BLUE : WHITE;
string textColor = (i == selectedMode) ? BLUE : WHITE;
cout << BOLD << WHITE << " ║ " << RESET;
cout << BOLD << boxColor << "╔══════════════════╗" << RESET;
cout << BOLD << WHITE << " ║" << RESET << "\n";
cout << BOLD << WHITE << " ║ " << RESET;
cout << BOLD << boxColor << "║ " << RESET;
if (i == selectedMode)
{
cout << BOLD << BLUE << "➤ " << RESET;
}
else
{
cout << " ";
}
cout << BOLD << textColor << modes[i] << RESET;
cout << string(15 - modes[i].length(), ' ');
cout << BOLD << boxColor << "║" << RESET;
cout << BOLD << WHITE << " ║" << RESET << "\n";
cout << BOLD << WHITE << " ║ " << RESET;
cout << BOLD << boxColor << "╚══════════════════╝" << RESET;
cout << BOLD << WHITE << " ║" << RESET << "\n";
}
cout << BOLD << WHITE << " ╚════════════════════════╝" << RESET << "\n";
pos = {0, 0};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
previousMode = selectedMode;
}
if (_kbhit())
{
char ch = _getch();
if (ch == 'w' || ch == 'W')
{
if (selectedMode > 0)
selectedMode--;
}
else if (ch == 's' || ch == 'S')
{
if (selectedMode < 1)
selectedMode++;
}
else if (ch == '\r')
{
gameMode = selectedMode;
return;
}
}
Sleep(50);
}
}
// ==================== توابع تاریخچه بازی ====================
void saveGameHistory(const string &result)
{
ofstream file("gameHistory.txt", ios::app);
time_t now = time(0);
tm *ltm = localtime(&now);
string date = to_string(1900 + ltm->tm_year) + "-" +
to_string(1 + ltm->tm_mon) + "-" +
to_string(ltm->tm_mday);
string time = to_string(ltm->tm_hour) + ":" +
to_string(ltm->tm_min) + ":" +
to_string(ltm->tm_sec);
string gameModeStr = (gameMode == GAME_MODE_SIMPLE ? "Simple" : "Advanced");
file << currentPlayerName << endl;
file << gameModeStr << endl;
file << score << endl;
file << result << endl;
file << date << endl;
file << time << endl;
file.close();
}
void showGameHistory()
{
ifstream file("gameHistory.txt");
if (!file.is_open())
{
cout << RED << "Nothing has found :(" << RESET << endl;
cout << "\n\n";
return;
}
GameRecord histories[1000];
int count = 0;
while (count < 1000 &&
(file >> histories[count].playerName >>
histories[count].gameModeStr >>
histories[count].score >>
histories[count].result >>
histories[count].Date >>
histories[count].Time))
{
count++;
}
file.close();
if (count == 0)
{
cout << "\033[1;31mNo history found.\033[0m" << endl;
return;
}
cout << " ╔════════════════╦════════════════╦════════════════╦════════════════╦════════════════╦════════════════╗" << endl;
cout << " ║ Name ║ Mode ║ score ║ result ║ Date ║ Time ║ " << endl;
cout << " ╠════════════════╬════════════════╬════════════════╬════════════════╬════════════════╬════════════════╣" << endl;
for (int i = 0; i < count; i++)
{
cout << " ║ " << histories[i].playerName << string(15 - histories[i].playerName.size(), ' ')
<< "║ " << histories[i].gameModeStr << string(15 - histories[i].gameModeStr.size(), ' ')
<< "║ " << histories[i].score << string(15 - histories[i].score.size(), ' ')
<< "║ " << histories[i].result << string(15 - histories[i].result.size(), ' ')
<< "║ " << histories[i].Date << string(15 - histories[i].Date.size(), ' ')
<< "║ " << histories[i].Time << string(15 - histories[i].Time.size(), ' ')
<< "║" << endl;
if (i != count - 1)
{
cout << " ╠════════════════╬════════════════╬════════════════╬════════════════╬════════════════╬════════════════╣" << endl;
}
}
cout << " ╚════════════════╩════════════════╩════════════════╩════════════════╩════════════════╩════════════════╝" << endl;
cout << " Press any key to return to main menu ...";
_getch();
}
// ==================== توابع ذخیره و بارگذاری ====================
void saveGame()
{
ofstream file("saved_game.txt");
if (file.is_open())
{
file << gameMode << endl;
file << ball.x << " " << ball.y << " " << ball.vx << " " << ball.vy << " " << ball.radius << endl;
file << paddle.x << " " << paddle.y << " " << paddle.width << " " << paddle.height << " " << paddle.speed << endl;
for (int i = 0; i < BRICK_ROWS; i++)
{
for (int j = 0; j < BRICK_COLS; j++)
{
file << bricks[i][j].x << " " << bricks[i][j].y << " "
<< bricks[i][j].width << " " << bricks[i][j].height << " "
<< bricks[i][j].visible << " ";
}
file << endl;
}
if (gameMode == GAME_MODE_ADVANCED)
{
for (int i = 0; i < MAX_POWERUPS; i++)
{
file << powerups[i].x << " " << powerups[i].y << " "
<< powerups[i].vy << " " << powerups[i].type << " "
<< powerups[i].active << " " << powerups[i].collected << " ";
}
file << endl;
}
file << score << endl;
file << lives << endl;
file << gameStarted << endl;
file << currentPlayerName << endl;
file.close();
}
}
void loadGame()
{
system("cls");
ifstream file("saved_game.txt");
if (!file.is_open())
{
cout << BOLD << BRIGHT_RED << "\nNo unfinished game to load !" << endl;
cout << "Press any key to return" << RESET;
_getch();
return;
}
file >> gameMode;
file >> ball.x >> ball.y >> ball.vx >> ball.vy >> ball.radius;
file >> paddle.x >> paddle.y >> paddle.width >> paddle.height >> paddle.speed;
if (paddle.width < MIN_PADDLE_WIDTH)
paddle.width = MIN_PADDLE_WIDTH;
if (paddle.width > MAX_PADDLE_WIDTH)
paddle.width = MAX_PADDLE_WIDTH;
for (int i = 0; i < BRICK_ROWS; i++)
{
for (int j = 0; j < BRICK_COLS; j++)
{
file >> bricks[i][j].x >> bricks[i][j].y >> bricks[i][j].width >> bricks[i][j].height >> bricks[i][j].visible;
}
}
if (gameMode == GAME_MODE_ADVANCED)
{
for (int i = 0; i < MAX_POWERUPS; i++)
{
file >> powerups[i].x >> powerups[i].y >> powerups[i].vy >> powerups[i].type >> powerups[i].active >> powerups[i].collected;
}
}
file >> score;
file >> lives;
file >> gameStarted;
file.ignore();
getline(file, currentPlayerName);
file.close();
gameOver = false;
isPaused = false;
cout << BOLD << BRIGHT_GREEN << "\nGame loaded successfully!" << endl;
cout << "Player: " << currentPlayerName << endl;
cout << "Score: " << score << endl;
cout << "Lives: " << lives << RESET << endl
<< endl;
cout << BOLD << MAGENTA << "Continue the game ------> Press C" << RESET << endl;
cout << BOLD << BLUE << "Back to menu ------> Press M" << RESET;
while (true)
{
if (_kbhit())
{
char a = _getch();
if (a == 'C' || a == 'c')
{
initScreenBuffer();
hideCursor();
runGame();
}
else if (a == 'M' || a == 'm')
{
menuMove();
}
}
}
}
void clearSavedGame()
{
remove("saved_game.txt");
}
// ==================== تابع اصلی اجرای بازی ====================
void runGame()
{
while (!gameOver)
{
// اگر pause نیستیم، بازی رو render کن
if (!isPaused)
{
renderToBuffer();
renderWithColorsOptimized();
}
if (!gameStarted && !isPaused)
{
while (true)
{
if (_kbhit())
{
char key = _getch();
if (key == ' ')
{
gameStarted = true;
break;
}
else if (key == 'p' || key == 'P')
{
isPaused = true;
pauseMove();
break;
}
}
Sleep(100);
}
if (gameOver)
break;
}
// کنترل راکت - فقط وقتی pause نیستیم
if (!isPaused && _kbhit())
{
char key = _getch();
if (key == 'a' || key == 'A')
{
paddle.x -= paddle.speed;
if (paddle.x < 1)
paddle.x = 1;
if (!gameStarted && !isPaused)
{
ball.x = paddle.x + paddle.width / 2.0f;
}
}
else if (key == 'd' || key == 'D')
{
paddle.x += paddle.speed;
if (paddle.x + paddle.width > BOARD_WIDTH - 1)
paddle.x = BOARD_WIDTH - 1 - paddle.width;
if (!gameStarted && !isPaused)
{
ball.x = paddle.x + paddle.width / 2.0f;
}
}
else if (key == 'p' || key == 'P')
{
isPaused = true;
pauseMove();
continue;
}
}
if (gameStarted && !isPaused)
{
float deltaTime = 0.016f; // 60 فریم در ثانیه
updateBall(deltaTime);
if (gameMode == GAME_MODE_ADVANCED)
{
activatePowerUps(deltaTime);
}
// بررسی تمام شدن آجرها
bool allBricksDestroyed = true;
for (int i = 0; i < BRICK_ROWS; i++)
{
for (int j = 0; j < BRICK_COLS; j++)
{
if (bricks[i][j].visible)
{
allBricksDestroyed = false;
break;
}
}
if (!allBricksDestroyed)
break;
}
checkPaddleCollision();
checkBrickCollision();
checkWallCollision();
if (allBricksDestroyed)
{
gameOver = true;
renderToBuffer();
renderWithColorsOptimized();
printVictory();
saveGameHistory("Won");
clearSavedGame();
}
}
Sleep(8);
}
if (lives == 0)
{
clearMenuArea();
saveGameHistory("Lost");
printGameOver();
clearSavedGame();
}
cout << "\nPress any key to return to main menu..." << endl;
_getch();
clearMenuArea();
menuMove();
}
void newGame()
{
system("cls");
cout << "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
<< BOLD << BLUE << " ENTER YOUR NAME : " << RESET << endl;
cout << " ";
getline(cin, currentPlayerName);
while (currentPlayerName.empty())
{
cout << BOLD << RED << " Enter your name please :)" << RESET;
Sleep(1000);
system("cls");
cout << "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
<< BOLD << BLUE << " ENTER YOUR NAME : " << RESET << endl;
cout << " ";
getline(cin, currentPlayerName);
}
system("cls");
selectGameMode();
initScreenBuffer();
initializeBricks();
if (gameMode == GAME_MODE_ADVANCED)
{
for (int i = 0; i < MAX_POWERUPS; i++)
{
powerups[i].active = false;
powerups[i].collected = false;
}
}
system("cls");
paddle.x = INITIAL_PADDLE_X;
paddle.y = INITIAL_PADDLE_Y;
paddle.width = 10.0f;
paddle.height = 1.0f;
paddle.speed = PADDLE_SPEED;
ball.x = INITIAL_BALL_X;
ball.y = INITIAL_BALL_Y;
ball.vx = BALL_SPEED;
ball.vy = -BALL_SPEED;
ball.radius = 0.5f;
score = 0;
lives = 3;
gameOver = false;
gameStarted = false;
isPaused = false;
resetBallAndPaddle();
runGame();
}
// ==================== تابع main ====================
int main()
{
system("cls");
hideCursor();
// پیش‌ بارگذاری صداها برای کاهش تاخیر
preloadSounds();
loadSettings();
menuMove();
return 0;
}