Скачиваний:
0
Добавлен:
11.01.2026
Размер:
13.17 Кб
Скачать
#include <vcl.h>
#include <algorithm>
#include <cstdlib>
#include <ctime>
#pragma hdrstop

#include "TanksGame.h"
//---------------------------------------------------------------------------

// КЛАСС ИГРЫ
class TTanksGame {
public:
    void RunGame();

private:
    TForm *GameForm;
    TPaintBox *GameBox;
    TTimer *GameTimer;

    int playerX, playerY;
    int playerDirection;
    int playerScore;

    struct Enemy {
        int x, y, direction;
        bool alive;
    };
    Enemy enemies[3];

    struct Bullet {
        int x, y, direction;
        bool active;
    };
    Bullet bullets[10];
    Bullet enemyBullets[10];
    int bulletCount;
    int enemyBulletCount;
    int enemyShootTimer;

    void InitializeGame();
    void MoveBullets();
    void MoveEnemyBullets();
    void MoveEnemies();
    void EnemyShootLogic();
    void CheckCollisions();
    void CheckPlayerCollisions();
    void SpawnBullet();
    void SpawnEnemyBullet(int enemyIndex);
    bool AllEnemiesDestroyed();

    // ОБРАБОТЧИКИ КАК МЕТОДЫ КЛАССА
    void __fastcall GameBoxPaint(TObject *Sender) {
        if (!GameBox) return;

        TCanvas *canvas = GameBox->Canvas;
        canvas->Brush->Color = clBlack;
        canvas->FillRect(Rect(0, 0, GameBox->Width, GameBox->Height));

        // Рисуем танк игрока
        canvas->Pen->Color = clYellow;
        canvas->Brush->Color = clYellow;
        canvas->Rectangle(playerX-10, playerY-10, playerX+10, playerY+10);

        // Дуло танка
        canvas->Pen->Color = clRed;
        canvas->Brush->Color = clRed;
        switch(playerDirection) {
            case 0: canvas->Rectangle(playerX-2, playerY-20, playerX+2, playerY-10); break;
            case 1: canvas->Rectangle(playerX+10, playerY-2, playerX+20, playerY+2); break;
            case 2: canvas->Rectangle(playerX-2, playerY+10, playerX+2, playerY+20); break;
            case 3: canvas->Rectangle(playerX-20, playerY-2, playerX-10, playerY+2); break;
        }

        // Рисуем врагов
        canvas->Brush->Color = clRed;
        for(int i = 0; i < 3; i++) {
            if(enemies[i].alive) {
                canvas->Rectangle(enemies[i].x-8, enemies[i].y-8, enemies[i].x+8, enemies[i].y+8);
            }
        }

        // Рисуем пули игрока
        canvas->Brush->Color = clWhite;
        for(int i = 0; i < 10; i++) {
            if(bullets[i].active) {
                canvas->Ellipse(bullets[i].x-3, bullets[i].y-3, bullets[i].x+3, bullets[i].y+3);
            }
        }

        // Рисуем вражеские пули
        canvas->Brush->Color = TColor(RGB(255, 165, 0));
        for(int i = 0; i < 10; i++) {
            if(enemyBullets[i].active) {
                canvas->Ellipse(enemyBullets[i].x-3, enemyBullets[i].y-3, enemyBullets[i].x+3, enemyBullets[i].y+3);
            }
        }

        // Статус
        canvas->Font->Color = clLime;
        canvas->TextOut(10, 30, "Уничтожено врагов: " + IntToStr(playerScore) + " из 3");
    }

    void __fastcall GameTimerTimer(TObject *Sender) {
        MoveBullets();
        MoveEnemyBullets();
        MoveEnemies();
        EnemyShootLogic();
        CheckCollisions();
        CheckPlayerCollisions();

        if(AllEnemiesDestroyed()) {
            if (GameTimer) GameTimer->Enabled = false;
            ShowMessage("🎉 Победа! Все враги уничтожены!\nВаш счет: " + IntToStr(playerScore));
        }

        if (GameBox) GameBox->Repaint();
    }

    void __fastcall FormKeyDown(TObject *Sender, WORD &Key, TShiftState Shift) {
        if (!GameBox) return;

        switch(Key) {
            case 'W': case VK_UP:
                playerDirection = 0;
                playerY = std::max(20, playerY - 5);
                break;
            case 'S': case VK_DOWN:
                playerDirection = 2;
                playerY = std::min(GameBox->Height-20, playerY + 5);
                break;
            case 'A': case VK_LEFT:
                playerDirection = 3;
                playerX = std::max(20, playerX - 5);
                break;
            case 'D': case VK_RIGHT:
                playerDirection = 1;
                playerX = std::min(GameBox->Width-20, playerX + 5);
                break;
            case VK_SPACE:
                SpawnBullet();
                Key = 0;
                break;
            case VK_ESCAPE:
                if (GameForm) GameForm->Close();
                break;
        }
    }

