Добавил:
darksnaper
Поблагодарить: +79781085150 - CБЕР
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:
#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 семестр. Список оргтехники предприятия. С++
