#include #include #include #include #include #include #include #include #include #include #include #include #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 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; }