Как стать автором
Обновить
134
0.2

Пользователь

Отправить сообщение
Не, я только косынку умею играть. Научил друг в далёком 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 с порталами не подружить. Нужно как-то объединять сектора в один большой сектор, не создавая порталов.
Совсем забыл случай, когда стена пересекает прямую области видимости. В этом случае я просто обрезаю стену областью видимости так, чтобы она была со стороны игрока.
Спасибо. :) Ну, значит, MIT. :)

Правда, не знаю, кому эти исходники пригодиться вообще могут. Мне тут на одном форуме сказали, фигурально, что я фигнёй страдаю с софтверными движками и обычным OpenGL. И что давно вместо «forward rendering» используют Deferred Rendering и надо брать готовый движок типа Ogre3d и не изобретать велосипед. :) И я в общем, почти согласен с первым, но вот со вторым не соглашусь — зачем мне Ogre3D, если я игру делать всё равно не буду. :)
Кое-что расскажу о том, как это работает. В файлах исходников геометрический портал в cengine_gportal.cpp. Там вот что делается.
1) Задаём исходный портал, совпадающий с областью поля зрения игрока.
2) Задаём прямую отсечения — это не более, чем прямая, перпендикулярная вектору зрения игрока. Она нужна, чтобы выбросить из рассмотрения всё, что за спиной игрока. Дело в том, что использованная математика требует, чтобы всё происходило перед игроком.
3) Назначаем текущим сектором, сектор, где находится игрок.
4) Выводим стены текущего сектора
5) Рекурсивно бегаем через все порталы сектора, модифицируя портал на ходу и меняя текущий сектор (как зашли в сектор -выводим все его стены). При этом блокируем портал при заходе в него и разблокирует после выхода (через один портал можно смотреть по-разному, в зависимости от того, как мы в него пришли).

Вот и всё.А вот картинка, как обрезаются порталы и стены.



В OpenGL обрезать нужно только порталы — стены сами обрежутся OpenGL с помощью Z-буфера.

Вроде всё. :)
Обычно, интересует порядок цен и то очень приблизительно.
Вот как-то нужно нам было решить, запускаем мы собственную разработку устройства для электрохимического маркирования или покупаем готовое. Нашли производителей. Звоню. Сколько же стоит ваше оборудование? Начинается: «в зависимости от конфигурации...». Ну а в простейшей конфигурации? «Нет, нам надо знать, что вам точно нужно». В общем, я офигел от попыток выяснить хотя бы примерную стоимость хоть чего-то из их оборудования. А нам просто надо оценить, что дешевле сделать, своё или купить. Разработка своего с нуля будет стоить пару-тройку миллионов рублей с полным оформлением КД. А вот сколько ж будет стоить готовое — загадка природы. Плюнули и запустили свою разработку.
Странно, я думал, с яндекс-диска никаких проблем со скачиванием не бывает. Вот ссылка на другом ресурсе.
Кстати, я совсем забыл — в этом движке используется пирамида фильтрации текстур. Ну тут совсем просто — определяется, во сколько раз текстура сжата и выбирается нужная текстура и всё. Функция FindTexture как раз этим и занимается. Также в движке есть вывод спрайта — он просто закомментирован (функция PutSprite). В качестве спрайта используется текстура стены (он тестовый). Но для его вывода нужно раскомментировать в функциях текстурирования в cEngine_Base.cpp заполнение Z-буфера. Раньше я как раз я Z-буфером спрайты и выводил. Но это медленно, поэтому я отключил спрайты и как будет желание и время, подумаю, как обойтись без него.

Информация

В рейтинге
2 409-й
Откуда
Санкт-Петербург и область, Россия
Зарегистрирован
Активность