    void __fastcall ExitButtonClick(TObject *Sender) {
        if (GameForm) GameForm->Close();
    }
};

void TTanksGame::InitializeGame()
{
    playerX = 300;
    playerY = 300;
    playerDirection = 0;
    playerScore = 0;
    bulletCount = 0;
    enemyBulletCount = 0;
    enemyShootTimer = 0;

    enemies[0] = {100, 100, 0, true};
    enemies[1] = {200, 150, 1, true};
    enemies[2] = {400, 80, 2, true};

    for(int i = 0; i < 10; i++) {
        bullets[i] = {0, 0, 0, false};
        enemyBullets[i] = {0, 0, 0, false};
    }

    if (GameTimer) GameTimer->Enabled = true;
}

void TTanksGame::MoveBullets()
{
    if (!GameBox) return;

    for(int i = 0; i < 10; i++) {
        if(bullets[i].active) {
            switch(bullets[i].direction) {
                case 0: bullets[i].y -= 8; break;
                case 1: bullets[i].x += 8; break;
                case 2: bullets[i].y += 8; break;
                case 3: bullets[i].x -= 8; break;
            }

            if(bullets[i].x < 0 || bullets[i].x > GameBox->Width ||
               bullets[i].y < 0 || bullets[i].y > GameBox->Height) {
                bullets[i].active = false;
            }
        }
    }
}

void TTanksGame::MoveEnemyBullets()
{
    if (!GameBox) return;

    for(int i = 0; i < 10; i++) {
        if(enemyBullets[i].active) {
            switch(enemyBullets[i].direction) {
                case 0: enemyBullets[i].y -= 6; break;
                case 1: enemyBullets[i].x += 6; break;
                case 2: enemyBullets[i].y += 6; break;
                case 3: enemyBullets[i].x -= 6; break;
            }

            if(enemyBullets[i].x < 0 || enemyBullets[i].x > GameBox->Width ||
               enemyBullets[i].y < 0 || enemyBullets[i].y > GameBox->Height) {
                enemyBullets[i].active = false;
            }
        }
    }
}

void TTanksGame::MoveEnemies()
{
    if (!GameBox) return;

    for(int i = 0; i < 3; i++) {
        if(enemies[i].alive) {
            // Простой ИИ: двигаемся к игроку
            int dx = playerX - enemies[i].x;
            int dy = playerY - enemies[i].y;

            if(abs(dx) > abs(dy)) {
                enemies[i].direction = (dx > 0) ? 1 : 3;
            } else {
                enemies[i].direction = (dy > 0) ? 2 : 0;
            }

            switch(enemies[i].direction) {
                case 0: enemies[i].y -= 2; break;
                case 1: enemies[i].x += 2; break;
                case 2: enemies[i].y += 2; break;
                case 3: enemies[i].x -= 2; break;
            }

            // Отскок от стен
            if(enemies[i].x < 20 || enemies[i].x > GameBox->Width-20 ||
               enemies[i].y < 20 || enemies[i].y > GameBox->Height-20) {
                enemies[i].direction = rand() % 4;
            }
        }
    }
}

void TTanksGame::EnemyShootLogic()
{
    enemyShootTimer++;
    if (enemyShootTimer < 60) return; // Стреляют раз в ~3 секунды

    enemyShootTimer = 0;

    for(int i = 0; i < 3; i++) {
        if(enemies[i].alive) {
			// 60% шанс что враг выстрелит
            if(rand() % 100 < 60) {
                SpawnEnemyBullet(i);
            }
        }
    }
}

void TTanksGame::SpawnEnemyBullet(int enemyIndex)
{
    if(enemyBulletCount < 10) {
        enemyBullets[enemyBulletCount].x = enemies[enemyIndex].x;
        enemyBullets[enemyBulletCount].y = enemies[enemyIndex].y;

        // Стреляем в сторону игрока
        int dx = playerX - enemies[enemyIndex].x;
        int dy = playerY - enemies[enemyIndex].y;

        if(abs(dx) > abs(dy)) {
            enemyBullets[enemyBulletCount].direction = (dx > 0) ? 1 : 3;
        } else {
            enemyBullets[enemyBulletCount].direction = (dy > 0) ? 2 : 0;
        }

        enemyBullets[enemyBulletCount].active = true;
        enemyBulletCount = (enemyBulletCount + 1) % 10;
    }
}

