19.06.2012, 13:50
Наобум.
template <typename T>
class T
{
Sub<int> s1;
Sub<T> s2;
};
Просто редко приходится работать с шаблонами.
template <typename T>
class T
{
Sub<int> s1;
Sub<T> s2;
};
Просто редко приходится работать с шаблонами.
Quote:If a function-definition or member-declarator declares a member function of a class X, the expression this is a prvalue of type “pointer to cv-qualifier-seq X” between the optional cv-qualifier-seq and the end of the function-definition or member-declarator. It shall not appear before the optional cv-qualifier-seq and it shall not appear within the declaration of a static member function (although its type and value category is defined within a static member function as it is within a non-static member function). [Note: the type and value category is defined even for the case of a static member function because declaration matching does not occur until the complete declarator is known, and this may be used in the trailing-return-type of the declarator. —end note]
Otherwise, if a member-declarator declares a non-static data member (9.2 [class.mem]) of a class X, the expression this is a prvalue of type “pointer to X” within the optional brace-or-equal-initializer. It shall not appear elsewhere in the member-declarator.

//---------------------------------------------------------------------------
#include <vcl.h>
#include <math.h>
#pragma hdrstop
#include "Unit1.h"
#include <vector>
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
using namespace std;
TForm1 *Form1;
int mainX, mainY, raznica_ammo_enemy_Y, ammoN, n;
bool build;
const int enemyN=5;
class Tower
{
public:
int xx;
int yy;
int health;
int damage;
int target;
int reload;
Tower ( int x, int y, int h, int d, int t, int r);
void Draw_Tower();
void Zahvat_Target();
void Draw_Lazer();
void Reload_Tower();
};
class Enemy
{
public:
int xx;
int yy;
int health;
Enemy( int x, int y, int h );
void Draw_Enemy();
void Move_Enemy();
};
class Ammo
{
public:
int xx;
int yy;
int number;
int target;
Ammo (int x, int y, int n, int t);
void Move_Ammo( int j);
void Spawn_Ammo( int j);
void Draw_Ammo();
};
vector <Enemy> enemy_group;
vector <Tower> tower_group;
vector <Ammo> ammo_group;
vector <int> interval;
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; //Запоминаем номер врага
}
}
}
}
//-------------
void Tower::Draw_Tower()
{
Form1->Canvas->Draw(xx, yy, tower);
}
//-------------
void Tower::Draw_Lazer()
{
Form1->Canvas->Pen->Color=(TColor)RGB(200,0,0);
Form1->Canvas->MoveTo(xx,yy);
Form1->Canvas->LineTo(enemy_group[target].xx,enemy_group[target].yy);
}
//--------------
void Tower::Reload_Tower()
{
reload+=1;
}
//=====================================================================
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; //Обнуляем для нового отсчета
}
}
}
//-----------------
void Ammo::Draw_Ammo()
{
Form1->Canvas->Draw( xx, yy, ammo);
}
//===========================
void __fastcall TForm1::Button1Click(TObject *Sender)
{
for (int i=0; i < enemyN; i++)
{
Enemy newEnemy( random(100),random(300), 100 );
enemy_group.push_back( newEnemy );
}
Timer1->Enabled = true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
for (int i=0; i<enemyN; i++)
{
enemy_group[i].Move_Enemy();
}
//
if (tower_group.empty()!=true)
{
for (int i=0; i<tower_group.size(); i++)
{
tower_group[i].Zahvat_Target(); //Башни ищут ближайшую цель
}
for(int j=0; j<n; j++)
{
if (tower_group[j].reload==10)
{
ammo_group[j].Spawn_Ammo( j );
}
else
{
tower_group[j].Reload_Tower();
}
}
for (int k=0; k<ammoN; k++)
{
ammo_group[k].Move_Ammo( k ); //Двигаем все патроны
}
}
Invalidate();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormPaint(TObject *Sender)
{
for (int i=0; i<enemyN; i++)
{
enemy_group[i].Draw_Enemy();
}
if (tower_group.empty()!=true)
{
for (int i=0; i<tower_group.size(); i++)
{
tower_group[i].Draw_Tower();
if ( tower_group[i].target >= 0 ) //Если у башни есть цель то рисуем "лазер"
{
if (enemy_group[tower_group[i].target].health>0)
{
tower_group[i].Draw_Lazer();
}
}
}
for(int j=0; j < ammoN; j++)
{
ammo_group[j].Draw_Ammo();
}
}
Form1->Canvas->Draw(610, 235, main);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
DoubleBuffered=true;
for (int i=0; i < enemyN; i++)
{
Enemy newEnemy( random(100),random(300), 100 );
enemy_group.push_back( newEnemy );
}
n=0;
mainX=610;
mainY=235;
ammoN=0;
tower = new Graphics::TBitmap;
tower->LoadFromFile("tower.bmp");
main = new Graphics::TBitmap;
main->LoadFromFile("main.bmp");
enemy2 = new Graphics::TBitmap;
enemy2->LoadFromFile("enemy2.bmp");
ammo = new Graphics::TBitmap;
ammo->LoadFromFile("ammo.bmp");
boom = new Graphics::TBitmap;
boom->LoadFromFile("boom.bmp");
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormMouseDown(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y)
{
if (build==true)
{
Tower newTower ( X,Y, 100, 50, -1, 10);
tower_group.push_back( newTower );
n++;
}
Invalidate();
Form1->Edit1->Text=tower_group.size();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
if (build==true){
build=false;
}
else {build=true;}
}
//---------------------------------------------------------------------------

(04.07.2012 19:44)Efrit Wrote: [ -> ]9) Ввело в ступор содержимое функции Button2Click(). Надеюсь, что это просто "заглушка" такая?

Quote:1) Бросается в глаза разный стиль именования переменных: mainX, mainY, raznica_ammo_enemy_Y. Нотация везде должна быть единой, даже если эта нотация - венгерская.Единой и старался делать) в 3 переменной просто необходимо такое название, иначе не ясно разница между чем и чем. Ну а большая буква - координатная ось.
Quote:2) Конструктор класса Tower вынесен за его пределы - это ладно (хотя и не ясно, зачем), но почему он записан где-то в середине файла, а не сразу вслед за классом?У меня все конструкторы вынесены ниже, рядом с методами. Почему в середине? Просто у меня еще 2 класса, группировал контруктор+метод+метод+... И по порядку, как объявлены классы, так и контструкторы\методы идут.
Quote:3) Да и что значат его переменные, почему они все однобуквенны? В строке Tower ( int x, int y, int h, int d, int t, int r) разобраться сможет только автор этого кода, и никто другой.Исключительно для конструктора. Если заглянуть в сам конструктор там все предельно ясно
Quote:4) За названия вроде "raznica_ammo_enemy_Y"Ну тут название объектов, а не английские слова)
Quote:"Zahvat_Target()"А здесь не захотел писать Цель через транслит, вообще все слова где есть мягкий знак выглядят, как минимум, убого...
Quote:7) Скобки {} кое-где поплыли, а кое-где и отступы вместе с ними. Местами вообще получилась нечитабельная каша, как в функции Zahvat_Target().Просто начал писать все это ооооочень давно. Везде почти поправил, тут пропустил, потому что не требовалось что либо менять в этой функции.
Quote:2) Используется множество глобальных переменных - которые, как известно, не есть гут.Их количество уже сокращено в 3 раза. Еще меньше пока не выходит)
Quote:3) Из-за конструкций вроде Form1->Canvas->Draw(610, 235, main)Не понял что не так) КоординатаХ,КоординатаУ, картинка - вроде так все пишется.
Quote:4) В конструкторах лучше использовать списки инициализации, а не поочерёдное присваивание.Ammo::Ammo (int x, int y, int n, int t) : xx(x), yy(y), number(n), target(t); // ?
Quote:5) Кстати, а где константы-то?Одна есть и хватит)) А если серьезно - специально оставлял переменные - чтобы при надобности просто их менять, не правя при этом код.
Quote:6) Раздражают конструкции вида if (tower_group.empty()!=true) или reload+=1.
Quote:7) Приведение типов в стиле C, как в строке (TColor)RGB(200,0,0), не всегда безопасноЕсли честно вообще не знаю что это все делает, просто нашел где то как цвет задать, и все.
Quote:Либо неиспользуемая переменная, либо просто ошибка.Мой затупень. Надеюсь это просто неиспользуемая переменная)
Quote:9) Ввело в ступор содержимое функции Button2Click(). Надеюсь, что это просто "заглушка" такая?Нажали на кнопку - Вошли в режим строительства - каждый клик строит башню.

