Initial commit on develop branch
This commit is contained in:
+436
@@ -0,0 +1,436 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <fstream> // برای کار با فایل
|
||||
#include <conio.h> // برای دریافت ورودی کیبورد
|
||||
#include <chrono> // برای مدیریت زمان
|
||||
#include <cstdlib> // توابع استاندارد
|
||||
#include <ctime> // برای دریافت تاریخ و زمان
|
||||
#include <string> // برای مدیریت رشتهها
|
||||
#include <windows.h>// برای کنترل مکاننما و حذف پرش تصویر
|
||||
|
||||
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::milliseconds>(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<Brick> 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<unsigned int>(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;
|
||||
}
|
||||
Reference in New Issue
Block a user