void TTanksGame::CheckCollisions()
{
    // Пули игрока по врагам
    for(int i = 0; i < 10; i++) {
        if(bullets[i].active) {
            for(int j = 0; j < 3; j++) {
                if(enemies[j].alive &&
                   abs(bullets[i].x - enemies[j].x) < 15 &&
                   abs(bullets[i].y - enemies[j].y) < 15) {
                    enemies[j].alive = false;
                    bullets[i].active = false;
                    playerScore++;
                }
            }
        }
    }
}

void TTanksGame::CheckPlayerCollisions()
{
    // Вражеские пули по игроку
    for(int i = 0; i < 10; i++) {
        if(enemyBullets[i].active &&
           abs(enemyBullets[i].x - playerX) < 15 &&
           abs(enemyBullets[i].y - playerY) < 15) {

            if (GameTimer) GameTimer->Enabled = false; // ОСТАНОВИТЬ ТАЙМЕР
            ShowMessage("💀 Вы проиграли! Вас подбили!\nСчет: " + IntToStr(playerScore));
            if (GameForm) GameForm->Close();
            return;
        }
    }

    // Столкновение с врагами
    for(int i = 0; i < 3; i++) {
        if(enemies[i].alive &&
           abs(enemies[i].x - playerX) < 20 &&
           abs(enemies[i].y - playerY) < 20) {

            if (GameTimer) GameTimer->Enabled = false; // ОСТАНОВИТЬ ТАЙМЕР
            ShowMessage("💀 Столкновение с врагом!\nСчет: " + IntToStr(playerScore));
            if (GameForm) GameForm->Close();
            return;
        }
    }
}

void TTanksGame::SpawnBullet()
{
    if(bulletCount < 10) {
        bullets[bulletCount].x = playerX;
        bullets[bulletCount].y = playerY;
        bullets[bulletCount].direction = playerDirection;
        bullets[bulletCount].active = true;
        bulletCount = (bulletCount + 1) % 10;
    }
}

bool TTanksGame::AllEnemiesDestroyed()
{
    return !enemies[0].alive && !enemies[1].alive && !enemies[2].alive;
}

void TTanksGame::RunGame()
{
    // Инициализация случайных чисел
    srand(static_cast<unsigned>(time(0)));

    // Создаем форму
    GameForm = new TForm(Application);
    GameForm->Caption = "Танчики - Пасхалка by DarkSnaper";
    GameForm->Width = 600;
    GameForm->Height = 400;
    GameForm->Position = poScreenCenter;
    GameForm->BorderStyle = bsSingle;
    GameForm->Color = clBlack;

    // ДОБАВЬ ЭТО - настройка шрифта для формы
    GameForm->Font->Charset = RUSSIAN_CHARSET;
    GameForm->Font->Name = "Arial";
    GameForm->Font->Size = 9;

    // Игровое поле
    GameBox = new TPaintBox(GameForm);
    GameBox->Parent = GameForm;
    GameBox->Align = alClient;
    GameBox->OnPaint = &GameBoxPaint;

    // Статус
    TLabel *StatusLabel = new TLabel(GameForm);
    StatusLabel->Parent = GameForm;
    StatusLabel->Caption = "Управление: WASD/Стрелки - движение, SPACE - выстрел, ESC - выход";
    StatusLabel->Font->Color = clLime;
    StatusLabel->Font->Size = 9;
    StatusLabel->Left = 10;
    StatusLabel->Top = 10;

    // ДОБАВЬ ДЛЯ ЛЕЙБЛА ТОЖЕ
    StatusLabel->Font->Charset = RUSSIAN_CHARSET;
    StatusLabel->Font->Name = "Arial";
    StatusLabel->Top = 10;

    // Таймер игры
    GameTimer = new TTimer(GameForm);
    GameTimer->Interval = 50;
    GameTimer->OnTimer = &GameTimerTimer;

    // Кнопка выхода
    TButton *ExitButton = new TButton(GameForm);
    ExitButton->Parent = GameForm;
    ExitButton->Caption = "Выход";
    ExitButton->Left = 500;
    ExitButton->Top = 10;
    ExitButton->OnClick = &ExitButtonClick;
    ExitButton->TabStop = false;

    // Инициализация игры
    InitializeGame();

    GameForm->KeyPreview = true;
    GameForm->OnKeyDown = &FormKeyDown;

    // Запускаем игру
    GameForm->ShowModal();

    // Очистка
    delete GameForm;
    GameForm = nullptr;
    GameBox = nullptr;
    GameTimer = nullptr;
}

// ГЛОБАЛЬНАЯ ФУНКЦИЯ ДЛЯ ЗАПУСКА
void ShowTanksGame()
{
    TTanksGame game;
    game.RunGame();
}
Соседние файлы в папке Курсовая работа Армашев 3 семестр. Список оргтехники предприятия. С++