Quote:3) Почему не стоит обходить вектор через int-переменную, скромно умолчу.Мозгу нуба намного сподручнее пользоваться интами, чем абстрактными итераторами)
Quote:6) В любом классе желательно наличие конструктора по умолчанию (без параметров), дабы его объекты можно было использовать внутри массивов и STL-контейнеров. У тебя же далеко не везде так.Почему? 3 класса = 3 конструктора.
void __fastcall TForm1::Button2Click(TObject *Sender)
{
build = !build;
}
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 __fastcall TForm1::FormPaint(TObject *Sender)
{
for (int i=0; i<enemyN; i++)
{
enemy_group[i].Draw_Enemy();
}
....
}
Quote:Я эти ваши C++ не знаю, но ведь метод Draw_Enemy проходит по всем врагам и рисует их, но помимо этого он вызывается для каждого врага, не?Угу, это фейл.
packa Wrote:Единой и старался делать) в 3 переменной просто необходимо такое название, иначе не ясно разница между чем и чем.Не, я про другое. Я про символы подчёркивания в именах. Их надо либо использовать везде, либо вообще не использовать.
packa Wrote:У меня все конструкторы вынесены ниже, рядом с методами. Почему в середине? Просто у меня еще 2 класса, группировал контруктор+метод+метод+...Нет, функции-члены класса должны распаолагаться либо внутри него, либо сразу вслед за ним. Я не хочу рыскать по всему cpp-шнику в поисках нужной мне функции - особенно, если самих классов много.
packa Wrote:Исключительно для конструктора. Если заглянуть в сам конструктор там все предельно ясноНичего не ясно. В строке Tower ( int x, int y, int h, int d, int t, int r) - что такое x? Что такое h? Что такое d, t, r? Если я захочу создать экземпляр твоего класса - то я не смогу этого сделать, поскольку я понятия не имею, что же значат его параметры. Правильно писать Tower (int x_pos, int y_pos, int health, int damage, int target, int reload). Поскольку иначе мне придётся копаться во внунренностях твоего класса, а мне некогда.
packa Wrote:Не понял что не так) КоординатаХ, КоординатаУ, картинка - вроде так все пишется.Почему именно 610 и 235, а не 510 и 234? С какого перепугу функция меняет конкретные пиксели экрана? А что, если я захочу уменьшить размеры окна? Или у меня экран 480*320? А если это число 610 используется в нескольких функциях, а я захотел его поменять, что тогда? Мне придётся править каждую функцию, что ли?
packa Wrote:Ammo::Ammo (int x, int y, int n, int t) : xx(x), yy(y), number(n), target(t); // ?Да, именно так.
packa Wrote:Одна есть и хватит)) А если серьезно - специально оставлял переменные - чтобы при надобности просто их менять, не правя при этом код.Константы сильно экономят время, отлавливая ошибки ещё на этапе компиляции. Когда-нибудь ты это оценишь.
packa Wrote:Со вторым полностью согласен, а вот с первым нет. Потому что код явно теряет свою очевидность, что тупо мешает читаемости. Я бы сказал что здесь овчинка выделки не стоит)Какое из двух высказываний для тебя звучит более понятно?
packa Wrote:Нажали на кнопку - Вошли в режим строительства - каждый клик строит башню.Део верно заметил, что можно просто написать build = !build и не мучаться.
Нажали повторно, вышли из режима, можем кликать до посинения, ничего не произойдет
packa Wrote:Мозгу нуба намного сподручнее пользоваться интами, чем абстрактными итераторами)Итератор - это просто "обёртка" над указателем. Если ты не до конца понимаешь адресную арифметику указателей - то, конечно, итераторами пользоваться ещё не стоит.
Кстати уже заюзал в одном месте, но все равно тяжко обрабатывать мозгу, как это работает, хоть и понятно достаточно.
packa Wrote:Почему? 3 класса = 3 конструктора.Дык это не конструкторы по умолчанию - у них параметры есть! Я же говорил именно про конструкторы по умолчанию...

