Graphics::TBitmap *enemy2 ; Graphics::TBitmap *ammo ; Graphics::TBitmap *tower ; Graphics::TBitmap *boom ; Graphics::TBitmap *main ; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- Enemy::Enemy( int x, int y, int h ) { xx=x; yy=y; health=h; }
//----------------------------
void Enemy::Draw_Enemy() { for (int i=0; i<enemyN; i++) { if (enemy_group[i].xx!=mainX) { if (enemy_group[i].health>0) { Form1->Canvas->Draw(enemy_group[i].xx, enemy_group[i].yy, enemy2); } else { Form1->Canvas->Draw(enemy_group[i].xx, enemy_group[i].yy, boom); } } } } //---------------------
void Enemy::Move_Enemy() { if ( xx != mainX ) { if (xx>0) { xx+=1; } } } //===========================
Tower::Tower( int x, int y, int h, int d, int t, int r) { xx=x; yy=y; health=h; damage=d; target=t; reload=r; } //---------------
void Tower::Zahvat_Target() { int rasstoyanie[5]; //Массив расстояний от башни до врага for (int j=0; j < enemyN; j++) { if (enemy_group[j].health>0) { int raznicaXtarget = xx - enemy_group[j].xx; //Разница по Х int raznicaYtarget = yy - enemy_group[j].yy; //Разница по Y if (raznicaYtarget<0){ //Если башня выше цели raznicaYtarget=enemy_group[j].yy - yy; } rasstoyanie[j]=sqrt(pow(raznicaXtarget,2)+pow(raznicaYtarget,2)); //Расстояние от врага до башни, по Пифагору } int min = rasstoyanie[0]; int b=0; for (int j=0; j<enemyN; j++){ if (rasstoyanie[j]<min){ min=rasstoyanie[j]; //Находим ближайшего врага b=j; }
if (rasstoyanie[j]<350) { //Если враг в области поражения башни (пока числом) target=b; //Запоминаем номер врага } } }
Ammo::Ammo (int x, int y, int n, int t) { xx=x; yy=y; number=n; target=t; }
//-----------------------
void Ammo::Move_Ammo( int j ) { for(int j=0; j<ammoN; j++) // Для каждого патрона из массива... Делать столько раз, сколько патронов в потоке. { if ( enemy_group [target].xx == xx && enemy_group[target].yy == yy ) { enemy_group[target].health-=50; } else { xx-=1; // Движение по оси Х
//Разница между высотой врага и патрона=высота патрона - высота"выделенного" врага raznica_ammo_enemy_Y=0; if (enemy_group[target].yy > yy) //Если высота врага < высота патрона { raznica_ammo_enemy_Y = enemy_group[target].yy - yy; if (raznica_ammo_enemy_Y < 5) { yy += raznica_ammo_enemy_Y; } else { yy += 5; //Опускаемся на 5 } } else { raznica_ammo_enemy_Y = yy - enemy_group[target].yy; if (raznica_ammo_enemy_Y<5) { yy -= raznica_ammo_enemy_Y; } else { yy -= 5; //Поднимаемся на 5 } } } } }
//-------------------------- void Ammo::Spawn_Ammo ( int j ) { if ( tower_group[j].target >= 0 && tower_group[j].target < 5 ) //Если у башни есть цель { if (enemy_group[tower_group[j].target].health>0) { Ammo newAmmo (tower_group[j].xx, tower_group[j].yy, ammoN, tower_group[j].target); ammo_group.push_back( newAmmo ); ammoN++; tower_group[j].reload=0; //Обнуляем для нового отсчета } } } //-----------------
Оформление: 1) Бросается в глаза разный стиль именования переменных: mainX, mainY, raznica_ammo_enemy_Y. Нотация везде должна быть единой, даже если эта нотация - венгерская. 2) Конструктор класса Tower вынесен за его пределы - это ладно (хотя и не ясно, зачем), но почему он записан где-то в середине файла, а не сразу вслед за классом? А ещё лучше - выносить классы в отдельные файлы. 3) Да и что значат его переменные, почему они все однобуквенны? В строке Tower ( int x, int y, int h, int d, int t, int r) разобраться сможет только автор этого кода, и никто другой. А писать код надо так, будто сопровождать его будет склонный к насилию психопат - который знает, где ты живёшь. (с) 4) За названия вроде "raznica_ammo_enemy_Y" или "Zahvat_Target()" нужно вырвать и застрелить руки. Если уж не знаешь полностью английского (что вполне простительно) - то пиши всё транслитом, но смешивать языки - это моветон. 5) Все символы, относящие к названию типа, нужно писать слитно. В строке vector <Enemy> у тебя Enemy является частью типа, поэтому пробел ставить не надо. Это же касается и звёздочек в объявлениях указателей. 6) А вот в строках типа enemy_group[i].xx!=mainX, наоборот, нужно обязательно отделять пробелом знаки операций. Иначе визуально ничего не понятно. Арифметические операции - это полноценные функции, и они заслуживают "отделения". 7) Скобки {} кое-где поплыли, а кое-где и отступы вместе с ними. Местами вообще получилась нечитабельная каша, как в функции Zahvat_Target().
Кодинг: 1) Строка #include <vector> должна стоять выше, чем #pragma hdrstop. Потому как в твоём случае <vector> будет инклудиться всегда, хотя достаточно всего одного раза. 2) Используется множество глобальных переменных - которые, как известно, не есть гут. В большинстве случаев их можно заменить локальными, если только это не синглтоны. Да и хотя бы прокомментировать их не мешало бы. 3) Из-за конструкций вроде Form1->Canvas->Draw(610, 235, main) есть риск быть похороненным в закрытом гробу бирюзового цвета. Почему именно бирюзового? Потому что 610. А если уж эта строка нужна чисто "для дебага", то нужен комментарий об этом (а ещё лучше - условная компиляция). 4) В конструкторах лучше использовать списки инициализации, а не поочерёдное присваивание. Во-первых, так безопаснее. Во-вторых, только так можно проинициализировать не-статические константы класса. 5) Кстати, а где константы-то? В коде хватает переменных, которые не изменяются после инициализации. А ведь "константность" защищает от ошибок на этапе исполнения. 6) Раздражают конструкции вида if (tower_group.empty()!=true) или reload+=1. В первом случае сравнение с true можно не писать, а во втором нужен обычный инкремент. 7) Приведение типов в стиле C, как в строке (TColor)RGB(200,0,0), не всегда безопасно - лучше использовать "плюсовые" static_cast и dynamic_cast. 8) Зачем в функцию Move_Ammo( int j ) передаётся параметр j, когда он же вводится в первой строчке самой функции? Либо неиспользуемая переменная, либо просто ошибка. 9) Ввело в ступор содержимое функции Button2Click(). Надеюсь, что это просто "заглушка" такая?
Рекомендации: 1) Использовать везде единый стиль записи. Это касается именования переменных, расстановки скобок и комментариев. Имена должны быть осмысленными. 2) Упаковывать данные внутрь классов, используя идиому RAII. Если картинка относится к элементу конкретного класса, не надо таскать её как глобальную переменную - нужно выделить память под неё в конструкторе, и освободить в деструкторе. 3) Почему не стоит обходить вектор через int-переменную, скромно умолчу. Но на всякий случай посоветую почитать про итераторы. Через них всё идёт намного быстрее. 4) Вместо "голых" указателей лучше использовать shared_ptr<> и создавать всё в стеке, избегая кучи вообще. Хотя тебе ещё далековато до такой техники. 5) Вместо множества функций типа Draw_Tower() и Draw_Lazer() лучше иметь одну перегруженную функцию Draw(), которая могла бы принимать объекты разных типов. Это удобно для вызова функций (IDE сама показывает перегрузки), да и наследоваться от таких классов куда проще. 6) В любом классе желательно наличие конструктора по умолчанию (без параметров), дабы его объекты можно было использовать внутри массивов и STL-контейнеров. У тебя же далеко не везде так.
P.S. Только не стоит расстраиваться от прочитанного - я в твоём возрасте кодил намного хуже