Есть фирмы, где программу пишут один-два человека, и никаких систем контроля версий никто никогда не применял и не планирует применять.
И я инженер, а не программист или инженер-программист.
Дело в том, что программа от этого сокращается раза эдак в два (когда 2D). Кроме того, данная абстракция позволяет лучше понять суть производимых с координатами операций.
Всё может быть. Но по-моему, программа и так достаточно прозрачна и вполне себе понятна.
Им не надо «учиться» пользоваться. Надо просто начать и выучить две команды — git commit и git push. Ну хорошо, один раз будет нужно сделать git init
Я чтобы попробовать поставил git отдельно на компьютер и скачал книжку. Так вот, не получилось. В книжке написано — сделайте git add *.cc. Хорошая идея. Только вот как добавить несколько проектов? Как добавить папку? Не написано в той главе, где упоминается git add. А git clone вызывало ошибку kerlen322.dll — у меня Windows XP, а оно, которое скачанное, желает как минимум висту.
По этим ужасным простыням кода низкого качества, в котором отсутствует функциональное деление, использование констант и логичное именование переменных.
По-моему, всё это есть как в этом коде, так и в коде остальных статей. Констант, конечно, нет. Я всё-таки предпочитаю define. Но уж именование переменных и функциональное деление там точно есть.
Разбивка простыней на части помогает их структурировать.
Не соглашусь. От множества мелких функций будет в глазах рябить.
многие данные по смыслу являются векторами. Вот и работайте с ними, как с векторами.
Для шахмат такого лучше не делать. В движке это сделано и так. А эта программа порт с PSP и там я точно их не использовал, потому как, помнится, компилятор там был использован C, а не C++.
а не продираться через x1; x2; dx; и прочее.
Но в данном случае как раз x1,x2 и dx очень даже содержательны. x1;y1-начальные координаты, dx-размер по x.
Исключение составляют функции текстурирования в 2.5D движке — им 15 лет и я тогда написал именно так, а разбираться заново стало лень. Там действительно t1-индекс внутри текстуры, x1-координата, ну и т.д.
4)константные данные следует помещать в const, а не толкать в дефайны.
Не люблю глобальные переменные. А вот define смотрится органично и находится в тексте очень легко — большие буквы. А недостатки есть у многих вещей, но это не повод от них отказываться.
Не, я только косынку умею играть. Научил друг в далёком 2004 году. С тех пор и играю. :)
Кстати, сапёр у меня тоже есть самодельный. Может, и по нему какую-нибудь статью напишу. Вдруг кому столь простые игры интересны будут.
UPD. Прошу прощения, пока редактировал текст под макросы, сделал ошибку в функции MoveCard — цикл не до 52, а до 53 должен быть. А я чего-то решил, что правильно всё-таки до 52. Нет. :) Архив перезалит.
Скачавшие старую версию не смогут её выиграть — там из-за этой ошибки теряется карта,
А разве у нас не три разных по физике масс, которые константами и системой единиц приведены в единство? Гравитационная (F=G*M1*M2/R^2), инертная (F=ma) и та, что в E=m*c^2.
Это который от Сильвермана — Build. Это легендарный 100%. Shadow Warrion, Blood, Duke Nukem 3D.
Но к этой статье приложен не он, а самодельный, гораздо менее мощный.
И вот что меня удивляет. 20 лет, как вышел Duke 3D. Армия программистов. А движков самодельных (хоть с OpenGL, Direct 3D, хоть сотфверных) сделано очень мало. Как так-то? Вообще странно, столько программистов, а весь инет не завален их интересными программами (например, графическими). То ли они пишут только на работе, а дома нет, то ли ещё есть какая причина, но при таком количестве программистов их программ должно быть сильно дофига.
Так это ж самая очевидная схема работы с порталами. :) Я сперва именно геометрический портал и сделал. А потом, много позже, сообразил, что можно по экрану отсекать в случае, когда стены не могут наклоняться влево-вправо. В общем, для Wolf-3D под OpenGL геометрический портал просто идеален. Только надо при выводе стен не выводить одну и ту же стенку дважды (делать отметку о том, что стена уже выведена) и выводить не фрагмент, видимый через портал, а всю стену сразу. Так же и с персонажами и прочими объектами — выводить только из тех секторов-квадратов, которые были выведены через портал и заодно можно проверить, что объекты вообще видны в портал (описать прямоугольник вида сверху вокруг объектов и сравнивать его попадание в портал).
Конвертировал вот такой вот функцией в редакторе 3DEngineEditor. Карта задаётся в текстовом файле:'#'-стена.
//---------------------------------------------------------------------------
//импорт карты из текстового файла
//---------------------------------------------------------------------------
void CDocument_Map::ImportMapFromTXT(FILE *file,CDialog_SettingsWall *cDialog_SettingsWall_Ptr,CDialog_SettingsSector *cDialog_SettingsSector_Ptr)
{
long n;
DeleteAll();
//считываем текстовый файл в плоский массив (0-следующая строка)
vector<unsigned char> vector_data;
bool element=false;
long x=0;
long y=0;
long max_x=0;
while(1)
{
unsigned char b;
if (fread(&b,sizeof(char),1,file)<=0) break;//файл закончился
if (b<static_cast<unsigned char>(' '))
{
if (element==true)//если в строке что-то было считано, делаем перевод строки
{
y++;
vector_data.push_back(0);
}
element=false;
if (x>max_x) max_x=x;
x=0;//строка начинается заново
continue;
}
element=true;
x++;
vector_data.push_back(b);
}
long max_y=y;
//разворачиваем считанную карту в двумерный массив [max_y][max_x] и заполняем его точками
vector< vector<unsigned char> > vector_map(max_y,vector<unsigned char>(max_x,'.'));
x=0;
y=0;
long size=vector_data.size();
for(n=0;n<size;n++)
{
if (vector_data[n]==0 || n==size-1)
{
y++;
x=0;
continue;
}
if (vector_data[n]==static_cast<unsigned char>('#')) vector_map[max_y-y-1][x]=static_cast<unsigned char>('#');//непустое поле
x++;
}
vector_data.clear();
//создаём сектора и сегменты по считанной карте
CSector cSector_Create;//создаваемый сектор
cSector_Create.vector_SSectorPoint.clear();
cSector_Create.Select=false;
cSector_Create.sSector_State=cDialog_SettingsSector_Ptr->GetState();
CWall cWall_Create;//создаваемая стена
cWall_Create.Frontier=false;
cWall_Create.Select=false;
cWall_Create.sWall_State=cDialog_SettingsWall_Ptr->GetState();
for(y=0;y<max_y;y++)
{
for(x=0;x<max_x;x++)
{
unsigned char b=vector_map[y][x];
if (b==static_cast<unsigned char>('.'))//сектор пустой
{
//создаём пустой сектор
cSector_Create.vector_SSectorPoint.clear();
//добавляем точки четырёхугольника, описывающего сектор
SSectorPoint sSectorPoint[4];
sSectorPoint[0].X=(x+1)*100;
sSectorPoint[0].Y=(y+1)*100;
sSectorPoint[1].X=(x+1)*100;
sSectorPoint[1].Y=(y+0)*100;
sSectorPoint[2].X=(x+0)*100;
sSectorPoint[2].Y=(y+0)*100;
sSectorPoint[3].X=(x+0)*100;
sSectorPoint[3].Y=(y+1)*100;
cSector_Create.vector_SSectorPoint.push_back(sSectorPoint[0]);
cSector_Create.vector_SSectorPoint.push_back(sSectorPoint[1]);
cSector_Create.vector_SSectorPoint.push_back(sSectorPoint[2]);
cSector_Create.vector_SSectorPoint.push_back(sSectorPoint[3]);
//добавляем сектор в список секторов
vector_CSector.push_back(cSector_Create);
//если вокруг сектора есть стектора-стены, то добавляем стену, иначе добавляем линию раздела
for(n=0;n<4;n++)
{
long next_n=(n+1)%4;
cWall_Create.X1=sSectorPoint[n].X;
cWall_Create.Y1=sSectorPoint[n].Y;
cWall_Create.X2=sSectorPoint[next_n].X;
cWall_Create.Y2=sSectorPoint[next_n].Y;
cWall_Create.Frontier=true;//стена - линия раздела
if (n==0)//правая стена
{
if (x<max_x-1)
{
if (vector_map[y][x+1]!=static_cast<unsigned char>('.')) cWall_Create.Frontier=false;//сектор справа - стена
}
else cWall_Create.Frontier=false;
}
if (n==1)//нижняя стена
{
if (y>0)
{
if (vector_map[y-1][x]!=static_cast<unsigned char>('.')) cWall_Create.Frontier=false;//сектор снизу - стена
else continue;//не ставим портал, так как он уже есть с этой стороны
}
else cWall_Create.Frontier=false;
}
if (n==2)//левая стена
{
if (x>0)
{
if (vector_map[y][x-1]!=static_cast<unsigned char>('.')) cWall_Create.Frontier=false;//сектор слева - стена
else continue;//не ставим портал, так как он уже есть с этой стороны
}
else cWall_Create.Frontier=false;
}
if (n==3)//верхняя стена
{
if (y<max_y-1)
{
if (vector_map[y+1][x]!=static_cast<unsigned char>('.')) cWall_Create.Frontier=false;//сектор сверху - стена
}
else cWall_Create.Frontier=false;
}
//добавляем сегмент
vector_CWall.push_back(cWall_Create);
}
}
}
}
}
Всё, понял в чём дело. В функции конвертации карты из Wold-3D создавался двойной набор порталов. Вот оно и дико тормозило. Исправил — и всё заработало на ура. :) Не такая уж там и большая рекурсия, даже без объединения квадратов.
Попробовал конвертировать карту типа Wolf-3D. Получилось плохо и вот почему: если каждую клетку назначить сектором с порталами в 4 стороны (или меньше — со стороны блоков-стен нужно поставить стену, а не портал), то при рекурсивном обходе порталов в некоторых зонах начинаются тормоза (вплоть до FPS=0). Фишка в том, что раз сектора мелкие, обход через все порталы всех остальных порталов и секторов вырождается в здоровенную рекурсию. То есть, вот так втупую лабиринт из Wolf-3D с порталами не подружить. Нужно как-то объединять сектора в один большой сектор, не создавая порталов.
Совсем забыл случай, когда стена пересекает прямую области видимости. В этом случае я просто обрезаю стену областью видимости так, чтобы она была со стороны игрока.
Правда, не знаю, кому эти исходники пригодиться вообще могут. Мне тут на одном форуме сказали, фигурально, что я фигнёй страдаю с софтверными движками и обычным OpenGL. И что давно вместо «forward rendering» используют Deferred Rendering и надо брать готовый движок типа Ogre3d и не изобретать велосипед. :) И я в общем, почти согласен с первым, но вот со вторым не соглашусь — зачем мне Ogre3D, если я игру делать всё равно не буду. :)
И я инженер, а не программист или инженер-программист.
Всё может быть. Но по-моему, программа и так достаточно прозрачна и вполне себе понятна.
А у меня portable-версия не работает.
А, вы не про std:vector. Тогда зачем координаты представлять векторами?
Я чтобы попробовать поставил git отдельно на компьютер и скачал книжку. Так вот, не получилось. В книжке написано — сделайте git add *.cc. Хорошая идея. Только вот как добавить несколько проектов? Как добавить папку? Не написано в той главе, где упоминается git add. А git clone вызывало ошибку kerlen322.dll — у меня Windows XP, а оно, которое скачанное, желает как минимум висту.
По-моему, всё это есть как в этом коде, так и в коде остальных статей. Констант, конечно, нет. Я всё-таки предпочитаю define. Но уж именование переменных и функциональное деление там точно есть.
Не соглашусь. От множества мелких функций будет в глазах рябить.
Для шахмат такого лучше не делать. В движке это сделано и так. А эта программа порт с PSP и там я точно их не использовал, потому как, помнится, компилятор там был использован C, а не C++.
Но в данном случае как раз x1,x2 и dx очень даже содержательны. x1;y1-начальные координаты, dx-размер по x.
Исключение составляют функции текстурирования в 2.5D движке — им 15 лет и я тогда написал именно так, а разбираться заново стало лень. Там действительно t1-индекс внутри текстуры, x1-координата, ну и т.д.
Не люблю глобальные переменные. А вот define смотрится органично и находится в тексте очень легко — большие буквы. А недостатки есть у многих вещей, но это не повод от них отказываться.
Кстати, сапёр у меня тоже есть самодельный. Может, и по нему какую-нибудь статью напишу. Вдруг кому столь простые игры интересны будут.
Скачавшие старую версию не смогут её выиграть — там из-за этой ошибки теряется карта,
Но к этой статье приложен не он, а самодельный, гораздо менее мощный.
И вот что меня удивляет. 20 лет, как вышел Duke 3D. Армия программистов. А движков самодельных (хоть с OpenGL, Direct 3D, хоть сотфверных) сделано очень мало. Как так-то? Вообще странно, столько программистов, а весь инет не завален их интересными программами (например, графическими). То ли они пишут только на работе, а дома нет, то ли ещё есть какая причина, но при таком количестве программистов их программ должно быть сильно дофига.
Правда, не знаю, кому эти исходники пригодиться вообще могут. Мне тут на одном форуме сказали, фигурально, что я фигнёй страдаю с софтверными движками и обычным OpenGL. И что давно вместо «forward rendering» используют Deferred Rendering и надо брать готовый движок типа Ogre3d и не изобретать велосипед. :) И я в общем, почти согласен с первым, но вот со вторым не соглашусь — зачем мне Ogre3D, если я игру делать всё равно не буду. :)