From 4a362f9c6072daf09c16830847ed67c213e69376 Mon Sep 17 00:00:00 2001 From: Romina Date: Tue, 14 Apr 2026 21:59:16 +0330 Subject: [PATCH] Initial commit on develop branch --- Breakout.cpp | 436 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 436 insertions(+) create mode 100644 Breakout.cpp diff --git a/Breakout.cpp b/Breakout.cpp new file mode 100644 index 0000000..57b35b9 --- /dev/null +++ b/Breakout.cpp @@ -0,0 +1,436 @@ +#include +#include +#include // برای کار با فایل +#include // برای دریافت ورودی کیبورد +#include // برای مدیریت زمان +#include // توابع استاندارد +#include // برای دریافت تاریخ و زمان +#include // برای مدیریت رشته‌ها +#include // برای کنترل مکان‌نما و حذف پرش تصویر + +using namespace std; + +// تنظیمات کلی بازی +const int WIDTH = 40; // عرض صفحه بازی +const int HEIGHT = 20; // ارتفاع صفحه بازی + +// توابع کمکی برای گرافیک (جلوگیری از پرش تصویر) + +// انتقال مکان‌نما به مختصات (x, y) بدون پاک کردن کل صفحه +void gotoxy(int x, int y) +{ + COORD coord; + coord.X = x; + coord.Y = y; + SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord); +} + +// مخفی کردن نشانگر چشمک‌زن موس برای زیبایی +void HideCursor() +{ + HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE); + CONSOLE_CURSOR_INFO info; + info.dwSize = 100; + info.bVisible = FALSE; + SetConsoleCursorInfo(consoleHandle, &info); +} + +// ایجاد وقفه زمانی دقیق +void waitFor(int milliseconds) +{ + auto start = chrono::high_resolution_clock::now(); + while (chrono::duration_cast(chrono::high_resolution_clock::now() - start).count() < milliseconds) + { + // حلقه انتظار (Busy wait) + } +} + +// کلاس توپ (Ball) +class Ball +{ +public: + float x, y; // مختصات + float dx, dy; // جهت حرکت + bool moving; // وضعیت حرکت + + Ball(float startX, float startY) : x(startX), y(startY), dx(0.5f), dy(-1.0f), moving(false) {} + + // حرکت توپ بر اساس سرعت فعلی + void move() + { + if (moving) + { + x += dx; + y += dy; + } + } + + // بازنشانی توپ به مکان اولیه (بعد از باختن جان) + void reset(float startX, float startY) + { + x = startX; + y = startY; + // جهت پرتاب تصادفی چپ یا راست + dx = (rand() % 2 == 0 ? 0.5f : -0.5f); + dy = -1.0f; + moving = false; + } +}; + +// کلاس راکت (Paddle) +class Paddle +{ +public: + float x; + int y; + int width; + + Paddle(int startX, int startY) : x(startX), y(startY), width(7) {} + + // حرکت به چپ با بررسی مرزها + void moveLeft() + { + x -= 2; + if (x < 1) x = 1; + } + + // حرکت به راست با بررسی مرزها + void moveRight() + { + x += 2; + if (x + width > WIDTH - 1) x = WIDTH - 1 - width; + } +}; + +// کلاس آجر (Brick) +class Brick +{ +public: + int x, y; + bool active; // آیا آجر هنوز وجود دارد؟ + int points; // امتیاز آجر + + Brick(int bx, int by) : x(bx), y(by), active(true), points(10) {} +}; + +// کلاس اصلی بازی (Game Engine) +class Game +{ +private: + bool gameOver; + bool victory; + int score; + int lives; + string playerName; + + Ball* ball; + Paddle* paddle; + vector bricks; + +public: + Game(string name) + { + playerName = name; + gameOver = false; + victory = false; + score = 0; + lives = 3; + + // ایجاد اشیاء بازی + paddle = new Paddle(WIDTH / 2 - 3, HEIGHT - 2); + ball = new Ball(WIDTH / 2, HEIGHT - 3); + + // چیدمان آجرها + for (int i = 0; i < 4; i++) + { + for (int j = 2; j < WIDTH - 2; j += 4) + { + bricks.push_back(Brick(j, i + 2)); + } + } + } + + ~Game() + { + delete ball; + delete paddle; + } + + // رسم محیط بازی (بدون پرش تصویر) + void draw() + { + gotoxy(0, 0); // پرش به ابتدای صفحه به جای پاک کردن کل آن + + string buffer = ""; // بافر برای ذخیره کل تصویر و چاپ یکجا + + // هدر بازی + buffer += "PLAYER: " + playerName + " | SCORE: " + to_string(score) + " | LIVES: " + to_string(lives) + "\n"; + for (int i = 0; i < WIDTH + 2; i++) buffer += "#"; + buffer += "\n"; + + // رسم محتوا + for (int i = 0; i < HEIGHT; i++) + { + for (int j = 0; j < WIDTH; j++) + { + if (j == 0) buffer += "#"; // دیوار چپ + + bool drawn = false; + // رسم توپ + if ((int)ball->x == j && (int)ball->y == i) + { + buffer += "O"; + drawn = true; + } + // رسم راکت + else if (i == paddle->y && j >= (int)paddle->x && j < (int)paddle->x + paddle->width) + { + buffer += "="; + drawn = true; + } + else + { + // رسم آجرها + for (auto& b : bricks) { + if (b.active && b.x == j && b.y == i) + { + buffer += "[]"; + drawn = true; + j++; // پرش از روی کاراکتر دوم آجر + break; + } + } + } + if (!drawn) buffer += " "; // فضای خالی + if (j == WIDTH - 1) buffer += "#"; // دیوار راست + } + buffer += "\n"; + } + + for (int i = 0; i < WIDTH + 2; i++) buffer += "#"; + buffer += "\n"; + + // راهنما پایین صفحه + if(!ball->moving) + buffer += "\nPress 'SPACE' to start. 'a'/'d' to Move. 'q' Quit "; + else + buffer += "\n "; + + cout << buffer; // چاپ نهایی بافر + } + + // دریافت ورودی از کاربر + void input() + { + if (_kbhit()) + { + char current = _getch(); + if (current == 'a' || current == 'A') paddle->moveLeft(); + if (current == 'd' || current == 'D') paddle->moveRight(); + if (current == 'q' || current == 'Q') gameOver = true; + if (current == ' ') ball->moving = true; + } + } + + // منطق بازی (فیزیک و برخوردها) + void logic() + { + if (!ball->moving) + { + // چسبیدن توپ به راکت قبل از پرتاب + ball->x = paddle->x + paddle->width / 2; + ball->y = paddle->y - 1; + return; + } + + ball->move(); + + // برخورد با دیوارهای چپ و راست + if (ball->x <= 1 || ball->x >= WIDTH - 1) ball->dx = -ball->dx; + // برخورد با سقف + if (ball->y <= 0) ball->dy = -ball->dy; + + // برخورد با راکت + if (ball->y >= paddle->y - 1 && ball->y <= paddle->y && ball->x >= paddle->x && ball->x <= paddle->x + paddle->width) + { + ball->dy = -ball->dy; + ball->y = paddle->y - 1; + } + + // افتادن توپ (باختن جان) + if (ball->y >= HEIGHT) + { + lives--; + ball->reset(paddle->x + paddle->width / 2, paddle->y - 1); + if (lives <= 0) gameOver = true; + } + + // برخورد با آجرها + bool allDestroyed = true; + for (auto& b : bricks) + { + if (b.active) + { + allDestroyed = false; + if ((int)ball->x >= b.x && (int)ball->x < b.x + 2 && (int)ball->y == b.y) + { + b.active = false; + ball->dy = -ball->dy; + score += b.points; + } + } + } + + // شرط پیروزی + if (allDestroyed) + { + victory = true; + gameOver = true; + } + } + + // ذخیره تاریخچه بازی در فایل + void saveHistory() + { + ofstream outFile("game_history.txt", ios::app); // برای اضافه کردن به ته فایل + if (outFile.is_open()) + { + // دریافت زمان فعلی + time_t now = time(0); + char* dt = ctime(&now); + // حذف کاراکتر خط جدید از انتهای رشته زمان + string timeStr = dt; + if (!timeStr.empty() && timeStr.back() == '\n') timeStr.pop_back(); + + outFile << "Name: " << playerName << " | Score: " << score << " | Date: " << timeStr << endl; + outFile.close(); + } + } + + // حلقه اصلی اجرای بازی + void run() + { + system("cls"); // پاکسازی اولیه + HideCursor(); + + while (!gameOver) + { + draw(); + input(); + logic(); + waitFor(60); // کنترل سرعت بازی + } + + // ذخیره امتیاز در پایان بازی + saveHistory(); + + system("cls"); + if (victory) + { + cout << "\n\n\t****************************\n"; + cout << "\t* YOU WON! *\n"; + cout << "\t* Score saved to history *\n"; + cout << "\t****************************\n"; + } + else + { + cout << "\n\n\t----------------------------\n"; + cout << "\t! GAME OVER !\n"; + cout << "\t! Score saved to history !\n"; + cout << "\t----------------------------\n"; + } + cout << "\nPress any key to exit..."; + _getch(); + } +}; + +// توابع منو + +void showHelp() +{ + system("cls"); + cout << "========================================\n"; + cout << " GAME HELP \n"; + cout << "========================================\n"; + cout << " Controls:\n"; + cout << " 'a' / 'd' : Move Paddle Left/Right\n"; + cout << " 'SPACE' : Launch Ball\n"; + cout << " 'q' : Quit Game\n\n"; + cout << " Rules:\n"; + cout << " Break all bricks to win.\n"; + cout << " Don't let the ball fall.\n"; + cout << "\nPress any key to return..."; + _getch(); +} + +void showHistory() +{ + system("cls"); + cout << "========================================\n"; + cout << " GAME HISTORY \n"; + cout << "========================================\n"; + + ifstream inFile("game_history.txt"); + string line; + if (inFile.is_open()) + { + while (getline(inFile, line)) + { + cout << line << endl; + } + inFile.close(); + } + else + { + cout << "No history found yet.\n"; + } + + cout << "\n========================================\n"; + cout << "Press any key to return..."; + _getch(); +} + +int main() +{ + srand(static_cast(time(0))); // تنظیم اولیه اعداد تصادفی + + while (true) + { + system("cls"); + cout << "========================================\n"; + cout << " BREAKOUT - MAIN MENU \n"; + cout << "========================================\n"; + cout << " 1. New Game\n"; + cout << " 2. Game History\n"; + cout << " 3. Help\n"; + cout << " 4. Exit\n"; + cout << "========================================\n"; + cout << " Select Option: "; + + char choice = _getch(); + + if (choice == '1') + { + system("cls"); + string pName; + cout << "\nEnter Player Name: "; + cin >> pName; + Game breakout(pName); + breakout.run(); + } + else if (choice == '2') + { + showHistory(); + } + else if (choice == '3') + { + showHelp(); + } + else if (choice == '4') + { + cout << "\nGoodbye!\n"; + break; + } + } + return 0; +} \ No newline at end of file