[ /tv/ /rf/ /vg/ /a/ /b/ /u/ /bo/ /fur/ /to/ /dt/ /cp/ /oe/ /bg/ /ve/ /r/ /mad/ /d/ /mu/ /cr/ /di/ /sw/ /hr/ /wh/ /lor/ /s/ /hau/ /slow/ /gf/ /vn/ /w/ /ma/ /azu/ /wn/ ] [ Main | Settings | Bookmarks | Music Player ]

No.9135 Reply
File: priznak_koshkosti_1.jpg
Jpg, 23.68 KB, 580×180 - Click the image to expand
edit Find source with google Find source with iqdb
priznak_koshkosti_1.jpg
Здесь будет мой бложик о том, как я рисовал на экране(-ах) компьютера рисунки и анимацию, воспроизводил звуки и имел клавиатуру, мышь и джойстик. Под Линем и Виндой.

Делать я это буду пока не знаю на чем. Выбираю между C# + OpenTK и UDK, но если в UnrealScript-е нет божественных лямбд, то выбор будет однозначен. Потом, скорее всего, инструмент сменю, но пока я только-только вхожу в этот прекрасный мир 2D- и 3D-графики, мне хватит и простоты.
>> No.9138 Reply
>>9135
> Под Линем
> C#
Да ты тот ещё извращенец.
>> No.9198 Reply
File: Снимок.png
Png, 7.43 KB, 645×508
edit Find source with google Find source with iqdb
Снимок.png
File: priznak_koshkosti...
Jpg, 33.79 KB, 580×180
edit Find source with google Find source with iqdb
priznak_koshkosti_2.jpg

Итак, Добрачик, я выбрал OpenTK и нарисовал вращающийся отрезок. Правда, почему-то без dithering-а. Пичалька. И VSync забыл включить.

Пока рисовал, попытался въехать в местные матрицы преобразований координат и немного помял себе мозг. Надо его восстановить, поспать немного. А пока решил, что для 2D достаточно матрицу model-view выставлять в glOrtho(..., -1, 1).

Так что же это получается, анон? Все это ваше 3D - это банальное пидарасение фреймбуфера (как в 1980-ых), да с такими-то утилитами типа "хуйнуть_точку(x, y)", "хуйнуть_линию(x1, y1, x2, y2)", "хуйнуть_полигон_с_антиалиасингом_и_освещением_учитывая_z_буфер(x, y, z, r, w, roll, pitch, scale, lights, etc)"? А 3D-ускорители просто выполняют эти утилиты быстрее?

Просто я раньше думал, что работа с 3D-ускорителем - это декларация ему примитивов, текстур, камеры, освещения и прочего; потом инициализация ускорителя парой мегабайт платформозависимого кода, и - вуаля! - на экран рендерится картинка. А потом просто меняешь состояние выбранных примитивов, и 3D-ускоритель сам обновляет картинку (с учетом VSync). Ну, типа, как видеопамять в ZX-Spectrum (память, отображаемая напрямую на экран), только напрямую отображаются не пиксели, а сферы, полигоны, светильники и камера (а хранятся в виде структур каких-нибудь). И я всегда думал, что вот эта RAM, объем которой указывается в характеристиках 3D-ускорителя, как раз и предназначена для хранения этих примитивов и текстур к ним.

То есть, все не так? 3D-ускорители - это что-то вроде мат. сопроцессоров с функциями... какими я написал?
>> No.9201 Reply
осиль уже VBO, прыщеблядь
>> No.9202 Reply
File: priznak_koshkosti_3.jpg
Jpg, 37.78 KB, 525×168 - Click the image to expand
edit Find source with google Find source with iqdb
priznak_koshkosti_3.jpg
>>9201
...и все эти ваши vertex arrays, display lists и VBO - это просто быстрый способ распидорасить фреймбуфер заранее подготовленными примитивами, да без оверхеда на вызовы функций?
>> No.9216 Reply
File: priznak_koshkosti_4.jpg
Jpg, 26.26 KB, 525×167 - Click the image to expand
edit Find source with google Find source with iqdb
priznak_koshkosti_4.jpg
Только сейчас дошло. Блядь, да они там упоролись! Какая gluPerspective, какой glFrustum в 3D!!!!!!!!??????

Чувствую, ох, чувствую, что вляпался в то еще говно. Разубеди меня, анон, пожалуйста.
>> No.9238 Reply
File: Снимок.png
Png, 7.88 KB, 649×508
edit Find source with google Find source with iqdb
Снимок.png
File: priznak_koshkosti...
Jpg, 35.94 KB, 525×170
edit Find source with google Find source with iqdb
priznak_koshkosti_5.jpg

Сделал второй заход в работу с координатами. Почти все понял, только почему-то GL.DepthRange() не делает ровным счетом ничего, и ось z смотрит назад (на меня).

Думал, z-буфер будет использоваться сразу, из коробки. Наивный. На пикрелейтеде красный полигон подразумевается находящимся позади голубого - как видно, OpenGL из коробки нихрена не использует никаких z-буферов и тупо перехреначивает фреймбуфер новым изображением.

Параллельно заглянул в главу про блендинг. Добрач, это пиздец. Полный, беспробудный пиздец. Или они там окончательно ебанулись все, или я не понимаю, что такое блендинг.

P. S. Да, изучаю по книге http://www.glprogramming.com/red.
>> No.9240 Reply
File: Снимок-1.png
Png, 8.51 KB, 649×511 - Click the image to expand
edit Find source with google Find source with iqdb
Снимок-1.png
>>9238
Насчет z-буфера ложная тревога, анон. Я просто забыл его активировать.

Осталось окончательно въехать в работу с координатами.

Так все-таки, Добрач, я прав насчет пидорасения фреймбуфера? Нигде никаких полигонов не хранится (кроме дисплей-листов)?
>> No.9250 Reply
File: Снимок-Безымянное...
Png, 2.37 KB, 640×480
edit Find source with google Find source with iqdb
Снимок-Безымянное окно.png
File: Снимок-Безымянное...
Png, 2.37 KB, 640×480
edit Find source with google Find source with iqdb
Снимок-Безымянное окно-1.png
File: priznak_koshkosti...
Jpg, 33.24 KB, 580×180
edit Find source with google Find source with iqdb
priznak_koshkosti_6.jpg

Добрач, а может, ну пока нахрен это 3D? Давай я пока 2D-возможности освою, а?
>> No.9255 Reply
File: priznak_koshkosti_7.jpg
Jpg, 27.37 KB, 580×180 - Click the image to expand
edit Find source with google Find source with iqdb
priznak_koshkosti_7.jpg
Да не, там все просто, братюни, с этим 3D. Надо просто запомнить, что:
- Ось z смотрит, как на уроках черчения, на наблюдателя. То есть, -10000 - это охуенно глубоко внутрь экрана.
- Преобразования над текущей матрицей указываются в обратном порядке; например, сначала перенос, потом ротация, хотя логика подсказывает наоборот. Матричная алгебра же.
- Как следствие, при композиции сцены и расстановке объектов сначала выставляется позиция камеры, потом выставляется позиция объекта. Запомнить просто: матрица называется "Model-View", соответственно, сначала идет "model", потом "view", но так как порядок обратный, то и выполнять действия надо в обратном порядке: сначала "view", потом "model". Кстати, это очень удобно: можно расположить камеру, как тебе надо, запихнуть ее в стек матриц и потом уже спокойно расставлять объекты.
- Матрица "Projection" - ТОЛЬКО ДЛЯ ПРОЕКЦИЙ, БЛЕЯТЬ! Не надо устраивать там вторую матрицу "Model-View". glFrustum() и glOrtho() - вот, две функции, которые к ней применимы, больше не надо.
- Ах, да, не забывать сбрасывать матрицы в единичные.

А для чего нужен glDepthRange(), я так и не понял. Вернее, я понял, что он предназначен для масштабирования координаты z, но у меня он почему-то ни на что не влияет (и glGetError() молчит). Кто-нибудь вообще когда-нибудь его пользовал?
>> No.9257 Reply
>>9255
А теперь нарисуй их в обратном порядке, позиционируя глубиной.
Я так и не нашел, как обойти проблему совместного использования альфы и глубины, когда альфа просвечивает сквозь все нижние слои, если они загружены позже.
>> No.9260 Reply
File: Снимок-Безымянное...
Png, 2.84 KB, 640×480
edit Find source with google Find source with iqdb
Снимок-Безымянное окно.png
File: priznak_koshkosti...
Jpg, 27.44 KB, 525×166
edit Find source with google Find source with iqdb
priznak_koshkosti_8.jpg
File: Снимок-Безымянное...
Png, 2.36 KB, 640×480
edit Find source with google Find source with iqdb
Снимок-Безымянное окно-1.png

>>9257
Лол, а никак. Альфа и z-буфер - вещи никак друг с другом не связанные. Или ты пользуешь сокрытие невидимых поверхностей, или смешивание. Я же говорил, что блендинг в OpenGL - говно.

Да и вообще все енто ваше 3D - говно. Банальная сборная солянка из утилит для пидорасения фреймбуфера ТАКИМИ-ТО ПРИМИТИВАМИ. Это больше подходит для рисования реалистичных 2D-спрайтов, чем для моделирования полноценных 3D-сцен. Как результат - костыли везде, проблемы, мануалы по 9000 мегабайт и говно вместо 3D-картинок. Неудивительно, что каждый второй пишет свой 3D-движок. Может быть, это просто OpenGL так устроен, может, в Direct3D все совсем по-другому?

Кстати, братюни, можно ли как-нибудь попользовать матричную алгебру OpenGL? А то он так здорово матрицы перемножает, да с таким-то ускорением, а обратно их не выдает...

P. S. Пока писал, пришла в голову идея: отключить нахуй z-буфер и сортировать объекты по удалению самому. Впрочем, и более быстрого способа я тоже придумать не могу.
>> No.9279 Reply
File: priznak_koshkosti...
Jpg, 24.15 KB, 525×165
edit Find source with google Find source with iqdb
priznak_koshkosti_9.jpg
File: Снимок.png
Png, 5.39 KB, 208×118
edit Find source with google Find source with iqdb
Снимок.png

Пикрелейтед. Думаю теперь, как погрешность сделать не накапливающейся.

А еще хочу размывание и цветовые фильтры.
>> No.9289 Reply
File: Butthurt - 3... 2... 1... Right now!.png
Png, 1300.12 KB, 796×1504 - Click the image to expand
edit Find source with google Find source with iqdb
Butthurt - 3... 2... 1... Right now!.png
А вот и первые ГОМОГЕННЫЕ КООРДИНАТЫ.

Начнем с того, что у GameWindow событие "Load" - это нихуя не полная готовность GameWindow к работе. Так что подготавливать спрайты, например, используя изобразительные возможности OpenGL, у вас не выйдет - получите черные квадраты Малевича. Ну вот и как мне теперь ресурсы инициализировать, блеять? Через if (!AreResourcesInitialized) { ... } в "RenderFrame"?

Далее. При растеризации (через glBitmap() или glDrawPixels()) спрайты НЕ ВРАЩАЮТСЯ. Не скалятся, не слоупятся и т. д. Вообще ничего. Тупо ебашатся во фреймбуфер как есть. А я, такой наивный, думал: ща, устрою вам тут Asteroids 3000, да с такой-то тряской экрана.

Случайно наткнулся на http://www.opengl.org/resources/features/KilgardTechniques/oglpitfall/ и опупел.
> When the raster position is invalid, OpenGL simply discards the pixel data specified by the glBitmap, glDrawPixels, and glCopyPixels commands.
> OpenGL's lighting calculations are done per-vertex.
Шел XXI век. Программисты графических приложений думают, как правильно реализовать клиппинг, и can not into нормальное освещение хотя бы от точечных источников. Пиздец, закапывайте.

От нестерпимого баттхерта заглянул в это ваше Direct3D (какой-то учебник в инете нашел; вроде стоит недорого). 20 COM-объектов и один вертексный шейдер для рисования одного сраного треугольника меня не удивили, но модель фреймбуфера и пайплайна, очень схожая с OpenGL-евской, порвала мою жопу в клочья. Хотя я и не ожидал, что там будет что-то принципиально новое: не могут же разработчики DirectX и OpenGL писать что-то совсем принципиально отличное от того, что им предоставляют 3D-ускорители.

Понравился в DirectX swapchain (куча задних буферов). В OpenGL насколько я понял такого нет, там только передний и задний буферы. Теперь я понимаю, откуда берется эта ебаная задержка в 0.2 с при нажатии на гашетку в Сириус Сэмах и прочих Крузисах.
>> No.9290 Reply
File: priznak_koshkosti_10.jpg
Jpg, 34.19 KB, 525×168 - Click the image to expand
edit Find source with google Find source with iqdb
priznak_koshkosti_10.jpg
У меня к добрейшему сообществу добрейшего чана есть вопросы:

Я собрался спрайты рисовать не через glBitmap() и glDrawPixels(), а как полигоны с текстурой-спрайтом. Все правильно делаю?

Когда все заканчивается, я диспозю только GameWindow, а display list-ы, например, не удаляю. Их ведь не надо удалять, их OpenGL сам удаляет, да?

Gaussian blur я буду делать так: копирну весь фреймбуфер к себе в массивчик (через ReadPixels()), сделаю там gaussian blur, потом выгружу массивчик обратно в буфер. Я долбоёб? Нет, ну не писать же целый пиксельный шейдер ради такой ерунды!
>> No.9295 Reply
>>9260
> что каждый второй пишет свой 3D-движок
Я пишу свой 2д-движок, например.
> отключить нахуй z-буфер и сортировать объекты по удалению самому
Вот как-то так и делаю, слабо представляю, как это будет выглядеть в 3д-движке.
>>9290
> рисовать не через glBitmap() и glDrawPixels(), а как полигоны с текстурой-спрайтом
Все правильно делаешь, glDrawPixels нужен для примеров в книжках.
>> No.9297 Reply
File: 65b2fe1b53d55e52a1b40907792dd023b4b4190a.jpg
Jpg, 107.82 KB, 760×550 - Click the image to expand
edit Find source with google Find source with iqdb
65b2fe1b53d55e52a1b40907792dd023b4b4190a.jpg
>>9240
> Так все-таки, Добрач, я прав насчет пидорасения фреймбуфера? Нигде никаких полигонов не хранится (кроме дисплей-листов)?
Тебе же уже ответили >>9201
Нормально и рисуют через массивы вершин (и) индексов к ним. Всякие glVertexXXX тормозные костыли. Дисплей листы делали для уменьшения call-cost от кучи апи вызовов. Так как каждый апи вызов проходит через пару слоёв абстракций, стоят они довольно недёшево, поэтому и придумали сохранять последовательность вызовов на нижних уровнях и потом просто одной командой её исполнять. И да, рисовать комбинацией glVertexXXX и дисплей листов сущий изврат.
>>9255
> - Ось z смотрит, как на уроках черчения, на наблюдателя. То есть, -10000 - это охуенно глубоко внутрь экрана.
Как сделаешь ViewProjection матрицу, так и будет смотреть. Left-handed и right-handed системы координат, какую матрицу сделаешь такая и будет система.
> - Преобразования над текущей матрицей указываются в обратном порядке; например, сначала перенос, потом ротация, хотя логика подсказывает наоборот. Матричная алгебра же.
Перенос и ротация в world(model) space, потом перенос и ротация в View space, и затем уже проекция. Всё по логике.
> запихнуть ее в стек матриц
Чем меньше зовёшь функций апи тем лучше, делай нормально сам управление матрицами.
> А для чего нужен glDepthRange(), я так и не понял.
Не лезь пока туда, это для всякой продвинутой магии.
>>9257
> Я так и не нашел, как обойти проблему совместного использования альфы и глубины, когда альфа просвечивает сквозь все нижние слои, если они загружены позже.
Самый тупой способ это сортировка полигонов по глубине. Но вообще это не совсем тривиальная задача, ага. Можно читнуть всяких пейперов в интернете.
>>9260
> Как результат - костыли везде, проблемы, мануалы по 9000 мегабайт и говно вместо 3D-картинок.
Ну насчёт манов по 9000 мегабайт ты приврал. Костылей многовато разве что в старых версиях опенгл, хз как в новых. А проблемы, да, всё просто не будет.
> Неудивительно, что каждый второй пишет свой 3D-движок.
Потому что каждый знает КАК лучше сделать.
> Кстати, братюни, можно ли как-нибудь попользовать матричную алгебру OpenGL? А то он так здорово матрицы перемножает, да с таким-то ускорением, а обратно их не выдает...
Юзай матлибы с SSE/AVX. Ну или сам напиши если есть желание и время.
> Пока писал, пришла в голову идея: отключить нахуй z-буфер и сортировать объекты по удалению самому. Впрочем, и более быстрого способа я тоже придумать не могу.
Для спрайтовой графики, если спрайтов не много, даст профит. Если ты конечно грамотно это будешь сортировать.
>>9289
> Начнем с того, что у GameWindow событие "Load" - это нихуя не полная готовность GameWindow к работе. Так что подготавливать спрайты, например, используя изобразительные возможности OpenGL, у вас не выйдет - получите черные квадраты Малевича. Ну вот и как мне теперь ресурсы инициализировать, блеять? Через if (!AreResourcesInitialized) { ... } в "RenderFrame"?
Инициализация->загрузка ресурсов(модельки, текстуры и прочее), и потом уже отрисовка. Не городи лишней ерунды.
> Далее. При растеризации (через glBitmap() или glDrawPixels())
Насколько я помню эти функции жутко тормозные и юзать их не надо.
> Шел XXI век. Программисты графических приложений думают, как правильно реализовать клиппинг, и can not into нормальное освещение хотя бы от точечных источников. Пиздец, закапывайте.
Несильно понятно, но освещение если 3д, делается через шейдеры. А ffp функции уже давно не юзают, кроме как если нужны простые возможности и/или платформа не поддерживает шейдеры.
> От нестерпимого баттхерта заглянул в это ваше Direct3D (какой-то учебник в инете нашел; вроде стоит недорого). 20 COM-объектов и один вертексный шейдер для рисования одного сраного треугольника меня не удивили
Можно нарисовать юзая около 3-5 объектов всего и без шейдеров, если на девятом. Просто там видимо пример сразу показывает как лучше всего делать.
> Теперь я понимаю, откуда берется эта ебаная задержка в 0.2 с при нажатии на гашетку в Сириус Сэмах и прочих Крузисах.
Буферы флипаются очень быстро, другое дело что пока сигнал дойдёт до монитора и прочее, но даже при 60 фпс это 1000 / 60 = 16 мс + какое то время на путь от видеокарты до монитора, что не 0.2 с, хотя и может быть чувствительно при задротстком стиле игры.
>>9290
> Я собрался спрайты рисовать не через glBitmap() и glDrawPixels(), а как полигоны с текстурой-спрайтом. Все правильно делаю?
Да.
> Их ведь не надо удалять, их OpenGL сам удаляет, да?
Читай доки, я в гл не слишком хорошо разбираюсь, но сильно вряд ли что он будет сам удалять.
> Gaussian blur я буду делать так: копирну весь фреймбуфер к себе в массивчик (через ReadPixels()), сделаю там gaussian blur, потом выгружу массивчик обратно в буфер.
За такое бьют по рукам, потому что это будут лютые тормоза. Делай либо через шейдер, либо если у тебя платформа планируется без поддержки шейдеров через магию с билинейной фильтрацией, будет хуже чем Гаусс конечно, но и не такой изврат.
> Нет, ну не писать же целый пиксельный шейдер ради такой ерунды!
int main(int argc, char* argv[])
{
    StartCrysis();
    return 0;
}
>> No.9299 Reply
File: 6zpu9197.jpg
Jpg, 56.01 KB, 570×760
edit Find source with google Find source with iqdb
6zpu9197.jpg
File: priznak_koshkosti...
Jpg, 32.32 KB, 525×167
edit Find source with google Find source with iqdb
priznak_koshkosti_11.jpg

>>9295
Поправляюсь: каждый второй пишет свой графический движок.

>>9297
> Тебе же уже ответили >>9201
Да ты опять не понял. Смотри, я представлял себе программу для работы с 3D вот так:
Init();   // Внутри - 5 мегабайт люто платформозависимого кода.
CSphere sphere = videocard.AddSphere(x, y, z, r);
CBox box = videocard.AddBox(...);
CBox alphaBox = videocard.AddTransparentBox(...);
CLight light = videocard.AddLight(...);
videocard.PositionCamera(...);
...  // Запускаем нашу игру!
videocard.MoveSphere(sphere, dx, dy, dz);
videocard.MoveBox(box, dx, dy, dz);
videocard.RotateBox(alphaBox, ox, oy, oz, angle);
Все, и видеокарта сама поддерживает фреймбу... видеопамять в актуальном состоянии, следит за порядком полигонов, корректно блендит полупрозрачные модели (ну, я же указал ей, что вот у этого полигона альфа - 0.5; что еще надо?) и отслеживает изменения в загруженных в нее объектах. А реалистичная вода, lense flare и ambient light - это все уберфичи видеокарты, которые тоже можно таким же образом настроить.

Ну, подобно тому, как в каком-нибудь CorelDraw ты создаешь объекты, располагаешь их на поле, задаешь им свойства - а CorelDraw сам уже следит за их отрисовкой, смешиванием и прочим. А раньше, до появления такой объектной концепции использовалась концепция холста: юзеру предоставлялся некий холст, утилита для рисования точки и... и все, собственно; весь остальной функционал (линии, полигоны, круги) реализовывался через "нарисовать точку". Такой подход по-своему хорош, но в играх он просасывает, потому что юзеру самому приходится следить, чтобы объекты рисовались в нужном порядке, чтобы предыдущий кадр не накладывался на текущий и т. д.

Так вот, я думал, что OpenGL (и видеокарта) реализуют такой вот объектный подход, но совсем никак не ожидал, что будет концепция холста.
> Как результат - костыли везде, проблемы, мануалы по 9000 мегабайт и говно вместо 3D-картинок.
...потому что подход с холстом и в 2D-то сосет, а в 3D - так и вовсе. Например, юзеру приходится самому следить за кадровой разверткой и самому (!) перерендеривать всю сцену, да не забывать очищать от предыдущего кадра; самому следить за порядком 3D-объектов (иногда без помощи z-буфера); самому реализовывать блендинг (бленд-функции в OpenGL - говно); самому следить за матрицами model, view и projection, чтобы после рендеринга очередного примитива они не стали говном; самому, самому, самому. XXI век, хули.
> [Дисплей-листы vs VBO]
Опля, а что, дисплей-листы никак не компилятся в какую-нибудь внутреннюю штуку для видеокарты? Например, в тот же VBO?
> > Кстати, братюни, можно ли как-нибудь попользовать матричную алгебру OpenGL? А то он так здорово матрицы перемножает, да с таким-то ускорением, а обратно их не выдает...
> Юзай матлибы с SSE/AVX. Ну или сам напиши если есть желание и время.
Да ну ты брось, ради очередного клона Elite подключать профессиональную библиотечку... Мне просто нужно Кобру-МК3 вперед по миру двигать. У OpenGL уже все для этого есть, вот только матрицы... кстати, доставать матрицы из него я таки научился, так что проблема решена.
> Инициализация->загрузка ресурсов(модельки, текстуры и прочее), и потом уже отрисовка. Не городи лишней ерунды.
Ниасилел. Мне нужно перед началом игры создать все VBO и загрузить в видяху все текстуры. Чтобы во время жаркой перестрелки комп не полез вдруг на винт.
> может быть чувствительно при задротстком стиле игры.
Стиль был задротский.
> [шейдеры, шейдеры, шейдеры]
Что-то больно часто они упоминаются. Я всегда думал, что эти штуки нужны для супер-крутых сцен, типа реалистичной воды, плывущих облаков... Мол, для казуальной простоты это оверкилл. Не оверкилл?

P. S. Пикрелейтед - торт "Дракон".
>> No.9300 Reply
File: priznak_koshkosti...
Jpg, 31.87 KB, 525×166
edit Find source with google Find source with iqdb
priznak_koshkosti_12.jpg
File: 1289429335037.jpg
Jpg, 32.03 KB, 335×479
edit Find source with google Find source with iqdb
1289429335037.jpg

Я решил написать свой игровой движок. Проверьте концепцию, братюни.

Будет интерфейс ILiving:
ILiving {
    
    /**
     * @returns true if this ILiving is still alive.
     */
    bool Live();
    
}
и все объекты игры будут ему удовлетворять.

Также будут два предопределенных класса, World и Camera. Они тоже буду ILiving. World будет транслировать вызов Live() всем объектам, которые в нем есть.

Убер-фичей у меня будет концепция "живи и дай жить другим" и, соответственно, возможность писать реализацию Live() с использованием yield return:
... Live0() {
    for (x = 0; x < 1000; x++) {
        this.X = x;
        yield return IGNORE;
    }
    // When the object returns it dies.
}
Общаться объекты будут друг с другом напрямую, находя друг друга через World. Возможно, будут подписываться на события друг друга, если захотят.

В класс Camera я думаю инкапсулировать создание GameWindow, настройку OpenGL и прочее. Мол, это же камера - вот пусть и занимается делами отображения.

Также будет интерфейс IRenderable:
IRenderable {
  
    void InitRendering(IGraphicsContext);
    
    void Render(IGraphicsContext);
    
    void DisposeRendering(IGraphicsContext);
    
}
И все объекты игры тоже будут ему удовлетворять.

У меня пока возникает проблема с менеджментом ресурсов. Я хочу в качестве ресурсов иметь делегаты InitRendering() и DisposeRendering(), но как грамотно их организовать, я не знаю. Проблема в том, что "инициализировать сразу все ресурсы" подходит только для маленьких казуальных игрушек, а для Крузиса надо проинициализировать только то, что будет использоваться в текущем уровне. А это надо явно прописывать классы в каком-нибудь стороннем списке, что мне не хочется. Алсо, упреждающая подгрузка прямо во время игры и диспозинг заведомо не использующихся ресурсов - тоже как бы фичи, и их тоже хочется поиметь...
>> No.9304 Reply
>>9289
> Случайно наткнулся на http://www.opengl.org/resources/features/KilgardTechniques/oglpitfall/ и опупел.
> Шел XXI век...
... а аноны с доброчана по прежнему продолжали юзать допотопные glBitmap, glDrawPixels и так и не научились смотреть на дату статьи, которую читают Copyright 1998, 1999 by Mark J. Kilgard. Last Updated July 10, 2000.

Сажа раковому треду.
>> No.9305 Reply
File: Девушка, отрендер...
Png, 237.68 KB, 1024×746
edit Find source with google Find source with iqdb
Девушка, отрендеренная прям из BitmapData.Scan0.png
File: Девушка, отрендер...
Png, 238.88 KB, 1024×746
edit Find source with google Find source with iqdb
Девушка, отрендеренная в RGB (перевернутая).png
File: Девушка, отрендер...
Png, 238.72 KB, 1024×746
edit Find source with google Find source with iqdb
Девушка, отрендеренная в BGR (перевернутая).png
File: priznak_koshkosti...
Jpg, 35.68 KB, 525×166
edit Find source with google Find source with iqdb
priznak_koshkosti_13.jpg

Сегодня научился эмбедить ресурсы в сборку. Понравилось. Ждите exe-шников на 200 Мб.

Алсо, научился читать рисунки из файлов и даже немножко их рендерить (да-да, все через тот же glDrawPixels). Обнаружил пару граблей. Например, порядок цветовых компонент в BitmapData, возвращаемом LockBits(), и в массиве, загружаемом в видеокарту, отличается, то есть, если ты залочил биты в формате RGB, то в видеокарту надо загружать в формате BGR. Ну, по крайней мере, на моем компьютере так. Не знаю, может, на других видеокартах это не так (правда, тогда это нехуевый платформозависимый косяк). Алсо, нельзя забывать про умолчальную систему координат - glDrawPixels() работает всегда именно в ней, поэтому картинку переворачивает.

Еще алсо, я окончательно решил, как буду делать менеджер ресурсов. У GameObject-ов будет функция GetResourcesData() (название рабочее), которая будет возвращать массив структур { ResourceID, Init(), Dispose() }. Дальше, я думаю, понятно. Единственное, освобождаться неиспользуемые ресурсы будут только тогда, когда очередной Init() вылезет за выставленные границы. То есть, да, границы надо будет выставлять с запасом.

В любом случае, когда загружается очередной уровень, в него сначала добавляются все его объекты, а вместе с ними грузятся и все ресурсы. В крайнем случае, если нужна упреждающая загрузка, можно будет как-нибудь исхитриться и прогрузить их через искусственные объекты.

>>9304
Да, я знаю. Просто не ожидал, что такое удобное API окажется устаревшим, да еще и нерабочим.

c:идеальный инфа чтоле живо бампуе иногда
>> No.9306 Reply
>>9305
> API окажется устаревшим, да еще и нерабочим.
Анон, у меня для тебя плохие новости - это не API устарел, его то как раз в последнее время хорошенько вычистили ото всякого дерьма. Просто твоё сознание осталось где-то в 90-х годах. Хотя, если ты продолжаешь изучать http://www.glprogramming.com/red/, то я этому не удивляюсь.
>> No.9307 Reply
>>9306
>>9304
Без полезных ссылок/советов твоя критика не имеет смысла.
Мимокрокодил
>> No.9308 Reply
>>9307
> Без полезных ссылок/советов твоя критика не имеет смысла.
А что его, по головке гладить, если он упорно юзает glDrawPixels ? И неужели мне правда нужно учить человека искать информацию в сети ? Ну так и быть, доброчан же:
  • Свежие спеки: http://www.opengl.org/documentation/specs/
  • Справочник по всем функциям: http://www.opengl.org/sdk/docs/man4/
  • Книги: http://www.opengl.org/documentation/books/, совсем новичкам советую обратить внимание на OGL Superbible
  • Книги скачать: rutracker.org, thepiratebay.org
  • Отдельно можно погуглить по словам deprecated opengl functions
  • Отдельно нужно напомнить, что на раене сейчас модно писать всё, что только можно, на шейдерах
  • Если ОП испытывает баттхёрт по поводу того, что OGL/DX это low level, то пусть гуглит по словам scene graph, inventor, retained mode, game engine
  • Судя по тому, что у ОПа начинает проявляться болезнь Орхитектора, пусть гуглит по словам Haskell, C, Lisp, Prolog
>> No.9309 Reply
>>9308
Няша, а OGL еще не протух? Мну еще лет 10 назад на нём писал (неосилил директтридэ, лол, имхо у OGL гораздо более человечные API). По идее за 10 лет должны были написать всё, что вообще на нём возможно написать, или он должен был протухнуть и все сейчас пишут на чём-то другом..
>> No.9310 Reply
>>9309
Сегодняшний OGL уже совсем не тот, что был 10 лет назад. Там половину API объявили deprecated, оставив одни только шейдеры, лол. Ещё последние версии стали пилить с оглядкой на OpenCL.
>> No.9318 Reply
File: priznak_koshkosti_14.jpg
Jpg, 23.52 KB, 525×165 - Click the image to expand
edit Find source with google Find source with iqdb
priznak_koshkosti_14.jpg
Доброчан добр.

Спокойно, братюни. Я все это прекрасно понимаю. И, в частности, glDrawPixels() использую исключительно в целях обучения - уж очень удобная оказалась, собака. Понятно, что дальше прототипов код с этой командой не пойдет.

Искать информацию меня учить не нужно (это все-таки АИБ, а не Вопросы-Ответы и не http://stackoverflow.com это студентам на заметку), но >>9308-куну, тем не менее, спасибо. Почти все это я уже сам нашел (при этом пару раз воскликнув: "ЕБАААААТЬ!"), но вот про scene graph и retained mode не слышал. Точнее, не знал, как это называется.

Баттхерта по поводу low-level-ности OGL/DX я не испытываю (тут меня как раз все устраивает пока что, даже движка никакого не надо, лол), я испытываю баттхерт от того, что этот самый low level работает в immediate mode, а не в retained. Нет, VBO и шейдеры - это не immeadiate mode. Необходимость самому следить за порядком полигонов и свапать буферы - это следствия immediate-ности. Кстати, из-за этого же, например, принципиально невозможно запилить нормальное освещение на аппаратном уровне - видеокарта не знает, какой из ее объектов юзер захочет отрендерить в следующий момент.

Ну так вот. С тех пор, как я начал изучать эти ваши шейдеры, я не перестаю восклицать: "ЕБААААААТЬ!" Я теперь понимаю, почему сейчас модно все на них делать. Так-то, конечно, можно вообще весь Крузис в видеокарту загрузить (вместе с игровой логикой и ИИ врагов) и посылать ей только команды от контроллеров. Но это ж пиздец, анон. Человечество потратило миллиарды человеколет и квадриллионы долларов на создание более-менее удобных средств разработки, абстрагирование от платформы, на компиляторы таких языков как C#, Python, Java, наконец, и мы опять возвращаемся к тому, с чего все начиналось - к голимому Ассемблеру. Ладно, хоть C-подобный компилятор для него сделали. И что, опять теперь всем проходить этот путь: C -> C++ -> STL -> .NET & Python (перефразирую: C -> говно с классами -> библиотеки классов -> говно с рантаймом & скриптовня) - только теперь уже для видеокарт? Да ну нахуй это дерьмо, я сваливаю с этой планеты!

P. S. Сами разработчики видеокарт не виноваты - их просто заебало на каждый чих покупателей пидорасить и продвигать очередной модуль GPU, вот они и сказали (посредством запиливания шейдеров): "да короче, пишите сами эти ваши бампмаппинги и антиалиасинги". А разрабы это проглотили и ничуть не возмутились. А должны были.

P. S. Обнаружил в OpenTK няшные функции для матриц, почти как GL-ные. Это, конечно, не расчет-через-видеокарту, но тоже неплохо.
>> No.9320 Reply
>>9318
> И что, опять теперь всем проходить этот путь: C -> C++ -> STL -> .NET & Python (перефразирую: C -> говно с классами -> библиотеки классов -> говно с рантаймом & скриптовня) - только теперь уже для видеокарт?
man nvidia CG
>> No.9322 Reply
>>9320
Ну, вот, собственно, уже началось. Этап Assembler -> C пройден. И да, на обоих этапах человечество умудрилось наплодить под сотню диалектов, причем еще более разительно отличающихся, чем для CPU. Нет, ждать этапа C -> C++ (а скорее всего, будет не C++, а на порядок более вонючее говно) я не собираюсь. Сваливаю со сраной планеты, спиздив сраный шаттл.
>> No.9366 Reply
File: priznak_koshkosti_15.jpg
Jpg, 34.41 KB, 580×180 - Click the image to expand
edit Find source with google Find source with iqdb
priznak_koshkosti_15.jpg
Ложная тревога, братюни. Сегодня поговорил с человеком и пришел к выводу, что запихивать целиком весь Крузис в видеокарту - это не круто, потому что:
- видеокарта заточена под обсчет картинок; на логике это такой же сраный кусок кремния, как и x86;
- в типичном Крузисе видеокарта и так дымится от нагрузки, а тут ее еще дополнительным кодом загружать, да на который она не рассчитана.

Так что правильно не весь Крузис писать на шейдерах, а только часть, отвечающую за рендеринг. А логику, физику (если нет PhysX), ИИ и пр. лучше писать для CPU. Он под эти вещи лучше заточен, да и средства для этого адекватные есть.

Алсо, сегодня увидел Crysis 2. От тамошнего Солнца, просвечивающего сквозь деревья, кончил радугой. Как они так сделали, блядь!?
>> No.9367 Reply
>>9322
Возьми Лисп @ напиши DSL.
>> No.9403 Reply
>>9367
> Возьми Лисп @ напиши DSL @ получи ссаные 16 fps в 2011 году на втором варкрафте.
Поправил.
>> No.9407 Reply
>>9318
Прогресс для экономики важен лишь как вторичный продукт переработки сырья, которое надо видоизменять, чтобы его продолжали хавать. После того, как Страуструп изобрёл свои «Си с классами», потому что ну нельзя уже было в мозгу держать десятки тысяч строк кода, никакого прогресса в программировании по сути и не происходило. По крайней мере я не заметил наличие чего-то столь важного и полезного. Майкрософт пишет жирные операционные системы, чтобы они могли тормозить и на новом железе, как бы естественно стимулируя производителей этого самого железа толкать хардварный поезд вперёд.
>> No.9410 Reply
>>9407
> После того, как Страуструп изобрёл свои «Си с классами»
> никакого прогресса в программировании по сути и не происходило.
Затопил жиром.
>> No.9411 Reply
File: 1301354489730.jpg
Jpg, 11.70 KB, 220×220 - Click the image to expand
edit Find source with google Find source with iqdb
1301354489730.jpg
>>9410
Ну хорошо, я затапливаю жиром тред, а ты запруживаешь память мемликами из своей джавы. Таки я безвреднее.
>> No.9414 Reply
>>9403
Ты дидил, да? Вся задача сиподобного говна для CUDA - один раз транислироваться в оссёмблер видеокарты, осесть там и пропускать через себя петабайты информации. И в общем-то похуй на чем это будет написано и сколько микросекунд займет трансляция. Просто педерастам больше нравится сишка, нормальные люди выберут более удобные инструменты.
> После того, как Страуструп изобрёл свои «Си с классами» .. никакого прогресса в программировании по сути и не происходило.
Прогресс обусловлен сочетанием социальных и технологических факторов. У опущенцев-байтоёбов прогресса не происходило, потому что С++ - это их верхняя планка, нормальные программисты давно ссут им в рот и смеются над убогими.
>> No.9416 Reply
>>9414
> сосут им в рот
Ай фолд
>> No.9446 Reply
>>9414
> нормальные программисты
Байтоёбы написали все существующие unix-like оси. А что написали «нормальные программисты»?
>> No.9451 Reply
>>9446
Нормальные программисты 40 лет назад создали инструменты для байтобов, а сейчас создают то, чем будут пользоваться потомки байтоёбов спустя еще 40 лет.
>> No.9457 Reply
>>9451
Все и так будут пользоваться С следующие 40 лет.
>> No.9459 Reply
>>9457
Ибо ваистену!
>> No.9462 Reply
>>9457
Не все, только быдло будет им пользоваться.
Но так как быдла большинство, тебе, быдлу, будет казаться, что все.
>> No.9463 Reply
>>9135

А теперь, няша,

1) берёшь и качаешь:

http://sourceforge.net/projects/irrlicht/files/Irrlicht%20SDK/1.7/1.7.2/irrlicht-1.7.2.zip/download

2) Затем, с умным лицом внимательно изучаешь исходники.
3) Рвёшь волосы себе на голове.
4) ??????
5) PROFIT!
>> No.9464 Reply
>>9463

Затем, когда осилишь, переходишь на:

http://sourceforge.net/projects/ogre/files/ogre/1.7/ogre_src_v1-7-2.exe/download
>> No.9465 Reply
>>9463
> The Irrlicht Engine is an open source high performance realtime 3D engine written and usable in C++
> C++
Дальше не читал.
>>9464
То же.
>> No.9466 Reply
>>9463>>9464

Да, поскольку ты дудкоёб, то сразу рекомендую тебе:

http://mogresdk.googlecode.com/files/MogreSDK_1.7.1_beta_r72.exe


И да, впредь настоятельно рекомендую тебе хоть немного изучить ту предметную область, в которую собрался лезть. Ты бы ещё под голое железо начал программировать и баттхёртил про "БЛЯДЬ, ГДЕ МОЙ СИШАРП, ПОЧЕМУ ТУТ КАКИЕ-ТО БАЙТЫ И ВООБЩЕ, КАКОГО Я В ДРЕВНЕМ 16 БИТНОМ РЕЖИМЕ 8086, У МЕНЯ ЖЕ ЁБАННЫЙ КОР АЙ СЕМЬ????!!!!!!!!"
>> No.9467 Reply
>>9465
>>9466

И да, научись впредь выбирать инструменты под стать твоим задачам. Да, вот ещё, если ты принципиально настроенный "дотнет и ниипёт", то майкрософт специально для тебя запилила:

http://www.microsoft.com/downloads/en/details.aspx?FamilyID=9ac86eca-206f-4274-97f2-ef6c8b1f478f
>> No.9468 Reply
>>9465

И да, что поделать, все движки пишутся на сраных плюсах, поскольку дотнет не может в производительность и SSE интринсики, столь необходимые движку. Но ты не парься по этому поводу, для движков есть биндинги к нормальным языкам, движок это просто библиотека.
>> No.9469 Reply
>>9457

Альтернатив для системного программирования ещё не придумали, все прочие языки требуют для себя уже существующую операционную систему, новую на них не написать.
>> No.9470 Reply
>>9469
О, еще одно быдло в треде. Октуда же вы все лезете? Это вам в ваших шарагах в процессе ебли в жопу заставляют учить мантру, что альтернатив плюсам еще не придумали и на чем можно писать операционные системы?
>> No.9471 Reply
>>9469

Кроме разве что няшного форта. Но на нём, в случае написания бэкэнда ещё больше байтоёбство чем с сишкой и с асмом, потом правда становится гораздо выразительнее и можно строить ТАКИЕ ТО АБСТРАКЦИИ.
>> No.9472 Reply
>>9470

От скриптобыдла, не способного в риал ворлд слышу. А про плюсы я не говорил, плюсы точно так же не могут в системное программирование как и дотнет, поскольку требуют уже работающей системы управления памятью (то есть уже существующей части ОС).
>> No.9473 Reply
>>9471

И да, я тоже ненавижу плюсы. С чего ты взял что я за них агитирую? Использую жабу и скалу, когда нужно байтоёбство - JNI и педалю на сях с SSE интринсиками . К плюсам прикасаюсь только в том случае, если требуется плюсовая либа и нет биндингов.
>> No.9474 Reply
>>9472
Поиграй мне еще в телепатию, наркоман.
> плюсы точно так же не могут в системное программирование как и дотнет
Ох, бля, сколько фейла..
1. define истемное программирование
2. Проблемы с написанием системы управления памятью?
Не мудрено, что у такого долбоёба как ты, Си - единственный пригодный язык. Съеби нахуй в ужасе и не возвращайся.
>> No.9475 Reply
>>9473
> Использую жабу и скалу,
А, ну ты сразу бы так и написал, а то я дурак тебе отвечать стал, я же не знал, что ты permanently brain damaged.
>> No.9476 Reply
> Проблемы с написанием системы управления памятью?
Никаких проблем, лишь необходимость делать новый язык программирования, кастрируя старый. Например, убрать оператор new из плюсов и шарпа (поскольку у нас ещё нет системы, обеспечивающей функциональность ни оператора new ни garbage collector'a), запилив таким образом новый System C#.
> define истемное программирование
Золотце, ты? Не узнал в гриме. Опять жиды всю воду выпили и бесконечностью всю ночь пытали?

На всякий случай:

http://en.wikipedia.org/wiki/System_programming
>> No.9477 Reply
>>9475
> я дурак
Твоя самокритичность радует мою душу. Не переживай, осознание - это половина исцеления.
>> No.9478 Reply
> usually a low-level programming language or programming language dialect is used that
C#
> can operate in resource-constrained environments
-
> is very efficient and has little runtime overhead
+-
> has a small runtime library, or none at all
--
> allows for direct and "raw" control over memory access and control flow
+
> lets the programmer write parts of the program directly in assembly language
-

LISP
> can operate in resource-constrained environments
+
> is very efficient and has little runtime overhead
+
> has a small runtime library, or none at all
+-
> allows for direct and "raw" control over memory access and control flow
+
> lets the programmer write parts of the program directly in assembly language
+
>> No.9479 Reply
>>9476
> Никаких проблем, лишь необходимость делать новый язык программирования, кастрируя старый.
Про бутстрапинг быдло не слышало?
> http://en.wikipedia.org/wiki/System_programming
Ох, блядь, сам бы тот текст прочитал, может быть не так фейлил. Что мешает написать, например, системную программу disk defragmenter на любом языке с FFI? Кароче иди нахуй, быдло.
>> No.9480 Reply
>>9478
> LISP
> > has a small runtime library, or none at all
> +-
Чиго блять? А компилер с собой тащить кто-будет? А гребаную кучу свистелок, что определена стандартом?
>> No.9481 Reply
> Про бутстрапинг быдло не слышало?
Полагаю, что да, про этот самый "бутстрапинг" ты, кроме самого баззворда, ничего не слышал.
> Что мешает написать, например, системную программу disk defragmenter на любом языке с FFI?
А что мешает написать ядро операционной системы?
Ну например, как ты, даже с использованием FFI будешь переходить из реал мода в лонг мод, из него а из него заполнять таблицы страниц?
>> No.9482 Reply
Ах да, божественный портируемый самобутстрапящийся дуднет:

http://habrahabr.ru/blogs/DIY/116771/
>> No.9483 Reply
> Ох, блядь, сам бы тот текст прочитал, может быть не так фейлил.
Полностью согласен, если бы ты его читал и переходил по всем ссылкам, то ты бы увидел:

> The most basic types of system software are:
> The computer BIOS and device firmware, which provide basic functionality to operate and control the hardware connected to or built into the computer.
> The operating system (prominent examples being Microsoft Windows, Mac OS X and Linux), which allows the parts of a computer to work together by performing tasks like transferring data between memory and disks or rendering output onto a display device. It also provides a platform to run high-level system software and application software.
> Utility software, which helps to analyze, configure, optimize and maintain the computer.
>> No.9486 Reply
Блядь! Что вы наделали! Мой бложик!
>> No.9487 Reply
>>9486

Да, советую, скачай MOGRE. Посмотришь, как устроен движок хотя бы. Да и биндинги там няшные сделали, можно лямбдами обмазываться.

http://www.ogre3d.org/addonforums/viewtopic.php?f=8&t=13123
>> No.9490 Reply
>>9481
Блядь, какой же ты тупой пидарас. Т.е. сишку, по-твоему, делает системным языком то, что в ней нет встроенного оператора выделения памяти? А встроенный тип double и мат. операции тебя не смущают? А то, что память под локальные переменные выделяется тебя не смущает? Откуда она выделяется, со стека, блядь? Так вот, необходимость наличия стека тебя не смущает, пидарас? А на наличие аппартного говна, вроде picoJava ты как смотришь?

Если нужен менеджер памяти, то он, блядь, пишется. Хоть на ассемблере, хоть на сишке, если она доступна на целевой платформе. Потом от задачи управления памятью абстрагируются и используют более подходящие инструменты. Только полные пидарасы, вроде тебя, будут тащить за собой сишку до самого верха и писать на ней всякие дефрагментаторы и системные утилиты. И ведь таких пидарасов большинство, как ни странно. Выучили, блядь, мантру, что сишка язык для системного программирования, и дрочат на неё. И вот, феерия долбоебизма - программирование CUDA на сишке. Там совсем другая архитектура, и сишка там как корова в седле. Гораздо эффективнее было бы сделать EDSL на Хаскеле и генерировать им объектный код. Но нет, ёжики будут колоться, плакать, но продолжать есть кактус. И когда же они иведуться? Думал, многоядерность их погубит, ведь сишка нихуя не предназначена для многопоточного программирования. Но нет, лучше в дохуя раз увеличить затраты на разработку, и стойко переносить тяготы и лишения долбления в жопу. Да, если человек пидарас - то это на всю жизнь. Как же я всех вас ненавижу.
> Ну например, как ты, даже с использованием FFI будешь переходить из реал мода в лонг мод, из него а из него заполнять таблицы страниц?
Никак. И на твоей системной сишке тоже. Потому что в хуй86 для этого надо срать в CR0, а сишка не предоставляет доступа к регистрам. Но на EDSL-е можно было бы замутить специальные команды для этого, плюс всякие проверки, чтобы ими пользовались корректно, или вообще декларативное описание оборудования, чтобы это могло работать не только под хуем-86, но под любой платформой, где это имеет смысл. Так что иди нахуй, пидарас.
>> No.9491 Reply
File: priznak_koshkosti_16.jpg
Jpg, 32.86 KB, 525×166 - Click the image to expand
edit Find source with google Find source with iqdb
priznak_koshkosti_16.jpg
Да не нужны мне эти ваши движки! Мне вполне хватает сейчас голого OpenGL... ну, обернутого в OpenTK разве что. Просто я не ожидал, что в ентом вашем 3D все будет совсем не так, как я себе это представлял.

И да, я правильно поступил, выбрав OpenTK вместо UDK. В UDK тоже какие-то абстракции абстракций, а зачем мне изучать шило, которое вызывает мыло, когда можно изучить мыло (при том же уровне функциональности и скорости) - я не понимаю.
>> No.9493 Reply
>>9487
А, да, глянул. Ну, в общем, об этом я и говорил: абстракции абстракций, когда можно изучить исходные абстракции (при пока что одинаковом уровне функционала). И да, мне ОЧЕНЬ не понравилось, что кроме SceneManager и Entity есть еще ненужные SceneNode, TerrainSceneManager и еще куча разных классов. Но это, наверно, результат длительного и упорной ёбли с байтиками, да?
>> No.9494 Reply
> А встроенный тип double и мат. операции тебя не смущают?
А схуяли меня должен смущать общепризнанный и используемый в 99% архитектур IEEE 754?

> А то, что память под локальные переменные выделяется тебя не смущает? Откуда она выделяется, со стека, блядь? Так вот, необходимость наличия стека тебя не смущает, пидарас? А на наличие аппартного говна, вроде picoJava ты как смотришь?
Нисколько не смущает, выделяется она на этапе компиляции, а не в рантайме, требуя систему выделения памяти и уже работающие страницы (и механизмы высокгого уровня навроде GC, работающие поверх всего этого). Стек реализован аппаратно и доступен сразу же по включению cpu. На аппаратное говно никак не смотрю. Гугл на своём андроиде одно время выпячивал идею мультиплатформенных высокоуровневых сборок на своей жид-машине. В итоге оказалось что высокоуровневый байткод жидмашины и производительность - вещи совместимые лишь на кластере серверов, а на обычных клиентских устройствах не очень и им пришлось запилоивать NDK с сишкой.
> Только полные пидарасы, вроде тебя, будут тащить за собой сишку до самого верха и писать на ней всякие дефрагментаторы и системные утилиты.
Ты ерунду какую-то несёшь, никто наверх тащить ничего не собирается, я писал конкретно про ядро операционной системы.
> Думал, многоядерность их погубит, ведь сишка нихуя не предназначена для многопоточного программирования. Но нет, лучше в дохуя раз увеличить затраты на разработку, и стойко переносить тяготы и лишения долбления в жопу. Да, если человек пидарас - то это на всю жизнь. Как же я всех вас ненавижу.
А ты к золотцу присоединись, у него там жиды и математика с бесконечностью виноваты, тоже виноватых поищи.
> Никак. И на твоей системной сишке тоже.
`
asm("movl %ecx %eax");
`

Твоё же функциональное говно хотя бы от жид-машины с рантаймом для начала отвязать, а затем компиляторы запилить, не говоря уже про стандартизацию.
> Но на EDSL-е можно было бы замутить специальные команды для этого, плюс всякие проверки, чтобы ими пользовались корректно, или вообще декларативное описание оборудования, чтобы это могло работать не только под хуем-86, но под любой платформой, где это имеет смысл.
> EDSL
> EDSL
> EDSL
> EDSL
> EDSL
> EDSL
> EDSL
> EDSL
> EDSL
> EDSL
> EDSL
> EDSL
> EDSL
> EDSL
> EDSL
> EDSL
> EDSL
> EDSL
> EDSL
> EDSL
> EDSL
> EDSL
> EDSL
> EDSL
> EDSL
> EDSL
> EDSL
> EDSL
> EDSL
Вот я о том и талдычу, блядь. Нужно пилить новый язык.
>> No.9495 Reply
> ненужные SceneNode, TerrainSceneManager и еще куча разных классов
Тащемта, в геймдеве, для которого пишутся эти движки оно как раз таки нужно. Чем плох встроенный готовый функционал?
> Но это, наверно, результат длительного и упорной ёбли с байтиками, да?
Ну зато +300fps в сложных сценах, а не 10 fps в игре 1993 года.
>> No.9496 Reply
> 1995
фикс.
>> No.9497 Reply
>>9494
> выделяется она на этапе компиляции
Дибил что-ли? А stack overflow тоже только во время компиляци случается? mov ebs esp; sub esp <framesize>.
> GC
Какого GC, блядь?
> Стек реализован аппаратно
На каких именно аппаратах?
> я писал конкретно про ядро операционной системы.
Уже лучше. Т.е. Си не для системного программирования, а для написания ядер операционных систем. Осталось теперь дать определение ядра, и указать конкретную аппаратурную платформу. И написать небольшое отступление, что Си подходит только для тех ядер, которые необходимо нашпиговать buffer overflow и прочим говном.
> asm("movl %ecx %eax");
Ты дибил. Надо объяснять почему?
> Вот я о том и талдычу, блядь. Нужно пилить новый язык.
Программирование - это всегда изобретение новых языков. Только быдло вроде тебя этого не понимает.
>> No.9498 Reply
> Дибил что-ли? А stack overflow тоже только во время компиляци случается? mov ebs esp; sub esp <framesize>.
Чтобы он не случался, нужны механизмы начиная с уже написанной операционной системы и далее уровнем выше.
> Какого GC, блядь?
Ну того, который во всяких там хацкелях и дотнетах. Там ещё и жид-машина есть.
> На каких именно аппаратах?
ARM, x86, PowerPC, продолжать?
> Ты дибил. Надо объяснять почему?
Инлайн ассемблер - встроенная конструкция языка. Но если ты такой принципиальный, то специально для тебя я могу записать код машинными инструкциями в память с помощью указателя и джампнуться на него через указатель на функцию.

> что Си подходит только для тех ядер, которые необходимо нашпиговать buffer overflow и прочим говном.
А что, есть какое-то принципиально другое говно, где нет bufffer overflow? Ой, кажется, чтобы механизмы защиты от buffer overflow и прочие абстракции работали нужна уже существующая ОС и механизмы, работающие поверх неё (жид-машина например), пичалька :(.

> Программирование - это всегда изобретение новых языков. Только быдло вроде тебя этого не понимает.
А мне казалось, что программирование - это получение результата в виде работающего программного продукта, а это оказывается строительство костылей и велосипедов, да придумывание воздушных замков, бида бида. Да, повторюсь, присоединяйся к золотцу, ты с твоим подростковым максимализмом и неповторимо-уникальным видением этого мира для него прекрасная пара. Поженитесь, детей заведёте. И, на будущее, частое употребление слова "быдло" - явный признак подросткового максимализма.
>> No.9499 Reply
Подытоживая, хаскеёб слился по всем фронтам.

1) Представлений ни о си ни о работе компонентов компьютера в целом у него нет.
2) Языков, которые подходят для системного программирование хаскееб так и не назвал.
3) Можно написать EDSL - не язык. Можно яблоки на дмарсе растить. А если вырастить во рту грибы - то будет не рот, а целый огород.

Не люблю цитировать других людей, особенно невежественных мудаков, прикидывающихся троллями, вроде золотца, но, поскольку ты из одной с ним кодлы больных абстракционизмом головного мозга и проживанием в стране эльфов (как вариант, в стране безразмерных серверов, где мясо генерирует холодильник, а жид машины не тормозят), то вынужден констатировать:

Слив защитан.
>> No.9501 Reply
File: 4d778bbc4f1df7d9d86d15a04647125c.jpeg
Jpeg, 132.06 KB, 600×473 - Click the image to expand
edit Find source with google Find source with iqdb
4d778bbc4f1df7d9d86d15a04647125c.jpeg
>>9472
> плюсы точно так же не могут в системное программирование как и дотнет,
ЛОЛШТО?
> поскольку требуют уже работающей системы управления памятью
gxx смотрит на тебя с недоверием.

>>9473
> Использую жабу
Фу таким быть.

>>9474
> define истемное программирование
Дабл лолд.

>>9478
М. Лиспач в треде. Не прояснишь мне, если LISP это язык обработки списков (что мне кажется близко по смыслу к sed), но на одном из его диалектов написан целый емакс, можно ли на нём написать модуль для ведра, например?

>>9479
Зашкаливающая концентрация слова на букву «б» на квадратный метр заставляет меня сделать вывод, что ты работаешь за еду на чём придётся.

>>9480
Покажи мне их.

Дальше плывут сотни взаимоисключающих параграфов на волнах анальной контузии, так что от комментирования я воздержусь.
мимо не пишу на С/С++/Java/.НЬЕТ, но мне интересно
>> No.9502 Reply
>>9495
> Тащемта, в геймдеве, для которого пишутся эти движки оно как раз таки нужно. Чем плох встроенный готовый функционал?
Значит, мне нужно дойти до этого. Я в упор не понимаю, зачем так делать (хоть и понимаю, как этим пользоваться). Значит, пока поиграюсь с OpenGL-ем.
> Ну зато +300fps в сложных сценах, а не 10 fps в игре 1993 года.
Да-да, я про это и говорю.

ВНЕЗАПНО пришла в голову мысль, что нет, такая архитектура не может быть результатом ёбли с байтами. В моем самописном движке будет только один уровень абстракции (GameObject) и прямая работа с OpenGL ( { InitRendering, DisposeRendering } ), а в Ogre - как минимум 2, и нет прямой работы с видеокартой. Нет, мне точно надо дорасти до движков.
>> No.9503 Reply
>>9499
Просто пиши "БАМП".
>>9501
> Дабл лолд.
Перед мамой своей лолкай, пидарас. Как видишь стоило начать разбираться, выяснилось, что сишка ни для какого системного программирования не предназначена и даже из real в long на хуй86 в ней перейти нельзя.
> можно ли на нём написать модуль для ведра, например?
Можно.
> так что от комментирования я воздержусь.
Правильно, тем более тут на твои потуги всем пофиг.
>> No.9504 Reply
>>9503
Заткнись уже, задолбал.

Бедный мой бложик, превратили его в сральник...
>> No.9505 Reply
>>9504
Черт, какой же я толстый.
>> No.9506 Reply
>>9504
> Бедный мой бложик, превратили его в сральник...
Так всегда и бывает, когда ведешь блог на имиджборде, обедаешь в спальне, а режешь кроликов в ванной.
>> No.9508 Reply
>>9503
> сишка ни для какого системного программирования не предназначена
Да почему?
> и даже из real в long на хуй86 в ней перейти нельзя.
Ты про typecast или что имел ввиду?
> > можно ли на нём написать модуль для ведра, например?
> Можно.
Пруфы.
>> No.9509 Reply
>>9502

Тут всё дело вот в чём. Одна из задач графического движка (помимо представления высокоуровневого API и связки низкоуровневого говна в юзабельтные фичи) - оптимизация вывода данных перед отправкой на рендеринг, чтобы и токой-то грофон был и не тормозило. Для этого вся поебота с нодами и сценграфом и есть - это встроенное средство движка чтобы иерархически строить сцену и при рендеринге не отправлять видеокарте ненужные объекты.

А про шейдеры и почему все опять проходят этот путь эволюции языков - всё просто. На данный момент графические конвейеры видеокарт способны выполнять лишь небольшое количество инструкций за раз без снижения производительности, а, поскольку шейдерные программы и так получаются в полторы строчки, то ЯВУ городить смысла нет. Когда там появятся какие нибудь ёба жифорсы 900000000000000000000000 которые могут выполнять миллионы инструкций за фрейм, тогда и появятся ЯВУ для шейдеров. Но, благодаря консолям, сомневаюсь, что до этих времён доживём. Сейчас даже D3D10 в геймдеве не особо из за консолей используют, максимум пару фич поверх DX9 кода кинут.

Вот, кстати, книжка про движки (автор из Naughty Dog):

http://dl.dropbox.com/u/932520/GEA.djvu
>> No.9974 Reply
File: priznak_koshkosti_17.jpg
Jpg, 33.40 KB, 525×168 - Click the image to expand
edit Find source with google Find source with iqdb
priznak_koshkosti_17.jpg
Прочитал про текстурирование (пока не пробовал). В принципе, ничего сложного.

Попытался понять, как накладывать текстуры с оттенками (ну, как в Alien Shooter, монстриков делать синими, красными, зелеными и т. д.) и помял себе мозг об texture functions. Я так понимаю, это делают шейдерами, да?
>> No.10004 Reply
File: priznak_koshkosti_18.jpg
Jpg, 29.72 KB, 580×180 - Click the image to expand
edit Find source with google Find source with iqdb
priznak_koshkosti_18.jpg
>>9974
Начал изучать шейдеры. В принципе, ничего сложного.

Попытался понять, как работать с текстурами, и помял себе мозг...

Блядь, говно какое-то сделали, а не работу с 3D. Тонны каких-то искусственных сущностей: пайплайн, шейдеры, буферы - а про собственно 3D-графику и забыли, лол. Сплошная байтосодомия и особенности аппаратуры НА УРОВНЕ API, БЛЯДЬ! Вся архитектура видео-процессора, считай, жестко задана этим уёбищным API, а значит, ее нихуя не оптимизировать же! Нахуй так жить?
>> No.10015 Reply
> Вся архитектура видео-процессора, считай, жестко задана этим уёбищным API, а значит, ее нихуя не оптимизировать же!
Наоборот. Уёбищное API жёстко задано уёбищной аппаратной (а до появления 3д ускорителей - математико-идеологической) архитектурой (vertex processing->rasterisation->pixel processing), не изменявшейся со времён динозавров. Просто как факт - 3Д видео всегда делалось ради игр. Большинство профессиональных карточек - допиленные игровые. Сейчас, с потерей актуальности писигейминга производители с помощью темы с GPGPU пошли в конверсию своей игровой продукции для других сегментов рынка. Я вот, тащемта, тоже считаю, что сканлайно-ориентированная "вертекс-растер-пиксель" игровая архитектура GPU времён 90х себя изжила и нужно срочно хоронить существующие GAPI.

> Тонны каких-то искусственных сущностей: пайплайн, шейдеры, буферы - а про собственно 3D-графику и забыли, лол.
Сущности вполне естественные - железки в видеокарте. К сожалению. Вертекс-растер-пиксель архитектура уже давно устарела, но, в силу исторических причин её тянут и тянут.
> Сплошная байтосодомия и особенности аппаратуры НА УРОВНЕ API, БЛЯДЬ
На то оно и низкоуровневое, высокоуровневая поебота слишком специфична для разных областей применения 3D, например в играх нужен риалтайм и полигоны считать, в твёрдотельном моделировании полигоны вообще нахуй не сдались, там детали проектировать надо а не деревьями любоваться и.т.д. За высоким уровнем - к игровым движкам и прочим библиотекам.


Резюмируя:

1) Поздравляю, ты ознакомился с рудиментами 90х годов, которые, увы, оставляют след и в устройствах сегодняшнего и завтрашнего дня, тормозя таким образом прогресс.

2) Традиционную архитектуру 3D GPU - закопать. Растеризаторы из видеокарты выкинуть нахуй.

3) GPGPU - развивать. Больше компиляторов и языков. 3D графика должна стать одной из множества прикладных задач универсального GPGPU, а не единственной задачей, под которую точится железяка железо.
>> No.10016 Reply
>>10004

А вообще, поздравляю, это второе, на моей памяти, сжигающее жопу неизбежное несовершенство нашего IT мира. Первое - штеуд86.
>> No.10017 Reply
И да, говорю же - не мучайся ты, блджад!

http://www.microsoft.com/downloads/en/details.aspx?FamilyID=9ac86eca-206f-4274-97f2-ef6c8b1f478f
>> No.10024 Reply
File: priznak_koshkosti_19.jpg
Jpg, 35.76 KB, 580×180 - Click the image to expand
edit Find source with google Find source with iqdb
priznak_koshkosti_19.jpg
>>10017
Он только под Винду. И, говорят, он немного уебищноват. Уж лучше UDK тогда или Ogre какой-нибудь. Кстати, да, я таки постепенно дорастаю до движков.

Тем временем я еще почитал про шейдеры. С превеликим удивлением обнаружил, что в них никак (вообще никак) не прочитать то, что отправилось во фреймбуфер. Только срать туда. Нет, не так. В ЭТОМ ВАШЕМ OPENGL НИКАК, БЛДЖАД, НИКАК НЕ ПРОЧИТАТЬ ТО, ЧЕМ ТЫ НАСРАЛ ВО ФРЕЙМБУФЕР. И чтоб это было эффективно. То есть, все мои цветовые фильтры, гауссовы размывания, "потемнение в глазах" и прочее НОРМАЛЬНО** в OpenGL не реализуешь, только через какую-то анальную жопу.

И, кстати, я эту жопу как раз и нагуглил: мужики предлагают аттачить фреймбуфер-обджект к текстуре, срать в этот обджект, потом использовать полученную текстуру для обратной связи и, соответственно, для рендеринга окончательной картинки. Но это, по-моему, изврат даже для OpenGL. Или нормально?
>> No.10047 Reply
>>10024
> Или нормально?
>>10015
> Наоборот. Уёбищное API жёстко задано уёбищной аппаратной (а до появления 3д ускорителей - математико-идеологической) архитектурой (vertex processing->rasterisation->pixel processing), не изменявшейся со времён динозавров. Просто как факт - 3Д видео всегда делалось ради игр. Большинство профессиональных карточек - допиленные игровые. Сейчас, с потерей актуальности писигейминга производители с помощью темы с GPGPU пошли в конверсию своей игровой продукции для других сегментов рынка. Я вот, тащемта, тоже считаю, что сканлайно-ориентированная "вертекс-растер-пиксель" игровая архитектура GPU времён 90х себя изжила и нужно срочно хоронить существующие GAPI.
У современной GTX 580 по прежнему такая же архитектура как и у Вуды из середины 90х. Только непрограммриуемую железную логику наложения текстур и обработки полигонов заменили на кучу программируемых DSP ядер (которые и представляют эти ваши шейдеры). Всё как и с Х86 - костыли времён динозавров. Только если в случае интелей их можно как-то оправдать (поддержка легаси-говна), то в случае GPU - оправданий не найти.
>> No.10048 Reply
>>10047
> У современной GTX 580
сегодня выбирал себе видюху чтобы во 2 ведьмака порезаться
GTX 590 - 20.000
GTX 580 - 14.000
GTX 570 - 10.000
охуел от цен и взял себе 570
>> No.11120 Reply
Ебать-топтать какой экземпляр - воинствующее плебейство. Пеши ишо и побольше
>> No.11130 Reply
>>11120

Байтокуртизанка закукарекала?
>> No.11132 Reply
>>11120
В контакт, быдло.
>> No.11178 Reply
>>11132
Да пофиг куда, лишь бы ОП писал ещё.
>> No.11181 Reply
>>11178

Судя по большому времени или у опа и вправду мало времени (что характеризует его с хорошей стороны), либо он и вправду усердно корпит над небайтоблядским движком (что было бы вообще охуитительно, хотелось бы аналог http://jmonkeyengine.com/ под .NET). В любом случае ОП - няша, а байтоблядям и прочим адептам бога-машины
   - вафлю за щеку и перо под ребро.

Машина должна и будет служить людям, она не шлюха, чтобы люди исполняли её прихоти. Отсюда байтобляди - пиздолисы, которые опускаются до полного говноедства, лишь бы ублажить её регистры и микросхемы. Альфапрограммисты, как и положено альфам, если машина не выполняет положенных ей задач и требует пресмыкаться перед ней и ублажать её байтами, просто берут и за патчкорды, ебашат с вертушки по передней панели и списывают машину на мороз, купив взамен ту, которая не будет выёбываться и выполнит код в сроки и без выебонов, будь там хоть 1000% неоптимизированного оверхеда.
>> No.11198 Reply
File: computers_are_racist-425x188.jpg
Jpg, 33.45 KB, 425×188 - Click the image to expand
edit Find source with google Find source with iqdb
computers_are_racist-425x188.jpg
Поржал с треда. Давно не видел такого мощного баттхерта дурачка-неосилятора.
>> No.11199 Reply
>>11198
> баттхерта
Туда ли ты зашел, боброкодер?
>> No.12832 Reply
File: priznak_koshkosti_20.jpg
Jpg, 28.70 KB, 580×180 - Click the image to expand
edit Find source with google Find source with iqdb
priznak_koshkosti_20.jpg
Маки-тред переезжает сюда.

Ну так вот:
  
ILiving:
  IEnumerator<int> Live()  -- MoveNext() у возвращаемого
    энумератора заставляет этот ILiving проживать один такт.
    Если MoveNext() вернуло false, то этот ILiving считается
    сдохшим и автоматически удаляется отовсюду.
  
IRenderable:
  void Render(/* RenderingContext */)  -- рендерит этот
    объект на RenderingContext. В случае с OpenGL никакого
    RenderingContext не будет (он глобальный).
  int RenderingPriority  -- IRenderable с более низким приоритетом
    рендерятся первыми.
  
ILivingRenderable : ILiving, IRenderable.
  
GameObject : ILivingRenderable:
  GameWorld GameWorld { get; set; }
  -- Тута будет набор координат, скоростей и прочего.
  -- Над этим набором надо будет подумать. Может,
  -- вообще выкинуть нахуй, пусть юзер сам решает.
  Vector2D Pos { get; set; }
  Vector2D Direction { get; set; }
  virtual void Render(/* RenderingContext */)  -- собственно,
    рендеринг. В задачи этого метода также входит загрузка
    ресурсов (см. класс Resource ниже).
  
Camera : GameObject:
  Camera(Screen screen)  -- создает камеру
    и привязывает его к screen. То есть, камера как бы
    является полноценным игровым объектом: летает в нем,
    крутится, вертится - и все, что "видит", рендерит на screen.
    В ее задачи входит вызвать Render у world-а.
    В качестве Screen будет выступать GameWindow.
  int RenderingPriority { get { return Integer.MIN_VALUE; } }
  virtual void Render(/* RenderingContext */)  -- Render() у
    World-а так или иначе вызовет этот метод. В задачи метода
    Render() у Camera входит настройка координат, шейдеров
    и прочего, то есть, подготовка RenderingContext-а.
  
GameWorld : ILivingRenderable:
  GameWorld()
  GameWorld(Timer)  -- создает мир, который будет "жить" (вызывать
    MoveNext() у энумератора, который вернет Live()) по каждому
    тику от переданного таймера.
    В качестве таймера будет выступать GameWindow.
  void Add(GameObject)
  void Add(IRenderable)  -- это типа статические объекты,
    шейдеры и партикли.
  void Remove(Object)
  -- Надо не забыть, что операции добавления и удаления должны быть
  -- отложенными: они должны реально выполняться, только когда очередной
  -- цикл Live() полностью завершится. Иначе будет
  -- ConcurrentModificationException.
  void Render()  -- тупо вызывает Render() у всех добавленных
    объектов (с учетом RenderingPriority()!).
  int RenderingPriority { get { return ПОХУЙ; } }
  IEnumerator<int> Live()  -- MoveNext() у этого энумератора тупо
    форвардится соответствующим энумераторам всех добавленных объектов.
  
  Resource:
    void Load() или void EnsureLoaded()  -- загружает этот ресурс,
      если он еще не загружен.
    protected void Unload()  -- выгружает этот ресурс, соответственно.
      А protected потому, что Resource сам выгрузку ресурсов.
    Resource(Action load, Action unload)  -- это чтоб подклассы
      каждый раз не писать.
    -- Плюс много разных утилит для загрузки спрайтов, вертекс-буферов,
    -- шейдеров и прочего.
  -- Рекомендуется делать ресурсы статическими объектами внутри классов
  -- игрообъектов:
  --
  -- class Bullet : GameObject
  -- {
  --    ...
  --    private static Resource Sprite = new Resource(
  --        () => { LoadSprite("Bullet.png") },
  --        () => { UnloadSprite("Bullet.png") }
  --    );
  --    ...
  --    public void Render()
  --    {
  --        Sprite.Load();
  --        ...  // А тут уже рендерим как обычно.
  --    }
  -- }
Еще надо подумать над наследованием: я хочу, чтобы GameObject и GameWorld были наследуемыми, и при этом наследники бы знали бы друг о друге. То есть, чтоб, например, бомбе (GameObject-у) не приходилось бы даункастить свой GameWorld до DestructableGameWorld. Или чтоб этот же движок можно было применять не только для OpenGL, но и для рогаликов (с рендерингом в Console).
>> No.12834 Reply
>>12832
> рендер прямо в объекте
> каждый объект со своим рендером
Я больше не хочу делать с тобой движок.
>> No.12838 Reply
>>12832
В чем смысл энумератора в ILiving?
>> No.12854 Reply
File: priznak_koshkosti_21.jpg
Jpg, 68.64 KB, 580×395 - Click the image to expand
edit Find source with google Find source with iqdb
priznak_koshkosti_21.jpg
>>12834
Ну, зачем же так сразу? Предложи вариант получше. Единственный плюс моего варианта - это "все в одном месте": все, что относится к данному GameObject-у, лежит в нем, и не надо лазить по проекту, чтоб собирать его по кускам. Больше плюсов нет.

>>12838
public IEnumerator<int> Live()
{
    Move(Direction.RIGHT, 1);
    yield return похуй;
    Move(Direction.UP, 1);
    yield return похуй;
    Move(Direction.LEFT, 1);
    yield return похуй;
    Move(Direction.DOWN, 1);
    yield return похуй;
    // Сдох.
}
И еще, я тут подумал: операция Remove() получается со сложностью O(n). И еще я забыл предусмотреть разбитие уровней на зоны. Короче, хуёво получилось, буду еще додумывать (уже есть одна идея). Но основная суть останется такой же: есть Мир, есть Объекты, их логика задается одной функцией на континуациях, Камера - такой же игрообъект, как и все остальные. Также слушаю ваши предложения, может, у вас есть еще удобней архитектура. И, главное, быстрей.
>> No.12855 Reply
File: 6bd43cd2723a2d756...
Jpg, 81.47 KB, 563×800
edit Find source with google Find source with iqdb
6bd43cd2723a2d756d5d47fbf493336994e47829.jpg
File: DobrochanTest.rar
Rar, 1.09 KB, 0 files
view
DobrochanTest.rar

>>12854
Вот накодил по-быстрому то, что ты надумал.

Идеея "все в одном обьекте" для небольшой игры сойдет.
Идею с энумераторами не понял. А если понадобится изменять состаяние не по определенной последовательности, а учитывая окружающую обстановку — то перепрыгивать между елдами? (так вообще возможно?). Или, например, местоположение надо обновлять каждый фрейм на протяжении всей игры — не писать же 100500 елдов. Я бы предложил просто enum с состоянием (спавнимся, двигаемся, дохнем), свитч в Live() и флаг isAlive, по которому определяется, существует ли обьект.
А вот загрузку ресурсов лучше делать не в обьекте, а в загрузках уровней.

Приделаю какой-нибуть спрайтик — выложу.
>> No.12856 Reply
File: 3256703.png
Png, 117.71 KB, 389×500 - Click the image to expand
edit Find source with google Find source with iqdb
3256703.png
>>12854
И еще вопрос.
> void Add(IRenderable) -- это типа статические объекты,
> шейдеры и партикли.
IRenderable обрабатываются в той же очереди, что и GameObject или в разных?
Чем партиклы хуже обычных обьектов? Для "статических" обьектов, можно не городить огород, а просто оставить пустой Live().
При чем тут шейдеры? Если они будут выполнятся в общей очереди, то это сгодится разве что для полноэкранных эфектов. Плюс их надо выключать, т.е. иметь пару обьектов и следить за их RenderPriority. Я бы отдельно сделал их загрузку, а включение в самих методах Render(), если уж вся отрисовка там.
>> No.12862 Reply
>>12854
Рендер это рендер, а абстракции объектов - абстракции объектов.
Рендер должен заниматься рендером, а не объекты.
А если ты решишь что-то поменять, то будешь в каждом объекте менять? Я сам наткнулся на те же грабли и судорожно переписывал.
>> No.12868 Reply
Отлично. Завтра отвечу. С кодингом не торопитесь, пока думаем.
>> No.12879 Reply
File: priznak_koshkosti_22.jpg
Jpg, 32.08 KB, 580×180 - Click the image to expand
edit Find source with google Find source with iqdb
priznak_koshkosti_22.jpg
>>12855
> идея с энумераторами
Ну, по сути, Live() - это корутина. А yield return - это pass (переключение на следующую корутину). Просто в Сярпе нет корутин, поэтому приходится эмулировать их таким вот образом.
От состояния я отказался сразу, потому что в терминах состояний простые последовательности ("двигайся 1 секунду прямо, потом 2 секунды направо") выглядят как говно. А в случае корутин state-машина получается чем-то вроде частного случая. И вообще, меня во всех движках бесило именно то, что поведение описывается как-то через жопу вместо простой и понятной императивной последовательности (пусть даже разбавленной pass-ами).
>>12856
> IRenderable обрабатываются в той же очереди, что и GameObject или в разных?
В разных... Но
> можно не городить огород, а просто оставить пустой Live().
Я боялся накладных расходов на лишний вызов. :-[

Шейдеры как отдельные объекты будут выполняться в общей очереди и будут использоваться для полноэкранных эффектов. Шейдеры для отдельных объектов будут использоваться внутри самих объектов:
class BigShip : GameObject
{
    ...
    void Render()
    {
        BlinkingShader.Activate();
        BlinkingShader.SetUniformVariable("time", World.Time);
        ShipSprite.Render();
        BlinkingShader.Deactivate();
    }
}
Этого достаточно будет?

>>12862
Это верно. Плюс еще MVC, декомпозиция, все дела... Но я не представляю, как можно отделить рендер от логики, не получив ситуацию, когда каждый объект требует два класса, описывающих его. А чем плохи GameObject-ы с пустым Live(), которые занимаются только рендерингом?

>>12855, код
- RenderingPriority() меняться не будет. Это надо будет прописать в комментах.
- deltaTime лучше вынести куда-нить в глобал. В тот же GameWorld.
- "GameWorld - наследник GameWindow" - это фейл. Ну, не фейл, но у меня в голове от этого загорелась красная лампочка: "противоречие здравому смыслу". GameWindow - это окно. Дисплей камеры. А GameWorld - это мир. Просто мир, никак с нашим миром не связанный. Так что если и делать кого-то наследником GameWindow, то это Camera.
> // Предлогаю ввести GameObject target , за которым будет следовать камера.
Это будет сделано отдельной рутиной. Как и эффект тряски. Камера должна быть полностью подконтрольной программисту. И да, можно будет делать ее подклассы.

Текущие проблемы:
- Сложность операции GameWorld.Remove() O(n), если не ухудшать остальные характеристики. Можно, конечно, сделать и меньше, но на клоне Beat Hazard любой Remove(), который больше O(1), положит процессор на лопатки.
- Зонирование. Никак. Не предусмотрено. Либо живут и рендерятся все объекты разом, либо ни одного.

Новое предложение:
  
// Это... Жизнь и существование (равно как и смерть и исчезновение) -
// вещи разные. Объект может быть мертвым, но существующим.
  
abstract class ExistingRenderableObject
{
    public ExistingRenderableObject() { ... }
    public IEnumerator<пох> Existence
    {
        get { ... }
        protected set { ... }   // А это позволит менять поведение объекта извне,
           // а также позволит удалять его без использования GameZone.Remove().
           // А изначально поведение задается в конструкторе.
    }
    public abstract int RenderingPriority();
    public abstract void Render();
    // Примеры мутаторов поведения:
    public void Remove()
    {
        Existence = Disappear();
    }
    public void Freeze()
    {
        Existence = StayStill();
    }
    protected static IEnumerator<пох> Disappear()
    {
        yield break;
    }
    protected static IEnumerator<пох> StayStill()
    {
        while (true) yield return пох;
    }
}
  
abstract class GameObject : ExistingRenderableObject
{
    // Заметка: я тут параллельно предлагаю ввести разбиение мира на зоны.
    
    public GameZone Zone { get {...} set {...} }
}
  
class GameZone : GameObject
{
    public GameZone() { ... }
    public GameZone(Timer /* то бишь, GameWindow */) { ... }
    public virtual IEnumerable<ExistingRenderableObject> Objects { get; }  // Забыл прошлый раз. :-[
    public virtual void Add(GameObject);
    // А Remove() не будет. Такие дела. Хочешь удалить объект - убивай его.
    public virtual int RenderingPriority() { return 0; }
    public virtual void Render() { ... }  // Тупо вызывает Render у всех Objects.
}
  
// GameRoom могут быть вложенными, это позволит разбить игровой мир на зоны.
// Но проблема все равно остается: если игрок переходит из одной
// комнаты в другую, надо перетащить его в другую GameZone (вместе с камерой),
// а Remove() у GameZone нет.
  
class Camera : GameObject
{
    public Camera(Screen /* то бишь, GameWindow */) { ... }
    ...
    // Задача камеры - рендерить GameZone, в которой она лежит.
}
UPD: А, не, все равно ксепота: при вот такой структуре:
            RoomZone1
          /
WorldZone - RoomZone2
          \
            RoomZone3
все RoomZone будут жить одновременно, потому что им всем будет передан GameWindow (и они все подпишутся на его OnUpdate).
>> No.12884 Reply
File: 10946277.png
Png, 124.52 KB, 600×600 - Click the image to expand
edit Find source with google Find source with iqdb
10946277.png
>>12879
Все равно полезность елдов для меня сомнительна. Ладно, отложим на потом.
Кстати, если безразлично, что возвращает энумератор, то луче делать его не шаблонную версию (без <тип>) и возвращать null.
> BlinkingShader.SetUniformVariable("time", World.Time);
> "time"
При обращении по имени оно каждый раз парсит текстовый файлик шейдера. Лучше при создании шейдера определять индексы юниформов, атрибутов и обращаться по ним.

У меня компромиссное решение между рендер в одном объекте и рендер где-то далеко. Можно сделать для однотипных действий(отрисовка спрайтов, партиклы) менеджеры в GameWorld, а в GameObject обращаться к ним:
Render()
{
  GameWorld.SpriteManager.RenderSprite(/*тип спрайта, координаты…*/);
  GameWorld.ParticleManager.RenderParticle(/*тип, координаы…*/);
}
А затем в менеджерах это все будет сортироваться, группироваться в VBO и только потом одним вызовом отправляться на отрисовку.
> - "GameWorld - наследник GameWindow" - это фейл. Ну, не фейл, но у меня в голове от этого загорелась красная лампочка: "противоречие здравому смыслу". GameWindow - это окно.
Логика логикой, но класс GameWindow это не только графический контекст, но и, по сути, точка входа, классы Mouse, Keyboard и множество виртуальных функций и перенаправлять это все в GameWorld — это абстракция ради абстракции. Разве что можно сделать GameWorld объектом-контейнером для всех игровых объектов внутри GameWindow, но основной цикл и отрисовка должны быть в GameWindow.
> - Сложность операции GameWorld.Remove() O(n)
Ну можно использовать связные списки — удаление будет быстрее. Доступ по индексу все равно не требуется. Плюс при добавлении объекта не требуется сортировка, а только вставка в конкретное место.

Над зонами попозже подумаю.
>> No.12886 Reply
>>12879
> я не представляю, как можно отделить рендер от логики, не получив ситуацию, когда каждый объект требует два класса, описывающих его.
Достаточно просто: рендерить все объекты одинаково. Там вообще не нужно ооп. В объекте достаточно хранить упоминание о том, что он где-то там рендерится, а рендер, в свою очередь, вообще не должен знать, что где-то там есть какие-то объекты.
> GameZone
> Render()
У тебя еще и в каждой зоне свой рендер штоле?
> Задача камеры - рендерить GameZone, в которой она лежит.
> камеры
> рендерить
А у тебя есть объекты, которые не занимаются рендером? Или рендер - суть твоей игры?
>> No.12888 Reply
File: JBGwdg5604mn2.jpg
Jpg, 39.44 KB, 450×600
edit Find source with google Find source with iqdb
JBGwdg5604mn2.jpg
File: priznak_koshkosti...
Jpg, 36.53 KB, 580×180
edit Find source with google Find source with iqdb
priznak_koshkosti_23.jpg

>>12884
Спрайты - это ресурсы:
class Sprite : Resource
{
    private int TextureID;
    private string FileName;
    private int Width;
    private int Height;
    
    public Sprite(String fileName)
    {
        FileName = fileName;
    }
    
    protected void Load0()  // Реализация public void Load() { ... }
    {
        using (Bitmap bitmap = new Bitmap(FileName))
        {
            this.TextureID = GL.GenTexture();
            this.Height = bitmap.Height;
            this.Width = bitmap.Width;
            GL.BindTexture(TextureTarget.Texture2D, this.TextureID);
            BitmapData data = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, ...
        }
    }
    protected void Unload()
    {
        GL.UnbindTexture(TextureTarget.Texture2D, this.TextureID);
        ...
    }
    
    public void RenderAt(float X, float Y)
    {
        ...
    }
}
  
class Fighter : Object
{
    private static FighterFlyingSprite = new Sprite("fighter/flying.png");
    private static FighterLandingSprite = new Sprite("fighter/landing.png");
    ...
    public void Render()
    {
        if (Flying)
        {
            FighterFlyingSprite.Load();   // Или лучше EnsureLoaded();
            FighterFlyingSprite.RenderAt(this.X, this.Y);
        }
        else
        {
            FighterLandingSprite.Load();
            FighterLandingSprite.RenderAt(this.X, this.Y);
        }
    }
}
Причем смари, когда ты делаешь ресурсу Load(), он автоматически делает Unload() ресурсам, которые не использовались и просто занимают место. То есть, в него внутри встроен ResourceManager. Я сначала думал сделать ResourceManager отдельным классом, но потом сообразил, что его можно запихнуть внутрь Resource в качестве статического элемента.

Для общих ресурсов можно сделать так:
class SharedResources
{
    public static Sprite StandardEnemyBullet = new Sprite("bullet.png");
    public static Sprite Explosion = new Sprite("explosion.png");
    public static Shader BrightnessUp = new Shader("brightness_up.glsl");
}
> GameWindow
Понимаешь, я хотел на этом же движке написать еще один консольный тетрис и, может быть, рогалик. Через класс Console.
> можно сделать GameWorld объектом-контейнером для всех игровых объектов внутри GameWindow, но основной цикл и отрисовка должны быть в GameWindow.
Да. Просто у GameWorld и Camera будут удобные конструкторы, которые этот самый GameWindow подготовят, настроят и запихнут туда основной цикл и отрисовку.
> - Сложность операции GameWorld.Remove() O(n)
Проблема возникает, когда во врага летит 100 пуль, и одна из них попадает и решает удалить врага из мира. Вот в этом случае Remove(GameObject) получается O(n) даже на связанном списке: чтобы найти нужный GameObject, нужно пробежаться по всему списку. Я выкрутился так: напрямую удалять объекты из мира нельзя, но можно подменить корутину GameObject.Existence у удаляемого объекта на DisappearImmediately. Тогда во время очередной пробежки по объектам GameWorld посчитает, что этот объект завершил свое существование (Existence.MoveNext() вернет false) и удалит его.
>> No.12889 Reply
>>12888
Ой, тама
 class Fighter : GameObject
>> No.12891 Reply
File: 5144726.png
Png, 1038.29 KB, 1050×1000 - Click the image to expand
edit Find source with google Find source with iqdb
5144726.png
>>12888
> Спрайты - это ресурсы:
> public void RenderAt(float X, float Y) …
Ну значит здесь обращение к менеджеру спрайтов. Главное сократить количество обращений к видеокарте. Использование VBO дает выигрыш в 1-2 порядка по сравнению с отрисовкой каждого спрайта по отдельности.
> один консольный тетрис и, может быть, рогалик. Через класс Console.
Боюсь представить количество костылей и/или слоев абстракции, что бы один движок работал и через OpenGL и через консоль. Я бы не заморачивался и остановился на чем-то одном.
> - Сложность операции GameWorld.Remove() O(n)
Что при обычном, что при связном списках удаление будет происходить где-то в основном цикле при переборе объектов и проверке Existence. В методе GameWorld.Remove() для данного обьекта просто какой-нибудь флаг устанавливается в false. У себя в коде я таки не правильно сделал. Только в обычном списке оно О(n) не по тому, что надо пробегаться по всему списку, а по тому, что при удалении элемента создается новый массив и в него копируются все элементы кроме удаленного, чего нет в связном списке.
class Fighter : Object
{
    private static FighterFlyingSprite = new Sprite("fighter/flying.png");
    private static FighterLandingSprite = new Sprite("fighter/landing.png");
    ...
    public void Render()
    {
            FighterFlyingSprite.Load();   // Или лучше EnsureLoaded();
Опять же, ресурсы должны загружаться до первого вызова, при загрузке уровня. Я склоняюсь к единому менеджеру ресурсов.
> GL.UnbindTexture
Нету там такого :3

Я начинаю подумывать в сторону >>12886 .
>> No.12894 Reply
File: priznak_koshkosti_24.jpg
Jpg, 19.65 KB, 580×180 - Click the image to expand
edit Find source with google Find source with iqdb
priznak_koshkosti_24.jpg
А этого братюню я пропустил, сорри.
>>12886
> Достаточно просто: рендерить все объекты одинаково. Там вообще не нужно ооп. В объекте достаточно хранить упоминание о том, что он где-то там рендерится, а рендер, в свою очередь, вообще не должен знать, что где-то там есть какие-то объекты.
Не могу себе это представить. Приведи пример, плиз. Или это общие слова, предлагаешь мне самому подумать?
> > GameZone
> > Render()
> У тебя еще и в каждой зоне свой рендер штоле?
Да, но он наследуется от GameZone. То есть, он общий для всех гейм-зон. Но его можно перегрузить, если надо.
> А у тебя есть объекты, которые не занимаются рендером?
Теоретически, да. Render может быть пустой, тогда это получается невидимый объект. И наоборот, если Existence у объекта равно StayStillForever, тогда это просто рендерилка какая-нибудь.

>>12891
> Использование VBO дает выигрыш в 1-2 порядка по сравнению с отрисовкой каждого спрайта по отдельности.
Стоп. Не понял, ты предлагаешь всю сцену запихнуть в один VBO?
Я изначально рассчитывал, что каждый объект в идеале будет рендериться одной-двумя командами: GL.ВыставитьТекущуюТекстуру(Спрайт); GL.ВыставитьViewAndModelMatrix(...); GL.ОтрисоватьVBO(БуферСКоординатамиТекстурыСпрайта). Не так?
> В методе GameWorld.Remove() для данного обьекта просто какой-нибудь флаг устанавливается в false
Я изначально тоже так же хотел сделать, и это, кстати, более простой вариант для реализации, но мне не нравилась лишняя проверка. В моем варианте GameWorld будет проверять только MoveNext() на false, а так - еще и флаг Removed.
> Опять же, ресурсы должны загружаться до первого вызова, при загрузке уровня.
На первом такте GameWorld сначала вызовет у всех добавленных объектов Existence.MoveNext(), а потом Render()-ы, которые прогрузят все нужные ресурсы (у них там у всех будет SomeResource.Load() стоять, который при загруженным ресурсе будет ничего не делать). Не катит?
> Я склоняюсь к единому менеджеру ресурсов.
Он и есть, просто он зашит как статический объект в классе Resource.
> > GL.UnbindTexture
> Нету там такого :3
Ну, я условно.
> Боюсь представить количество костылей и/или слоев абстракции, что бы один движок работал и через OpenGL и через консоль. Я бы не заморачивался и остановился на чем-то одном.
Давайте так: пока что, по моим прикидкам никаких дополнительных слоев вводить не надо. Если понадобится что-то там наворачивать - дропаем. Просто оглядка на нее немного дисциплинирует мозг.
> Я начинаю подумывать в сторону >>12886 .
Я тоже, но я не совсем его понимаю.
>> No.12898 Reply
>>12894
> Я изначально рассчитывал, что каждый объект в идеале будет рендериться одной-двумя командами: GL.ВыставитьТекущуюТекстуру(Спрайт); GL.ВыставитьViewAndModelMatrix(...); GL.ОтрисоватьVBO(БуферСКоординатамиТекстурыСпрайта). Не так?
А если у тебя этот спрайт используют несколько объектов? Предлагаю тебе сгруппировать рисуемые примитивы в некоторые сущности так, чтобы этой каждой сущности соответствовала одна из загруженных текстур. Например
[code]vertexBuffer
{
   triangle *triangles;
   texture *texture;
}[/code]
И потом рисовать эти буфера с помощью вершинных массивов или VBO.
первый раз у вас здесь, интересно, я зафейлю разметку?
>> No.12909 Reply
File: 3094290.jpg
Jpg, 205.58 KB, 781×876 - Click the image to expand
edit Find source with google Find source with iqdb
3094290.jpg
>>12894
> Не понял, ты предлагаешь всю сцену запихнуть в один VBO?
В идеале да. При загрузке ресурсов, менеджер создает текстурный атлас(одна большая текстурка содержащая все используемые); затем, при вызове рендера, определяются текстурные координаты, создается один массив для VBO. Ну или, как минимум, отдельный VBO для всех объектов использующих данную текстуру, как пишет >>12898. Для фона и неподвижных объектов можно держать отдельный VBO с параметром StaticDraw и вообще его не обнавлять, а только отрисовывать. Но это уже тонкости…
> На первом такте GameWorld сначала вызовет у всех добавленных объектов Existence.MoveNext(), а потом Render()-ы, которые прогрузят все нужные ресурсы (у них там у всех будет SomeResource.Load() стоять, который при загруженным ресурсе будет ничего не делать). Не катит?
Костыль же.
> Я тоже, но я не совсем его понимаю.
А я кажеться начинаю понимать. Этот подход вроде бы называется "объект, как чистая композиция или агрегация".
Т.е. у тебя есть несколько классов, производных от одного, отвечающих за рендеринг однотипных объектов: один — просто спрайтик, второй — спрайт + партиклы, итд. Дальше, при создании экземпляра твоего GameObject'а в нем создается один из вышеописанных классов и определяются его параметры(какая текстура, где и когда генерить партиклы…) и уже ссылка на экземпляр этого класса добавляется в список рендерМенеджера.
Тоже самое можно проделать с физикой, озвучкой, скриптами итд.
Т.е. сам GameObject содержит ссылки на классы, которые определяют поведение объекта, и эти ссылки роздаются в соответствующие обработчики. Если обьект не нуждается в отрисовке/расчете физики/…, то соответствующая сылка = null, и в обработчик она не отправляется.

>>12898
Две вот такие ковычки ` до кода и после.
>> No.12912 Reply
>>9490
> И вот, феерия долбоебизма - программирование CUDA на сишке. Там совсем другая архитектура, и сишка там как корова в седле. Гораздо эффективнее было бы сделать EDSL на Хаскеле и генерировать им объектный код.
Среди диванных экспертов новая мода
>> No.12921 Reply
>>12894
> Не могу себе это представить. Приведи пример, плиз.
Ну возьми любую опенсорсную игрушку, которую разрабатывают достаточно долгое время, чтобы они уже прошли через этап твоих костылей и переписали движок, потому что при таком раскладе он давал 3 фпс при 4-х опенглных кубах в сцене. Я бы привел свой код, но я застраял на этапе переписывания, и дело пока не движется.
> GL.ВыставитьТекущуюТекстуру(Спрайт); GL.ВыставитьViewAndModelMatrix(...); GL.ОтрисоватьVBO(БуферСКоординатамиТекстурыСпрайта)
Оно у тебя просядет еще на первом этапе, если будет каждый спрайт по отдельности рисовать.
>>12909-кун все правильно говорит,
> При загрузке ресурсов, менеджер создает текстурный атлас(одна большая текстурка содержащая все используемые); затем, при вызове рендера, определяются текстурные координаты, создается один массив для VBO.
Только вот меня давно терзает вопрос, а какой максимальный размер создаваемого атласа? Или 2к*2к пикселей - это мерки 98 года и сейчас все не так?
>> No.12934 Reply
Стоп. То есть, правильно делать так:
- создается два буфера: один с координатами на текстурном атласе, другой - с координатами спрайтов на экране;
- каждый объект меняет свой кусок второго буфера;
- потом оба буфера разом отправляются на видяху. Вернее, только второй, первый (с текстурным атласом) загружается один раз.
Я правильно понял?
>> No.12957 Reply
File: 1404447.jpg
Jpg, 279.41 KB, 700×919 - Click the image to expand
edit Find source with google Find source with iqdb
1404447.jpg
>>12934
Не совсем.
Каждый вертекс состоит из Vector2D координаты и Vector2D текстурные координаты (если нужен цвет и/или прозрачность, то + Vector4D для цвета). При отправке объекта на отрисовку, в буфер добавляются 4 вершины(если это просто один спрайт), координаты которых вычисляются исходя из положения объекта, а текстурные координаты исходя из типа текстуры и данных менеджера. Это все хранится как массив структур. И далее это все отправляется на видяху.

>>12921
> Только вот меня давно терзает вопрос, а какой максимальный размер создаваемого атласа? Или 2к*2к пикселей - это мерки 98 года и сейчас все не так?
GL.GetInteger(GetPName.MaxTextureSize, …) возвращает 8192x8192. Как по мне, достаточно.
>> No.12966 Reply
>>12957
> Как по мне, достаточно.
Что-то я сомневаюсь, но воможно, я излишне беспокоюсь, все равно сейчас спрайтов даже не четверть не наберется. С другой стороны, даже если таких штук будет две, то это все равно значительно снизит потери при перебинде.
А как сейчас насчет упаковки разноразмерных картинок в текстурные атласы? Я помню, писал какой-то костыль, но он был самопальный и расчитан был на то, что максимальный размер поля не известен и нужно создать наименьшее со степенью двойки в сторонах. Но я подозреваю, что уже давно кто-нибудь написал что-нибудь намного более оптимальное, а я просто его тогда не нашел.
>> No.12969 Reply
>>12966
> А как сейчас насчет упаковки разноразмерных картинок в текстурные атласы?
А хз. Думаю сам написать.
> наименьшее со степенью двойки в сторонах
Вроде бы степень двойки уже давно не обязательна практически во всех случаях.
>> No.12970 Reply
>>12969
> степень двойки уже давно не обязательна
Это уже скорее традиция, да и проще с ней работать, чем с непонятным числом.
>> No.12971 Reply
>>12957
Так, падажи, ёбана. А если я захочу обложить отдельный объект шейдером? Например, сделать корабль мигающим синим цветом?
>> No.12976 Reply
>>12971
Лучшей идеей будет тогда все делать на шейдерах.
>> No.12977 Reply
>>12971
Ну делать отдельный VBO со всем остальным для каждого шейдера.
Алсо, мигание синим цветом и цветом вершин сделать можно. Та и вообще, шейдеры для отдельных объектов в 2D — это понты для приезжих.
>> No.13005 Reply
File: priznak_koshkosti_25.jpg
Jpg, 36.31 KB, 580×180 - Click the image to expand
edit Find source with google Find source with iqdb
priznak_koshkosti_25.jpg
Ну, про мигание синим цветом я так, к примеру сказал. Можно же и бампмаппинг какой-нить захотеть, и хромирование, и все, что угодно.

Похоже, над OpenGL3D-ускорителем понадобится еще один уровень абстракции. Голым им пользоваться вообще невозможно.

Появилась еще одна идея: делать отдельно логику, отдельно рендеринг. То есть, тотальный MVC. Логика будет в GameWorld, GameObject, Camera и др., а рендеринг будет в отдельном методе, который будет "видеть" GameWorld. Плюсы: максимальная гибкость в рендеринге. Минусы: GameObject-ы - отдельно, их рендеринг - отдельно. Буду эту идею развивать параллельно с основной. Если вы не найдете в ней фатальных недостатков, конечно.

Идея >>12976-куна мне нравится. Тем более, как сказал >>9310-кун, в OpenGL постепенно выкидывают всё и оставляют только их. Но я в упор не представляю, как можно весь рендеринг увести в шейдеры. Наверно, нужно будет какое-то комбинаторное shader API.
>> No.13007 Reply
>>13005
> GameObject-ы - отдельно, их рендеринг - отдельно.
Я еще раз повторяю, это плюс, а не минус. Тебе этот рендеринг дальше рендеринга и не нужен, зачем его тащить в объекты и крутить тормозяшие абстракции?
>> No.13008 Reply
>>13005
В 2D, где нет освещения и угол обзора постоянный, от шейдеров толку не много.
Кстати, что мы делаем то? В смысле концепт игры и как это все выглядеть должно. Возможно, шейдеры и не потребуются вовсе. Я бы сначала оценил, что нам действительно потребуется, а не внедрять все идеи подряд, потому что это модно, стильно, молодежно.
>> No.13009 Reply
File: 1314201295236.png
Png, 1.54 KB, 300×20 - Click the image to expand
edit Find source with google Find source with iqdb
1314201295236.png
Я тут подумал, поскольку вы отчасти пишете то же, что и я, хотя и на другом языке, я бы хотел поворовать ваш код, взамен принеся свои наработки(2/3 рендера, кое-какие идеи по организации интерфейсов, мира, конфиги и редактор) и, возможно, какие-то патчи. Как с вами можно контактировать?
>> No.13030 Reply
File: priznak_koshkosti_26.jpg
Jpg, 32.75 KB, 580×180 - Click the image to expand
edit Find source with google Find source with iqdb
priznak_koshkosti_26.jpg
>>13008
Пока делаем только движок, потому что игр будет далеко не одна. Но, возможно, ты и прав, не стоит гнаться за универсальностью. Тем более, что задача риалтайм рендеринга еще не решена (иначе бы не было такого зоопарка движков). Можно вообще сделать так: написать первую игрушку качественно, модульно, а для второй просто взять куски кода из первой. С вариантом >>13007-куна это вроде как прокатывает.
>>13009
Контактируем прямо через этот тред. Только, я смотрю, аноны тут сидят по вечерам, а я пташка ранняя. Надо что-то с этим делать.

Не знаю, решен ли вопрос с рендерингом или нет (от вас и ваших мыслей зависит, братюни), но однозначно есть вопрос: как разбивать игровой мир на зоны? Предположим, рендерингом занимается вообще отдельный модуль, который никак ни с кем не контактирует. Так вот, задача разбиения на зоны звучит примерно следующим образом. Имеем огромный игровой мир, но на игровой процесс влияют только объекты, находящиеся в некоторой окрестности игрока. Остальные объекты можно не обрабатывать вообще, и это ни на что не повлияет. Как это сделать?
>> No.13033 Reply
File: 1314268454176.png
Png, 1.50 KB, 300×20 - Click the image to expand
edit Find source with google Find source with iqdb
1314268454176.png
>>13030
Я так понял, что в этом треде нас всего трое, да и вроде спешки никакой нет, мой проект живет 3 год в альфа-состоянии, и вроде как здравствует.
> как разбивать игровой мир на зоны
Я пытался реализовывать что-то вроде регионов в виде квадратов размером 30-50к клеток(тайтлы 32*32) в ребре(я так его и не тестировал, поэтому не знаю оптимального количества, может вообще достаточно 10к), каждый из которых имел свой конфиг, в котором описывается ландшафт, объекты и всякая разная ерунда. У каждого региона есть какой-то определенный оффсет, благодаря которому они состыкуются друг с другом и расчитывать глобальную(общемировую) позицию достаточно просто.
> но на игровой процесс влияют только объекты, находящиеся в некоторой окрестности игрока
Я генерю и уничтожаю объекты на расстоянии одной камеры от игрока. На самом деле тут все упирается в производительность. Разумеется, нет смысла рисовать объект в далеке от камеры, но можно придумать объектам какую-то особо легкую абстракцию, которая может, предположим, двигаться, и превращать в нее объект при значительном удалении, это даст какое-то подобие живого мира, вот только я не уверен, насколько оно нужно.
>> No.13036 Reply
File: 3122967.jpg
Jpg, 222.77 KB, 1000×800 - Click the image to expand
edit Find source with google Find source with iqdb
3122967.jpg
>>13033
> Не знаю, решен ли вопрос с рендерингом или нет (от вас и ваших мыслей зависит, братюни)
Вот что я надумал. Перед началом их работы(при загрузке лвла) указывается, какие текстуры нужны. Загружаются текстуры, создаются текстурные атласы(тут еще надо учесть, что могут быть текстуры, которые уже состоят из нескольких секций). Объекты отправляются на отрисовку каждый фрейм, дальше упаковка и отрисовка одним вызовом.
Проблема разбиения на зоны лежит точно не на графическом модуле — просто объекты вне некоторой области просто удаляются из обработки "основной" логикой. Тут стоит учесть, что видяха сама неплохо справляется с отсечением объектов вне зоны обзора, поэтому сильно беспокоится я бы об этом не стал.
Тут хотелось бы уточнить функциональность рендера: надо ли изменение цвета, масштабирование, вращение спрайта?
Кстати у меня сомнения по поводу камеры. Инициализация графики в камере не совсем логично, ведь может потребоваться ре-инициализация при изменение размера окна или переключении в фулскрин, т.е. при событии OnResize игрового окна. Я б где-то там и запихнул все это. Плюс особого профита в наследовании от GameObject не вижу. Ведь у камеры все-таки особый статус. В любом случае она будет существовать все время работы приложения, иметь n камер нет смысла. Обращаться к ней необходимо многим подсистемам, поэтому всё равно придется держать её в "глобальной" области видимости.

И еще, не вкурсе, возможно ли получить размеры пикчи, без полной её загрузки через new Bitmap(<fileName>)? Хотелось бы перед созданием атласа сначала определить местоположение всех текстур в атласе и его размеры, а уже потом силами видеокарты рендерить их в атлас, как в фрейм буфер.

Начинаю потихоньку продумывать все это. Может к выходным будет пре-альфа версия :3

>>13033
> мой проект живет 3 год в альфа-состоянии, и вроде как здравствует.
Не юккури случайно?
>> No.13047 Reply
>>13036
Они и есть, я думаю, код ты найдешь. Наиболее свежая часть с отрисовкой карты(хотя и она заброшена на стадии атласов и не доведена до ума, того же VBO так и не реализовал, хотя планировал), объекты рисуются через зад.
> возможно ли получить размеры пикчи, без полной её загрузки
Я прописываю в конфигах каждый спрайт, например. Т.е. размер спрайта и их количество для каждого объекта, при этом каждый объект может иметь разный размер. Мне кажется, не стоит использовать всю картинку.
> камеры
Камера у меня относится к рендеру настолько же, насколько и конфиги интерфейса. Объект камеры - по сути абстракция, которая каждый цикл двигает видимую область сцены, если это необходимо. Получилась довольно интересная штука, которую можно цеплять к объектам, например, и поле видимости будет двигаться вместе с ними.
C ресайзом опять же никаких проблем, ибо достаточно просто вызвать установку режима со сбросом параметров.
>> No.13075 Reply
File: priznak_koshkosti_27.jpg
Jpg, 38.43 KB, 580×180 - Click the image to expand
edit Find source with google Find source with iqdb
priznak_koshkosti_27.jpg
>>13033
> как разбивать игровой мир на зоны
Я вот тоже склоняюсь к квадратным регионам, но не могу сообразить, как это сделать инкапсулированно. Можешь код, там, или объектную модель привести?
UPD: Уже не надо. Немного поприменял мозг, лол. Отдельный объект класса Zones будет отслеживать положение игрока и создавать/уничтожать объекты в зависимости от их удаления. А уж как он там будет определять достаточную степень удаления - это уже его проблемы. Хоть через квадратные регионы, хоть через октодерево, хоть через черта лысого.
>>13036
> надо ли изменение цвета
Либо полноценные шейдеры, либо ничего. Ну, может, полупрозрачность еще. ИМХО.
UPD: А что если
loop {
    отрендерить обычные объекты;
    активировать шейдер "некий эффект";
    отрендерить объекты с эффектом "некий эффект";
}
? Сильно это уроет производительность?
> Нужно ли масштабирование, вращение спрайта?
Да.
> Инициализация графики в камере не совсем логично, ведь может потребоваться ре-инициализация при изменение размера окна или переключении в фулскрин, т.е. при событии OnResize игрового окна
Та самая первая моя задумка была такая: камера пусть хоть что делает: подписывается на события в GameWindow, настраивает его, патчит, да хоть на голову встает - но чтоб картинка была отрендерена и отрендерена правильно. "Вот тебе GameWindow, вот тебе GameWorld. Чтоб через 5 секунд я на экране видел все GameObject-ы. Все ясно? Выполнять!"
В задумке, где рендеринг делается в отдельном методе, все это теряет смысл.
> Плюс особого профита в наследовании [камеры] от GameObject не вижу.
Потом можно будет унаследоваться от нее и реализовать ей тряску, например. Или цеплять к объектам, как делает >>13047-кун. А еще можно создать n камер и сделать кооперативный мультиплеер за одним компом или (!) порталы.
> Обращаться к ней необходимо многим подсистемам, поэтому всё равно придется держать её в "глобальной" области видимости.
Много чего придется держать в "глобальной" области видимости, причем разные вещи в зависимости от игры. Например, игрока. Это не страшно, главное, чтоб соответствующие геттеры (class World { propery Camera Camera { get; } property Player Player { get; } }) не работали слишком долго.

Текстурные атласы предлагаю компоновать на стадии компиляции. Художник рисует png-шки, а специальный препроцессор потом делает из них "texture-atlas.bmp" и "texture-atlas.idx" (возможно, несколько комплектов).

Резюме:

Идея 1: GameObject-ы, GameWorld; Camera - наследник GameObject. GameObject-ы содержат в себе и логику (Exist()), и рендеринг (Render()), и даже ресурсы.
Плюсы: Всё, относящееся к определенному объекту, сосредоточено в одном модуле.
Минусы: Нехилый abstraction penalty в рендеринге.
Предлагаемое решение: Передавать в Render() не голый GL, а некую абстракцию над ним. Эта абстракция будет накапливать в себе координаты вертексов и текселей, а потом все это будет сбрасываться на видео-карту.

Идея 2: То же, что и идея 1, но объекты представляют собой чистую композицию.
Плюсы: Всё, относящееся к определенному объекту, сосредоточено в одном модуле.
Минусы: Всё еще заметный abstraction penalty по рендерингу.

Идея 3: GameObject-ы и GameWorld содержат в себе исключительно логику, а рендерится все отдельным методом. Camera - некая абстракция, указывающая на текущую область видимости.
Плюсы:
- MVC.
- Максимальная скорость и гибкость в рендеринге.
Минусы:
- Опасность дублирования кода (как минимум, перечисление всех объектов надо будет делать и в логике, и в рендеринге).
- Нужно делать распознавание объектной модели (как минимум, надо будет определять, какой спрайт на данный момент соответствует данному объекту).

Вопросы в посте:
- Shader per object - медленно или приемлемо?
- Компоновка текстурных атласов на стадии компиляции.
>> No.13078 Reply
>>13075
> Текстурные атласы предлагаю компоновать на стадии компиляции
И я каждый раз, как захочу поменять картинку должен буду перекомпилировать? Лучше уж тогда это в какой-нибудь редактор выносить. Да и вообще, что тогда мешает рисовать все спрайты на одной картинке?
> перечисление всех объектов надо будет делать и в логике, и в рендеринге
Зачем объектов? Только структур, описывающих спрайты, не вижу дублирования в хранении массива спрайтов в рендеринге, а в объекте ссылок на этот спрайт.
> какой спрайт на данный момент соответствует данному объекту
это тоже решает.
>> No.13079 Reply
File: priznak_koshkosti_28.jpg
Jpg, 58.68 KB, 580×398 - Click the image to expand
edit Find source with google Find source with iqdb
priznak_koshkosti_28.jpg
>>13078
> И я каждый раз, как захочу поменять картинку должен буду перекомпилировать?
Ну, да, а что такого?
> Да и вообще, что тогда мешает рисовать все спрайты на одной картинке?
Координаты спрайтов на этой картинке. Как ты их указывать будешь?
>> No.13080 Reply
>>13079
> Ну, да, а что такого
Ты никогда этого не делал с проектами, которые компилируются больше пары секунд? Тебе надоест компилировать на 3 раз, когда ты всего лишь захочешь поменять немного один спрайт. Опять же попробуй объяснить это каким-нибудь художникам. Суть модульности в том, что изменения производить проще за счет того, что все вынесено. Почему бы тогда не собирать вообще все в один блоб, не хардкодить параметры, например?
> Координаты спрайтов на этой картинке
Прописываю в конфиге, УМВР. По сути картинка - лишь контейнер, туда можно напихать все что угодно, спрайты же ассоциируются с объектами при загрузке используя конфиги.

Да, меня последнее время мучает вопрос, если каждый объект загружать по отдельности, то как из них строить атлас. Пока решение вижу только в том, чтобы сначала подгружать ресурсы, собирая информацию о картинках, а потом загружать их. Идея с автоматической подгрузкой каких-то ресурсов кажется мне неудачной по той же причине. На ходу ресайзить/дорисовывать в атлас крайне неудачная идея.
>> No.13085 Reply
>>13080
А, так ведь никто не просит перекомпиливать весь проект на каждый чих. Художнику вообще достаточно только атласы пересобирать (и то только те, спрайты в которых он изменил).

Red alert! Прописывать координаты спрайтов ручками - это нахуй и в пизду. Машина - не шлюха, чтобы ей угождать.
>> No.13086 Reply
File: 14269.jpg
Jpg, 101.51 KB, 785×747 - Click the image to expand
edit Find source with google Find source with iqdb
14269.jpg
>>13085
> Художнику вообще достаточно только атласы пересобирать
Т.е. ты хочешь написать компилятор ресурсов, я так понимаю? Все равно, поменять один пиксель и потом компилировать, чтобы проверить - не столько отнимающее много времени, сколько раздражающее действие.
> Прописывать координаты спрайтов ручками - это нахуй и в пизду
Ты уже написал систему автоматического распознавания изображений, которая сама разложит спрайты по объектам? Или ты сделаешь 9000 картинок 32*32 и каждую ручками пропишешь? Посмотри какой-нибудь freedroid, там сделано именно так. Они прописывают каждую картинку, потом они загружают по одной картинке и собирают в кусок, не очень разумное решение(хотя и простое).
Да, и зачем ручками?
>> No.13095 Reply
>> No.13097 Reply
File: 7444327.jpg
Jpg, 3810.71 KB, 2480×3507 - Click the image to expand
edit Find source with google Find source with iqdb
7444327.jpg
Не вижу принципиальной разницы в реализациях: сборка атласа при компиляции и в рантайме. Один йух алгоритм одинаковый — почему бы и не собирать в рантайме? Главное что бы это происходило в специально отведенное для этого дела время, т.е. при загрузке лвла, локации итд, а то эффективно подгружать текстуры в уже собранный атлас врятле получится.

>>13075
> А что если…
Ну если уж тебе неймется воткнуть шейдеры, то можно сделать так:
где-то в рендерМенеджере:
// Список всех используемых шейдеров.
Shader[] shaders;

// Массив массивов. Величина первой размерности = кол-ву шейдеров, второй = необходимому кол-ву вершин для отображения объектов с использованием данного шейдера.
ObjectVertexes[][] vertices;
процесс рендеринга:
Atlas.Bind(); // один атлас на всех.
GL.Enable…    // для буферов.
for (int i = 0; i < shaders.Length; i++)
{
  // Причем нулевой шейдер можно оставить просто пустым с нулевым хендлом,
  // т.е. будет использоваться дефолтный конвейер. 
  GL.UseProgram(shaders[i].Handle); 
  // Тут установка юниформов.
  // Алсо, с атрибутами для каждой вершины возможно придется повозиться.
  GL.BufferData(…,ObjectVertexes[i].Length, ObjectVertexes[i],…); // Загрузка в буфер.
  GL.DrawArrays(…, ObjectVertexes[i].Length); // Отрисовка.
}
GL.Disable…
GL.UseProgram(0);
Atlas.Unbind();
Главное, что бы не отдельный шейдер на каждый объект и будет норм. И при добавлении спрайта в менеджер, придется добавить еще один параметр, определяющий шейдер.
Но я все еще не считаю шейдер чем-то необходимым. Ведь няшный анимированый спрайтик >>>> шейдеров, и я бы больше беспокоился, кто их будет рисовать.
>> No.13130 Reply
File: priznak_koshkosti_29.jpg
Jpg, 43.26 KB, 580×180 - Click the image to expand
edit Find source with google Find source with iqdb
priznak_koshkosti_29.jpg
>>13095
Знаю.
Знаю.
Знаю.
ЕБААААААААТЬ!!!
Полезно.
ЕБААААААААТЬ!!!
ЕББББААААААААААААААААТЬ!!!
Но ведь это же не мануал по видео-карте, это же просто практические приемы? Так сказать, шаблоны проектирования, да?
>>13097
Да.
>> No.13155 Reply
>>13130
Доделал отрисовку из атласа через VBO. В фулскрине 1000 спрайтов: через VBO — 333 fps, в immediate mode(Begin…End) — 205 fps; 10000 спрайтов: через VBO — 36 fps, в immediate mode — 22 fps.
Итого примерно 60% прирост fps. Ожидал большего. Либо я делаю что-то не так…
Завтра доделаю чють и выложу исходники.
>> No.13157 Reply
File: priznak_koshkosti_30.jpg
Jpg, 31.53 KB, 580×180 - Click the image to expand
edit Find source with google Find source with iqdb
priznak_koshkosti_30.jpg
>>13155
Если честно, для меня результаты более, чем ожидаемые. Если, конечно, ты рендеришь так, как я думаю. Ну, сам подумай, велика ли разница: отправлять каждый кадр 10000xN команд с координатами или 10000xN флоатов. Все равно все упирается в канал между видяхой и процом. Есть повод поизгаляться с шейдерами. Алсо, ты рендеришь треугольниками или полигонами?

Я тут подумал... Ну, камера-то ладно, а как мы будем спрайты вращать? Что, все 4 координаты спрайтов будем пересчитывать процессором? А как же матричные функции видяхи? Хнык-хнык?
>> No.13158 Reply
File: Безымянный.jpg
Jpg, 25.38 KB, 702×423 - Click the image to expand
edit Find source with google Find source with iqdb
Безымянный.jpg
Пожалуй тоже чего-нибудь с вами порисую.
Только на Хаскелем на html-ном canvas.

`module Main where
`
`import Language.HJavaScript.Syntax
`
`import HJScript
`import HJScript.DOM.Document
`
`import HJScript.Objects.Canvas
`
`script = do
` context <- inVar (getCanvas # getContext2D)
` context # fillRect (10::Float, 10::Float, 50::Float, 50::Float)
` where
` getCanvas = castObject $ v2e $ headArr $ document # getElementsByTagName (string "canvas")
`
`main = writeFile "Main.js" (show $ snd $ evalHJScript script)

Может олимпиаду какую-нибудь устроим?
>> No.13170 Reply
File: Main.png
Png, 12.23 KB, 640×480 - Click the image to expand
edit Find source with google Find source with iqdb
Main.png
<-- Кружочек на diagrams c бекэндом cairo.
Вернусь из банка, попробую прикрутить генератор джаваскрипта для canvas в качестве бэкэнда к diagrams.
>> No.13171 Reply
>>13170
Есть dia-functions с генератором SVG
>> No.13172 Reply
File: 0186c85e5ab2c4fe1b37ec757538a053e80731c1.jpg
Jpg, 453.59 KB, 2000×1411 - Click the image to expand
edit Find source with google Find source with iqdb
0186c85e5ab2c4fe1b37ec757538a053e80731c1.jpg
>>13157
Еще чуток поэкспериментировал. Таки в прошлый раз для VBO был не очень удачный случай. Я использовал спрайты 128х128 и они как бы покрывали экран в несколько слоев. Если же использовать спрайты небольшого размера, то в случае с VBO, fps возрастает в несколько раз, а в immediate mode — остается прежним. Плюс если сдвинуть камеру так, чтобы их было частично видно/не было видно, то опять же с VBO —fps растет, в immediate mode — остается прежним. Поэтому в некоторых случаях VBO обгоняет в разы.
> Ну, сам подумай, велика ли разница: отправлять каждый кадр 10000xN команд с координатами или 10000xN флоатов.
Дело в том, что флоат — это флоат, а команда — это: переключение режима + команда + флоат + переключение режима и так 10000xN раз. Да и скорость передачи шины видяхи измеряется гигабитами, и вроде как на переключение режимов тратиться больше времени, чем тупо на передачу данных.
Кстати, использовать флоаты или даблы?
> Алсо, ты рендеришь треугольниками или полигонами?
GL.DrawArrays(BeginMode.Quads, 0, spriteCount * 4);
> Что, все 4 координаты спрайтов будем пересчитывать процессором?
Я так и пересчитывал. Наличие или отсутствие всех этих преобразований ни на единичку не меняет фпс. Я бы по этому поводу не замарачивался. Менять матрицу под каждый спрайт будет не быстрее уж точно. Да и сами эти матрицы тоже вычислять надо.

Соображения по поводу текстур. Каждая пикча содержит, либо пачку текстур выровненных по сетке, либо одну текстуру(сетка в 1 колонку и 1 столбец). Каждая пикча, кроме имени файла, имеет имя, по которому к ней обращается программа; для повышения быстродействия, можно по имени получить индекс текстуры. Инфа об имени, колонках и столбцах хранится в скриптовом файлике.
Для скриптовых файликов сразу предлагаю XML. В NET есть парсер для них.
>> No.13173 Reply
>>13172
А почему не любой человеческий формат? Подозреваю, что для них тоже есть парсеры.
>> No.13189 Reply
File: 6841796.jpg
Jpg, 149.40 KB, 880×1024
edit Find source with google Find source with iqdb
6841796.jpg
File: DobrochanTest.rar
Rar, 1.97 KB, 0 files
view
DobrochanTest.rar

Доделал атлас и рендерМенеджер. Повысил IRenderable до абстрактного класса. Переделал GameObject и сделал пару примеров для рендерАспектов. F10 - фулскрин, правой кнопкой можно двигать камеру. Вверху виднеется собраный атлас. Алгоритм для построения атласа спер с http://blog.wonderville.ru/texture-atlas/ .

>>13173
Ну пусть будет любой человеческий, мне просто по этому поводу лень копаться.
>> No.13190 Reply
File: Безымянный.jpg
Jpg, 24.20 KB, 670×586
edit Find source with google Find source with iqdb
Безымянный.jpg
File: Main.png
Png, 13.34 KB, 640×480
edit Find source with google Find source with iqdb
Main.png

Прикрутил js бэкэнд к diagrams (пока прототип).
На картинках - cairo (стандартный) и canvas (мой).
Код диаграмы:
'dia = circle 1 # scaleX 0.5 # rotateBy (1/6)
Рендерится примерно так:
'main = do
' let carioResult = renderDia Cairo (CairoOptions "Main.png" (PNG (640, 480))) dia
' fst carioResult
' let canvasResult = renderDia canvas (CanvasOptions (640, 480)) dia
' writeFile "Main.js" $ renderBlock canvasResult
' where
' canvas = Canvas $ castObject $ v2e $ headArr $ document # getElementsByTagName (string "canvas")
(тут и JS и cairo)
На выходе получается примерно такой код:
'var var_0 = document.getElementsByTagName('canvas')[0].getContext('2d');
'var_0.save();
'var_0.translate(320.0,240.0);
'var_0.rotate(0.5235988);
'var_0.scale(355.00812,177.50406);
'var_0.arc(0.0,0.0,1.0,0.0,6.2831855,false);
'var_0.restore();
'var_0.stroke();
>> No.13191 Reply
File: Безымянный.jpg
Jpg, 188.68 KB, 1280×800 - Click the image to expand
edit Find source with google Find source with iqdb
Безымянный.jpg
>> No.13200 Reply
>>13191
Странно. Обнови дрова на видяху.
>> No.13209 Reply
>>13200
У меня хуйпоймикакая видяха. Но большинство игрушек на ней работает, что позволяет предположить, что ты используешь какие-то редкие функции.
>> No.13211 Reply
>>13209
Не такая уж и редкая. Написано, что поддерживается как расширение с 1.1 версии, и с 3.0 в самом openGL. Попробуй разные её варианты, например GL.Ext.GenFramebuffers, глянешь в обозревателе объектов кароч.
Что у тебя возвращает string version = GL.GetString(StringName.Version); ?
>> No.13223 Reply
Как мило, пекоразработчики знакомятся с пекопроблемами. Как эе хорошо что на соснолях и айфоне подобных проблем нет.
>> No.13224 Reply
>>13223
Откуда там им взяться, если всё вся платформа поставляется одним ональным хозяином?
>> No.13226 Reply
File: priznak_koshkosti_31.jpg
Jpg, 34.61 KB, 580×180 - Click the image to expand
edit Find source with google Find source with iqdb
priznak_koshkosti_31.jpg
Привет всем. Вчера угробил весь день и полночи на Iji, поэтому сейчас невменяем.

В итоге наш движок должен с легкостью держать http://rghost.ru/19804341 или Beat Hazard. Особое внимание хочу обратить на спрайты с полупрозрачностями в первом. UPD: Я так понял, с этим проблем нет, да?

Огромное спасибо >>13172-куну за тайминги.
> Кстати, использовать флоаты или даблы?
Зависит от требуемой точности. В логике - даблы, в отображении - флоаты (или вообще Half-ы), если требуется накапливание - лонг даблы.
> Для скриптовых файликов сразу предлагаю XML.
Лучше INI. Если парсер есть, конечно.

По поводу текстур: художник будет лепить спрайты отдельными файлами, программист будет обращаться к спрайтами по именам этих файлов. Я наизнанку вывернусь, но сделаю, чтоб это выглядело именно так (не без вашей помощи, конечно).

Атласы еще можно генерить функциями для работы с BMP-ухами. Как вариант. И еще, я так понимаю, построение атласа - это олимпиадная задача, да? "Дано n прямоугольников разных размеров; уложить их на прямоугольном поле как можно более плотно".

>>13223
А что, OpenGL ES устроен как-то принципиально иначе?

Пока все. Пойду проветриваться.
>> No.13227 Reply
>>13226

Так же, просто отсутствуют зоопаркопроблемы из серии "предусмотреть наличие и отсутствие фичанеймов в железе пользователей". Для андроида зоопаркопроблемы так же проявляются в полной мере, только к тому же ещё и железо никак не документировано, тк вендоры SoC чипов беспокоятся за сохранение своей анальной девственности. В итоге приходится гадать, какие мобилки с какими процессорами с какими фичами ходят нынче у народа по рукам. Большинство разработчиков по этой причине и пишут под айфон, т.к. всего 3 модели железа, подробно описанные в документации.
>> No.13228 Reply
>>13226
> > Для скриптовых файликов сразу предлагаю XML.
> Лучше INI. Если парсер есть, конечно.
В сисярпе есть linq для xml. Очень удобно.
>> No.13230 Reply
>>13226
> INI
Оно же примитивно и что-то хитрое им не описать.
> программист будет обращаться к спрайтами по именам этих файлов
Ну попробуй, я уже говорил, что это неудобный вариант. Придется разработать систему названий файлов и следить, чтоб они были правильно поименованы. Автоматизация этого видится мне какими-то крайними костылями.
>> No.13239 Reply
File: priznak_koshkosti...
Jpg, 37.39 KB, 580×180
edit Find source with google Find source with iqdb
priznak_koshkosti_32.jpg
File: Юленька1.jpg
Jpg, 90.69 KB, 577×600
edit Find source with google Find source with iqdb
Юленька1.jpg

>>13230

<оффтоп>
> > INI
> Оно же примитивно и что-то хитрое им не описать.
А сложного и не надо.
</оффтоп>

В любом случае, подгонять формат исходников спрайтов под формат, удобный OGL - это плохо. Пусть художники рисуют так, как им удобно. Умные программисты потом все приведут к чему надо.

>>13227
А разве в OGL ES нет функций вида "GL.GetFichaVersion(FichaName)"? Я же вроде видел такое.
>> No.13250 Reply
>>13226
> В итоге наш движок должен с легкостью держать http://rghost.ru/19804341
легко. Алсо, странно сделано: ограничение по фпс, но вертикальная синхронизация не включена.
> или Beat Hazard.
А вот это не плохо сделано, такое врятли осилим.
> в отображении - флоаты
В следующий раз переделаю все под флоаты.
> Лучше INI. Если парсер есть, конечно.
Я все еще настаиваю на XML.
> По поводу текстур: художник будет лепить спрайты отдельными файлами, программист будет обращаться к спрайтами по именам этих файлов.
Чем тебя не устраивает система, как в прошлых исходниках: имя файла и еще одно имя, по которому обращаться? А если пикчи будут лежать в разных папках, но иметь одно имя? Или понадобиться для тестов менять туда-сюда разные версии текстур — менять везде имена файла? А так имя файла отдельно, идентификатор — отдельно.
> Атласы еще можно генерить функциями для работы с BMP-ухами. Как вариант.
Не вариант. Они значительно тормознее. Плюс в оперативке картинки хранятся без сжатия, поэтому для заполнения максимально возможного по размерам атласа потребуется около 500мб.
> И еще, я так понимаю, построение атласа - это олимпиадная задача, да?
Это задача вида: "Вбей в гугл, выбери подходящее и подгони под свои нужды".

Теперь по поводу шейдеров. Что ты ими собрался делать. Всмысле, что потребуется шейдеру. Если нужны текстуры, то или добавлять их в атлас, или использовать мультитекстурирование. Или может какие-то дополнительные параметры для вершин. Наверно потребуется отдельные структуры и массивы для каждого шейдера. А если параметры будут сильно различаться, то и отдельная функция для добавления спрайта для каждого шейдера.
>> No.13258 Reply
>>13211
> Что у тебя возвращает string version = GL.GetString(StringName.Version); ?
2.1.7659 Release
>> No.13295 Reply
File: priznak_koshkosti...
Jpg, 68.93 KB, 580×398
edit Find source with google Find source with iqdb
priznak_koshkosti_33.jpg
File: 1282535696838.jpg
Jpg, 300.80 KB, 638×934
edit Find source with google Find source with iqdb
1282535696838.jpg

>>13250
> > или Beat Hazard.
> А вот это не плохо сделано, такое врятли осилим.
С чего бы? Там ж вроде только спрайты, партикли да пара полноэкранных шейдеров. Нет?
> Я все еще настаиваю на XML.
INI - это ассоциативный массив, сериализованный. Если структура конфига не подходит под сериализованный ассоциативный массив, то INI однозначно не подходит.
> Пикчи: имя файла и еще одно имя
Лишняя сущность. Один идентификатор уже есть - относительный путь к файлу (от папки с ресурсами) - зачем еще второй заводить? А наборы текстур можно переключать переименованием папок с ресурсами (например, рабочая папка называется "Resources", а тестовая - "Resources (Test)").
> Атласы еще можно генерить функциями для работы с BMP-ухами. Как вариант.
Естесственно, это для предварительной сборки атласов (будь то компиляция или первоначальная загрузка игры). Во время игры, между уровнями будут грузиться уже готовые атласы или в крайнем случае собираться как-нибудь быстрым алгоритмом (с использованием видяхи). Боже упаси заниматься сборкой атласов, когда игра уже запущена и готова к работе.

> Шейдеры.
Вот эту тему я бы хотел обговорить по-подробнее. Мне нужны два вида шейдеров:
1. Полноэкранный - помехи, размывание из-за скорости, инфракрасное зрение и т. п. Высший пилотаж (и потому пока не обязательный) - это учет обстановки в шейдерах. Например, одна из моих дальних задумок - это что-то наподобие http://www.indiedb.com/games/ranger/, но с гауссовым размыванием невидимых частей карты.
2. Пообъектный - "силовое поле", "хамелеон" (окраска объекта меняется в зависимости от окружения), "электрошок" и т. п.
Причем здесь возникает проблема: если для инфракрасного зрения или "силового поля" знать то, что уже нарендерено, не нужно, то в размывании из-за скорости или "хамелеоне" нужна своего рода обратная связь: нужно знать цвета пикселей позади объекта или около него. Я, кстати, по этому поводу уже матерился выше: в шейдерах никак нельзя узнать, что было нарендерено до них. Только пайплайн, только хардкор.

Короче, я к чему: может быть, нам вполне хватит и простых, однонаправленных шейдеров, но я в этом очень сильно сомневаюсь. Скорее всего, понадобятся полноценные. А единственный способ добиться полноценного "шейдинга", который я для себя открыл - это сначала нарендерить изображение без шейдеров в какую-нибудь текстуру, а потом пропустить эту текстуру через требуемый шейдер (с выводом на экран). Потому-то я и согласен полностью с тем, что лучше наклепать десяток няшненьких спрайтиков, чем трахаться с шейдерами - не потому, что трахаться придется долго (как раз наоборот), а потому, что это по вполне очевидным причинам уроет FPS.

С кодингом, повторюсь, торопиться не стоит. Как будет более-менее полноценный проект, так и закодим. Завтра, если здоровье позволит, выложу новый вариант архитектуры. <анонс>Я решил оставить Render(...) в GameObject-ах. Но рендерить они будут не в голимый OpenGL context, а в специальный контейнер (GLRenderingContext или GLScreen). Паттерн Visitor, короче.</анонс>
>> No.13296 Reply
Но за тайминги все равно спасибо.
>> No.13298 Reply
File: 2657722.jpg
Jpg, 85.82 KB, 429×600 - Click the image to expand
edit Find source with google Find source with iqdb
2657722.jpg
>>13295
> INI - это ассоциативный массив, сериализованный. Если структура конфига не подходит под сериализованный ассоциативный массив, то INI однозначно не подходит.
Вложенность лишней не будет, а ini не может в неё.
> Боже упаси заниматься сборкой атласов, когда игра уже запущена и готова к работе.
Я тебе гарантирую сборку максимально возможного атласа в рантайме, используя текущий алгоритм не более чем за секунду. В любом случае здесь "узкое горлышко" — это загрузка с винта.
> Шейдеры
Значит текстуры для них таки лучше держать отдельно.
Полноэкранные сделать относительно легко. Просто, перед рендерингом сцены, активируется фреймбуфер, а затем он используется как текстура для шейдера. Я бы рекомендовал обходиться только ими — и дешево и сердито. Единственная тонкость, это необходимо будет интерфейс рендерить после всего этого, отдельной пачкой.
А вот как красиво организовать пообъектные шейдеры да еще и с вышеописанными плясками, я затрудняюсь ответить. Пока попробую что-то попроще замутить.
> наподобие http://www.indiedb.com/games/ranger/
Где ты тут шейдеры увидел? Или видимость врагов ими определяется?

>>13258
> 2.1.7659 Release
Тогда не удивительно. По идее, если поменять все, что связано с фреймбуфером на EXT-версии, то должно работать:
GL.Ext.GenFramebuffers…
GL.Ext.BindFramebuffer…
GL.Ext.FramebufferTexture2D…
…
GL.Ext.DeleteFramebuffers…
>> No.13299 Reply
>>13298

предлагаю написать адаптер, который будет дёргать нужные функции в зависимости от капсов конфигурации железа. Лучше это всё как нибудь делегатами оформить, чтобы инициализировалось один раз и дальше без лишних ифов дёргалось.
>> No.13311 Reply
yaml, няши, yaml. И вложенность, и удобство редактирования руками - все есть.
>> No.13347 Reply
>>13295
Тред не читал, но няшу схоронил.
Спасибо, бро.
>> No.13389 Reply
File: priznak_koshkosti...
Jpg, 32.48 KB, 580×180
edit Find source with google Find source with iqdb
priznak_koshkosti_34.jpg
File: 13032944064531.jpg
Jpg, 75.07 KB, 402×604
edit Find source with google Find source with iqdb
13032944064531.jpg

Итак, цели создания движка:
1. Сделать API для видеокарты. Я не говорю о его юзабельности, черт бы с ней. Сейчас API вообще никакого нет (OpenGL и DirectX - это Ad, Pizdets & Iob tvoyu mat, а не Application Programming Interface).
2. Создать общий код для игр. Чтобы не приходилось каждый раз описывать игровой мир, объекты, реализовывать простейшие модели поведения и прочее.

Новый положняк: http://pastebin.com/ajD4Bfzt . Названия функций и классов надо рефакторить, это не окончательный вариант. GLScreen еще можно назвать RenderingContext. Еще есть вариант сделать GLScreen глобальным статическим классом и назвать его, я не знаю, GL2, там, что ли.

UPDATE: Только сейчас понял, что такая архитектура фейлит на лейаутах вида "экран в экране", то есть, например, когда на HUD есть минидисплейчик, который показывает происходящее в другом месте. Если честно, я склоняюсь к архитектуре "объекты отдельно, рендеринг отдельно". Но у нее есть критическая проблема: для пущей эффективности в объектах надо указывать, каким спрайтом они должны рендериться. Но тогда получается какое-то недо-MVC, когда отдельное представление вроде бы есть, но его куски валяются в модели.
UPDATE 2: Кажется, я начинаю понимать смысл MVC. Это не разделение кода на три независимых куска, а разделение логики на три независимых куска. Ничего плохого в том, что в модели хранятся некоторые "хинты" для отображения, как-то: номера мессаг, имена спрайтов, требуемые эффекты - нет. На поддержке это не скажется. А вот вплетение кода отображения в код бизнес-логики - это доказанные многолетним опытом IT-промышленности ад и погибель.

>>13172
> n спрайтов в одной пикче.
Есть два варианта:
1. Для пикч, содержащих n спрайтов всегда считается, что спрайты в них расположены в определенной сетке. В специальном конфиге, сопровождающем пикчу, будет описано, сколько спрайтов в ней содержится по горизонтали и вертикали. Исходя из этого будет рассчитываться размер одного спрайта и кол-во спрайтов. Обращение к отдельному спрайту будет происходить с указанием координат ячейки, в которой содержится спрайт. Например: "C:\BobroGame\Resources\Level 1\Player.png" имеет размер 1600x400 и содержит 4 спрайта. Обращение в программе ко второму спрайту будет выглядеть так: "Level 1\Player.png\1,0".
2. То же, но положение и размеры отдельного спрайта на пикче не вычисляются компьютером, а описываются художником. Более того, художником же присваивается идентификатор спрайта. Например: "Level 1\Player.png\Looking right".

Пикчи, не имеющие специального сопровождающего конфига, воспринимаются как один спрайт.

>>13250
В C#, как я понял, работа с имейджами сделана через memory-mapped files. Правильно понял?

>>13298
> А вот как красиво организовать пообъектные шейдеры да еще и с вышеописанными плясками, я затрудняюсь ответить.
Да так же:
1. Рендерим всю сцену без зашейденного объекта в текстуру.
2. Рендерим текстуру и сам объект через шейдер на экран. Или в другую текстуру, если нужно будет еще эффектов понакладывать.
Что тут можно оптимизировать, я не представляю. Потому и надеюсь на то, что пообъектных шейдеров будет от 0 до 1 на всю игру.

>>13311
Сделай мне для YAML API удобнее, чем LINQ для XML.
UPDATE: С другой стороны, общаться с конфигом в манере "foreach (spriteName in config["Levels"][0]["Sprites"]) { PrepareSprite(spriteName); }" - это же убер-ня! Может, стоит запилить своё YAML API?
>> No.13390 Reply
>>13389
Неужели ты понял, что я тебе полтреда пытаюсь сказать?
> Есть два варианта:
В своей поделке я использую оба, первый для анимации(т.е. анимация по сути смена спрайта из сетки, что достаточно удобно и быстро, только некрасиво), второй для статичных объектов. Однако там какие-то жуткие костыли с этим, хотелось бы как-то это все более правильно оформить.
>> No.13397 Reply
File: b_img222.jpg
Jpg, 40.42 KB, 410×450
edit Find source with google Find source with iqdb
b_img222.jpg
File: priznak_koshkosti...
Jpg, 37.57 KB, 580×180
edit Find source with google Find source with iqdb
priznak_koshkosti_35.jpg

>>13390
Ну, значит, у нас будут все три варианта. Я уже вижу это:
Resources\
    Common\
        Player ship.png
        Player ship.cfg : <sprites columns="1" rows="5"/>
        Explosion.png
        Explosion.cfg : <sprites columns="4" rows="1"/>
        Enemy airplane.png    //  А конфига нет, значит, один спрайт.
        Bullets.png
        Bullets.cfg :
                <sprites>
                     <sprite id="Simple bullet" left="10" top="52" width="16" height="4"/>
                     <sprite id="Plasma shot" left="30" top="40" width="16" height="16"/>
                     <sprite id="Boss plasma shot" left="30" top="123" width="32" height="32"/>
                </sprites>
    Level 1\
        Boss.png
        Boss.cfg :
                <sprites>
                     <sprite id="Top arm" left="0" top="0" width="1600" height="400"/>
                     <sprite id="Брюхо" left="0" top="401" width="1600" height="800"/>
                     <sprite id="Low arm" left="0" top="1201" width="1600" height="400"/>
                </sprites>
        Background.png    // Тоже конфига нет.
        Ground.png        // И тоже.
А в коде:
RenderSprite("Common\Bullets.png\Simple bullet");
RenderSprite("Common\Player ship.png\1,3");   // Все-таки нумерация с 1 выглядит естесственней, ИМХО.
Ни у кого нет возражений? А если расширение имен файлов из идентификаторов убрать ("Common\Player ship\1,3")?

Кстати, а как учитывать разницу в разрешении? Я крутой и хочу делать версии и под топовый 21-дюймовый моник, и под дисплеи мобилок. Как это в мире делают?
>> No.13401 Reply
>>13397
А зачем каждому спрайту по конфигу, может один конфиг на всех?
> RenderSprite("Common\Bullets.png\Simple bullet");
Как-то не хорошо, в коде оно должно иметь внутреннее представление, а не описываться путем. Вообще спрайты в коде не должны быть захардкожены, они должны в конфигах объектов описываться, а движок должен знать соответствие между спрайтом и объектом.
> Кстати, а как учитывать разницу в разрешении?
Насколько я понимаю, об этом не следует беспокоиться, об этом думает видеокарта и графический бакенд.
>> No.13402 Reply
>>13397


Когда создаёшь вьюпорт, то указываешь его вунтренние размеры относительно трёхмерного пространства в еденицах пространства. Зная разрешение созданного тобой окна и внутреннее разрешение созданного тобой вьюпорта можешь считать.
>> No.13414 Reply
File: c8877f73f892.jpg
Jpg, 127.07 KB, 450×600
edit Find source with google Find source with iqdb
c8877f73f892.jpg
File: priznak_koshkosti...
Jpg, 22.67 KB, 580×180
edit Find source with google Find source with iqdb
priznak_koshkosti_36.jpg

>>13298
> > наподобие http://www.indiedb.com/games/ranger/
> Где ты тут шейдеры увидел? Или видимость врагов ими определяется?
Нет, там шейдеров нет. Это я хочу сделать игру, подобную этой, в которой невидимые области будут смачно блюриться. Но это пока сильно далекие планы.

>>13390
Да я с самого начала понял, что ты имел ввиду. Просто для меня удобство этого варианта было не очевидно, а у тебя мог оказаться "замыленный взгляд".

>>13401
Я уже вижу это:
Resources\
    Sprites.xml :
            <sprites>
                <file name="Common\Player ship.png" rows=5 col=1/>
                <file name="Level 1\Boss.png">
                    <sprite id="Top arm" left=0 top=0 width=1600 height=400/>
                    <sprite id="Брюхо" left=0 top=401 width=1600 height=800/>
                    <sprite id="Bottom arm" left=0 top=1201 width=1600 height=400/>
                </file>
            </sprites>
    ...
> Как-то не хорошо, в коде оно должно иметь внутреннее представление, а не описываться путем.
Лол, тоже красная лампочка в голове мигает, да? Это как раз тот случай, когда общепринятый вариант не есть самый правильный. Давайте обратимся к практике. Вот написал программист код. Он точно знает, какие спрайты ему нужны. Он говорит художнику: "Нарисуй-ка мне такие-то такие-то спрайты". Художник отвечает: "О'кей, но в каком виде тебе их предоставить?" Я говорю: "Вот тебе конкретные имена файлов, просто запиши спрайты в них - и все". Вы говорите: "Записывай в какие хочешь файлы, но потом предоставь мне XML-ничек, в котором будут такие-то ID и их соответствие твоим файлам". В первом случае художник просто рисует спрайты, какие я ему сказал. Во втором случае рисует спрайты и дополнительно пишет XML-ничек. В котором, кстати, может ошибиться (гуманитарий же). Лишняя работа. Бритва Оккама во все поля, короче.
UPDATE: С другой стороны, программист может запросить "Bleat-mujik (frame 1).png", "Bleat-mujik (frame 2).png" и "Bleat-mujik (frame 3).png", а художнику может оказаться удобнее запихнуть все 3 кадра в "Bleat-mujik.png" и написать в конфиге, что это на самом деле 3 картинки. Но это, опять же, решается, если конечные идентификаторы в конфиге будут именно те, которые указал программист.

Короче, я предлагаю ID-шники спрайтов назначать полуавтоматически.
> Вообще спрайты в коде не должны быть захардкожены, они должны в конфигах объектов описываться, а движок должен знать соответствие между спрайтом и объектом.
Ты сделал меня задуматься. Первые идеи: GameObject оставить, как есть сейчас, но сделать какой-нибудь ConfigurableGameObject, который будет наследоваться от GameObject и читать себя из конфигов.

А вообще я начинаю приходить к выводу, что нам достаточно будет фреймворка для игровой логики (Existing, GameWorld, GameObject) и связки утилит для OpenGL-я. Любая универсализация, как вы сами видите, очень быстро обрастает костылями и abstraction penalty и потому становится непригодной.
> Разные разрешения
Я имею ввиду текстуры. Для хотя бы 1024x768 и 1600x1200 подойдет один и тот же набор текстур? При масштабировании они не превратятся в говно?
>> No.13417 Reply
>>13414

Ты не совсем понимаешь воркфлоу создания игры. Программист не является ключевым звеном, ключевым звеном является науськиваемый продюссером игры гейм-дизайнер. который пилит концепт игры и раздаёт, грубо говоря, художникам, программистам и музыкантам части проекта на реализацию. Программист и художник не взаимодействуют, для художников пишутся тулзы с помощью которых они выдают подходящий для движка контент.

Те геймдизайнер говорит программисту - а запили ка мне чтобы два перса дрались на мечах с токим то грофоном. Программист или идёт выполнять или говорит геймдизу, что такое по определённым причинам невозможно (мы пилим игру для андроида, а там нельзя в графон, начальник!), тогда геймдиз и кодер ищут компромисс. Параллельно художникам он командует нарисовать, смоделлить и анимировать двух чуваков, максимум говорит им о лимите количества полигонов, о котором ему сказал кодер (начальник, двигло на этой платформе потянет 100 тысяч полигонов на кадр!). которые дерутся на мечах. В результате программист пишет код, художники пишут контент, и если тулмейкеры не проебались, то друг с другом кодер и художнике практически не контактируют.
>> No.13418 Reply
File: 8833784.jpg
Jpg, 169.83 KB, 1400×968 - Click the image to expand
edit Find source with google Find source with iqdb
8833784.jpg
>>13389
Что-то мне совсем не нравится то, что ты намутил.
> Есть два варианта:
По возможности, лучше все унифицировать. Спрайты выровняные по сетке? — ОК. Один спрайт? — это сетка 1х1 — ОК. Положение спрайта в пикче рандомное? — Алгоритм вычисления текстурных координат идет попипо , обрастает свитчами и прочими костылями; обращение по имени+индексы также накрывается.
Да и
> Player.png\1,0
> Player.png\Looking right
странно и ни разу не естественно выглядит.
> memory-mapped files
Хуже. Любой жпг или пнг хранятся как битовая карта: 1 пиксель — 4 байта. Вот и считай размер 8192х8192 пикчи(а возможно и не одной) в памяти.
> 1. Рендерим всю сцену без зашейденного объекта в текстуру.
Почему без? И зачем в текстуру? Всмысле текстура текстурой — полноэкранные эфекты без проблем сохраняют модульность и на все остальное не влияют, т.е. не имеет значения есть они или нет для других спрайтов, в том числе и зашейдереных.
Меня волнует другое. Для обычного спрайта достаточно передать структуру "координаты,текстурные координаты, цвет". Для шейдера же нужны еще и юниформы, которые кто-то должен установить и обновлять,
а для обшейдеренного объекта еще и дополнительные параметры для вершин спрайта, причем уникальные для каждого объекта. Т.е. для эфекта шума одинаковые текстурные координаты карты шума еще покатат, но одинаковая фаза для всех мигающих(например) объектов будет бросаться в глаза и выглядеть странно. Значит для каждого пообъектного шейдера нужны уникальные структура данных, сигнатура у функции добавления спрайта и я хз что еще.

>>13397
> Ну, значит, у нас будут все три варианта.
Опять же. Пожалей функцию определения текстурных координат.
> Я уже вижу это:
А меня сделай это развидеть.
Один файл конфига текстур и унифицированый формат их объявления. Смысл лепить кучку хаотично расставленых текстур в одином файле, если атлас потом их все равно склеит, только лишняя работа художникам.
Теперь по поводу имени. Ни имя файла спрайта, ни даже его идентификатор не должны фигурировать в коде. Это должно выглядеть так:
Пикчеконфиг:
<texture file="vehicles/tank.jpg" id="Tank" cols="5" rows="1"/>

Объектоконфиг:
<tank>
    <animation>
       <idle><sprite id="Tank" col="1" row="0"></idle>
       <move><sprite id="Tank" col="2" row="0"></move>
       …
    </animation>
   …
</tank>
Это условно, но суть думаю ясна. Далее в рантайме происходит сборка объекта: создается собственно танк и его рендер-объект. Причем рендер-объект находит в рендер-менеджере нужную себе текстуру (по id="Tank")и рендер менеджер уже возвращает свой внутренний ID (желательно int как у меня в коде —индекс в массиве, что бы сократить время на поиск нужной текстуры, а то обращаться по стрингу это пздец). Загрузка нужной текстуры идет по file="vehicles/tank.jpg".
> Все-таки нумерация с 1 выглядит естесственней, ИМХО.
Вот тут я согласен.

Далее по коду.
Ну не дают тебе елды и энумераторы покоя. В Live() должно быть что-то типа:
Position += Speed * DeltaTime; Или напиши уже наконец конкретный пример.
public const IEnumerator StayStill = null; // Вместо null будет что-то. Это ещё что за хрень? Какой конст?
GLScreen screen Какой еще ГЛскрин?
public void SetView(Matrix4 modelViewMatrix, Matrix4 projectionMatrix); Матрицы не нужны. Translate и Rotate наше всё. Тем более ты хотель побольше абстрагироваться от GL — знач надо передавать сами координаты.
public void SetRenderingQueue(float queue) {} Мне не нравиться сортировка в рендер-менеджере.
Получается хранятся где-то в списке рендер-объекты, которые отправляются на отрисовку в рандомном порядке. Потом это все сохраняется в другом виде в списке в рендер менеджере, потом это сортируется (каждый фрейм!) и снова пересохраняется в массиве, который уже отправляется в видеокарту.
Чем тебе не нравится прошлый вариант с сортировкой при добавлении объекта? Так получается лишний массив и лишнее действие.
ActivateEffect() DeactivateEffect() Как ты описал не катит, по вышеописанным причинам.
public IEnumerable<GameObject> Objects { get {return null;} } Что за муть. Если подразумевается, что "тут будет что-то написано", то оставляй лучше пустое место или коментарии, а не get {return null;}
   abstract class GameObject : ExistingRenderable
    {
        public GameWorld World
        {
            /// <summary>
            /// Это доступно всем.
            /// </summary>
            get {return null;}
            
            /// <summary>
            /// А это доступно только GameWorld-у.
            /// </summary>
            set {}
        }
        
    }
Ну ёпт так и пиши:
    abstract class GameObject : ExistingRenderable
    {
        public GameWorld World { get; private set; }

        protected GameObject(GameWorld world)
        {
            this.World = world;
        }
    }
Я кончил.
Пойду дальше обдумывать шейдеры.
>> No.13421 Reply
>>13299
> адаптер
Та не. Ext и не-Ext — идентичны, но находятся в разных местах. Просто в будующем в подобных случаях лучше сразу юзать Ext. Ну и при загрузке сделать проверку, и в случае отсутствия соответствующих расширений выдавать сообщение о степени говёности видяхи.
>> No.13428 Reply
>>13418
> Спрайты выровняные по сетке? — ОК. Один спрайт? — это сетка 1х1 — ОК. Положение спрайта в пикче рандомное?
Смотри, в чем проблема. Предположим, у нас есть персонаж. У него спрайт постоянно одного и того же размера, его можно свести в сетку и работать с ним будет удобно. Теперь у нас есть лес. В лесу растут дуб, сосна, ель, у каждого спрайт разного размера. А теперь представь, что у нас большой лес с 9000 видами деревьев, для кажого создавать файл - в ресурсах получится месиво. Оптимальнее, да и удобнее, было бы нарисовать деревья в одном файле, вместе с травой, какими-нибудь камнями и прочей природой. Можно, конечно, тоже выровнять по сетке, но во первых - нерациональный расход места, во вторых - если размеры спрайта коррелируют с его игровыми размерами, то такой вариант тоже не подойдет. Не пойми неправильно, я не поддерживаю вариант обоих способов, я кроме костылей с него ничего не поимел, я просто хочу найти оптимальное решение.
> Мне не нравиться сортировка в рендер-менеджере.
Без нее будет трудно, если порядок отрисовки спрайтов имеет какое-то значение(т.е. если это не скроллшутер, а что-то изомерное). Я наткнулся на то, что опенгл глючный и не может нормально совмещать альфу с depth-буфером(текстуры, загруженные ранее своей альфой просвечивают через те, что загружены позже, но расположены глубже, т.е. видно фон, а не нижнюю текстуру), адекватного решения чему так и не нашел, даже какую-то полуофициальную рекомендацию видел, не использовать альфу и глубину вместе. Решение тут приходит только одно: хранить все объекты в массиве(по сути массив объектов, которые должны быть отрендерены, хранящийся в рендере, что не сильно хорошо) и каждый кадр его сортировать. Фпс почти не меняется, кстати(в пределах погрешности измерения).
>> No.13433 Reply
>>13428
> Смотри, в чем проблема.
Создавать в ресурсах месиво — норм, а создавать в одной пикче + в файле её описывающем месиво — плохо?
Я тут подумал. Все-таки это можно сделать не меняя функцию определения текстурных координат, но значительно переделать функцию добавления текстур в атлас.
Алсо, надо ли, что бы можно было делать большую текстуру, состоящию из рандомно расположеных маленьких, которые в свою очередь будут пачкой текстур выровняных по сетке?(Оно само по себе так будет, но если не надо, то можно "заблокировать")
Кароч я тебя в последний раз предупреждаю, что это все муть, а потом пойду и сделаю.

И мы таки остановились на XML?
> Без нее будет трудно, многа букав…
И к чему ты это написал? Как это мешает делать как в первоначальном варианте?
И мы же вроде без depth-буфера, не?
>> No.13456 Reply
Сдаётся мне, ОП никогда игор не делал. Я прав?
>> No.13457 Reply
Доброаноны, а у кого-нибудь был опыт работы с библиотекой Coin3D? Сложно ли будет осваивать её ньюфагу, который красивых сцен не рисовал, но в C++ ориентируется? А может быть ещё и попроще что-нибудь есть? Тред не читал.
>> No.13463 Reply
>>13457
Оно гпльное, чем оно лучше чего-нибудь еще?
>> No.13464 Reply
File: priznak_koshkosti_37.jpg
Jpg, 31.28 KB, 580×180 - Click the image to expand
edit Find source with google Find source with iqdb
priznak_koshkosti_37.jpg
ОП вернулся, испугался и убежал. Завтра подробно и обстоятельно отвечу на всё.
>> No.13534 Reply
File: 1310545752814.jpg
Jpg, 195.48 KB, 518×800
edit Find source with google Find source with iqdb
1310545752814.jpg
File: priznak_koshkosti...
Jpg, 28.92 KB, 580×180
edit Find source with google Find source with iqdb
priznak_koshkosti_38.jpg

>>13418
> текстурные координаты
Ты не понял. Тем, что выдает художник, пользоваться в программе вообще невозможно. Изначально это было мое предположение, но после >>13417-куна это стало утверждением. А раз так, то выхлоп художника в любом случае надо будет переводить в формат, удобный программистам. А раз так, то мы (программисты) можем сделать из этого выхлопа всё, что захотим. Хотим небо - сделаем. Хотим Аллаха - сделаем. Хотим набор из пары атласов 8192x8192 и мапы из ID спрайта в кортеж из имени атласа и координат на этом атласе (Map: SpriteID -> {AtlasName, Matrix2}) - сделаем. И все эти навороты, которые я описал: 3 способа задания спрайтов, 2 вида конфигов - это все делается для удобства художников, не кодеров. Сами мы этим пользоваться (по крайней мере, в игровом коде) не будем.

То есть, если кратко: от художника нам нужны будут текстурные атласы и мапа из ID спрайта в структуру "имя атласа; координаты этого спрайта на атласе". Всё. А уж будет ли художник сам эти атласы и мапы составлять, через нашу тулзу (то есть, используя конфиги) или если даже они будут собираться в рантайме - это уже дело тулмейкера. Сами мы этими конфигами пользоваться не будем.
> Шейдеры
> Для шейдера же нужны еще и юниформы, которые кто-то должен установить и обновлять,
Они будут выставляться перед отправкой всех координат спрайтов на видяху. То есть:
GL.АктивизироватьШейдер(YobaEffect);
GL.УстановитьЮниформ("Имя", Значение);
GL.УстановитьЮниформ("Имя", Значение);
...
GL.УстановитьЮниформ("Имя", Значение);
GL.ОтправитьВертексБуфферИТексельБуффер(ВертексБуфферСоВсейСценой, ТексельБуферСоВсейСценой);
> а для обшейдеренного объекта еще и дополнительные параметры для вершин спрайта, причем уникальные для каждого объекта. Т.е. для эфекта шума одинаковые текстурные координаты карты шума еще покатат, но одинаковая фаза для всех мигающих(например) объектов будет бросаться в глаза и выглядеть странно. Значит для каждого пообъектного шейдера нужны уникальные структура данных, сигнатура у функции добавления спрайта и я хз что еще.
Именно. Можно обойтись без дополнительных параметров в функции Render(...), просто добавить функции ActivateEffect(...), DeactivateEffect(...); то есть, сделать эдакую машину состояний. То есть, в рендер-менеджере:
GL.АктивизироватьШейдер(YobaEffect);
GL.УстановитьЮниформ("Имя", Значение);
GL.УстановитьЮниформ("Имя", Значение);
GL.УстановитьЮниформ("Имя", Значение);
...
GL.УстановитьЮниформ("Имя", Значение);
GL.ОтправитьВертексБуфферИТексельБуффер(ВертексБуфферПочтиСоВсейСценой, ТексельБуферПочтиСоВсейСценой);
GL.ДеактивироватьШейдер();
GL.АктивироватьШейдер("Мигание");
GL.УстановитьЮниформ("Имя", МигающийОбъект.ФазаМигания);
ВертексБуфер = ЗаполнитьВертексБуферИзОбъектов(new GameObject[] { МигающийОбъект });
ТексельБуфер = ЗаполнитьТексельБуферИзОбъектов(new GameObject[] { МигающийОбъект });
GL.ОтправитьВертексБуфферИТексельБуффер(ВертексБуфер, ТексельБуфер);
GL.ДеактивироватьШейдер();
GL.АктивироватьШейдер("МиганиеСиним");
GL.УстановитьЮниформ("Имя", ДругойМигающийОбъект.ФазаМигания);
ВертексБуфер = ЗаполнитьВертексБуферИзОбъектов(new GameObject[] { ДругойМигающийОбъект });
ТексельБуфер = ЗаполнитьТексельБуферИзОбъектов(new GameObject[] { ДругойМигающийОбъект });
GL.ОтправитьВертексБуфферИТексельБуффер(ВертексБуфер, ТексельБуфер);
GL.ДеактивироватьШейдер();
GL.АктивироватьШейдер("МиганиеВсемиЦветамиРадуги");
GL.УстановитьЮниформ("Имя", ТретийМигающийОбъект.ФазаМигания);
ВертексБуфер = ЗаполнитьВертексБуферИзОбъектов(new GameObject[] { ТретийМигающийОбъект });
ТексельБуфер = ЗаполнитьТексельБуферИзОбъектов(new GameObject[] { ТретийМигающийОбъект });
GL.ОтправитьВертексБуфферИТексельБуффер(ВертексБуфер, ТексельБуфер);
GL.ДеактивироватьШейдер();
...  // И так для всех мигающих объектов. Да-да, каждый зашейдеренный объект рендерится отдельно от всех.
Я на то отвечаю?
> по коду
> елды
class MovingObject : GameObject
{
    /// <summary>
    /// Сдвигает данный объект к указанной точке с указанной скоростью.
    /// </summary>
    protected void MoveTo(Vector2D pos, float pixelsPerSecond)
    {
        ...
    }
}
  
class ЖнецИзЛунарии : MovingObject
{
    public ЖнецИзЛунарии()
    {
        self.Pos = Vector2D(-100, 400);
        Existence = Logic();
    }
    private IEnumerator Logic()
    {
        // Вылетаем сзади.
        var newPos = Vector2D(1000, 400);  // Середина правого края экрана.
        while (self.Pos != newPos)
        {
            MoveTo(newPos, 1000/2 /* прописью: тысяча пикселей за две секунды */);
            yield return null;
        }
        // Пока не сдохнем...
        while (true)
        {
            // Поднимаемся...
            newPos = Vector2D(1000, 50);  // Верхний правый край.
            while (self.Pos != newPos)
            {
                MoveTo(newPos, 700/1);
                yield return null;
            }
            // Летаем вверх-вниз.
            for (int i = 0; i < 10; i++)  // 10 раз.
            {
                newPos = Vector2D(1000, 750);  // Нижний правый край.
                while (self.Pos != newPos)
                {
                    MoveTo(newPos, 700/1);
                    yield return null;
                }
                newPos = Vector2D(1000, 50);  // Верхний правый край.
                while (self.Pos != newPos)
                {
                    MoveTo(newPos, 700/1);
                    yield return null;
                }
            }
            // Готовимся к удару...
            newPos = Vector2D(1000, 400);  // Середина.
            while (self.Pos != newPos)
            {
                MoveTo(newPos, 700/1);
                yield return null;
            }
            // Ебошим!
            newPos = Vector2D(50, 400);  // Левый край экрана.
            while (self.Pos != newPos)
            {
                MoveTo(newPos, 1000/1);
                yield return null;
            }
            // Точно ебошим!
            УдаритьКосой();
            // Летим обратно.
            newPos = Vector2D(1000, 400);  // Правый край экрана.
            while (self.Pos != newPos)
            {
                MoveTo(newPos, 1000/2);
                yield return null;
            }
            // Повторяем все с начала.
        }
    }
    private void УдаритьКосой()
    {
        ...
    }
}
Разные способы описания подходят под разные задачи. С этим, думаю, никто спорить не будет. Декларативщина подходит под описание гуёв, функциональщина - под математические вещи, машина состояний - под я не знаю что, а под описание логики бота лучше всего подходит императивщина вида "ПодойдиК(Игрок.Позиция, я.Скорость); Отпизди(Игрок);".

INB4 "а если жнеца таки замочили?": некто делает "Жнец.Existence = DisappearImmediately();" - и все, жнец исчезает на следующем кадре.
> public const IEnumerator StayStill = null; // Вместо null будет что-то. Это ещё что за хрень? Какой конст?
Ой, я забыл, что в C# с const-ом говно какое-то.
Правильно здесь написать надо было так:
public IEnumerator StayStill = ...  // Комментарий для программиста: НЕ ВЗДУМАЙ ПРИСВАИВАТЬ ЭТОМУ ПОЛЮ НИЧЕГО, СУКА!!!!11
> GLScreen
Обертка над OpenGL. Типа всё равно все объекты рендерятся на экран - вот вам экран.
> Мне не нравиться сортировка в рендер-менеджере.
> Чем тебе не нравится прошлый вариант с сортировкой при добавлении объекта?
Я именно так и предлагаю, только сортируются при добавлении не объекты, а спрайты. Когда я говорю: "RenderSprite(TheSprite)" - этот спрайт просто добавляется в очередь, соответствующую: 1) текущему приоритету; 2) атласу, которому этот спрайт принадлежит (контрактам, которые я указал, это не противоречит). В результате за порядком объектов в GameWorld следить не надо (у объектов могут поменяться спрайты так, что может понадобиться другой атлас; плюс какой-нибудь из объектов может вылезти на передний план или уйти на задний), а RenderSprite(...) будет отрабатывать за амортизированное O(1). То есть:
class GameWorld
{
    private List<GameObject> Objects;
    
    public void Add(GameObject obj)
    {
        self.Objects.Add(obj);   // Тупо.
    }
}
  
class GLScreen
{
    private Map<Priority, Map<AtlasID, VertexAndTexelBuffer>> VertexAndTexelBuffers;
    
    public void RenderSprite(Vector2D pos, int spriteID)
    {
        var spriteDescription = TextureManager.FindSpriteDescription(spriteID);
        var buffer = VertexAndTexelBuffers[CurrentPriority][spriteDescription.AtlasID];
        buffer.AddCoordinates(
            // Vertices
            pos.x, pos.y, pos.x + spriteDescription.width, pos.y + spriteDesccription.height,
            // Texels
            spriteDescription.x, spriteDescription.y, spriteDescription.x + spriteDescription.width,
                    spriteDescription.y + spriteDescription.height
        );
    }
}
> Если подразумевается, что "тут будет что-то написано", то оставляй лучше пустое место или коментарии, а не get {return null;}
Я ошибки компилятором искал. Больше так не буду. Да, "return null" везде надо заменить на "...".
> Ну ёпт так и пиши:
Ты неправильно написал. Я не хочу выносить World в конструктор, иначе получится, что можно создать объект, но не добавить его в мир. Впрочем, это решается, и это на самом деле технические детали уже. Суть и так ясна: игрообъекты знают об игромире, в который они добавлены. Вот и все.

>>13433
> И мы таки остановились на XML?
Да, до появления варианта получше. Например, до няшного API для YAML.
> И мы же вроде без depth-буфера, не?
Без. Я периодически буду на него оглядываться, вдруг пригодиться (все-таки мощный инструмент, как ни крути), но пока без него.

>>13456
Ну, делал, на Бейсике.
10 DIM X(300) : DIM Y(300) : DIM BULLETX(50) : DIM BULLETY(50)
А чтоб вот так серьезно, с проектированием, с архитектурой - это первый раз.

--
> <tank>
> <animation>
> <idle><sprite id="Tank" col="1" row="0"></idle>
> <move><sprite id="Tank" col="2" row="0"></move>
> …
> </animation>
> …
> </tank>
Рефлекторно послал нахуй и в пизду, потому что попахивает скриптингом, а в моих задумках скриптинг - это оверкилл. Но здравое зерно в этом XML-нике есть. Сейчас объясню.

Я провел ряд мысленных экспериментов и обнаружил, что анимация - это тоже часто встречающаяся задача, и было бы неплохо ее тоже автоматизировать. Посему вбрасываю идею: отправлять рендер-менеджеру не спрайты, а целые анимации (какие-нибудь объекты класса Animation, там, я не знаю). А игрообъекты со своей стороны будут рулить этими анимациями: запускать, тормозить, проигрывать в обратном порядке, перематывать, зацикливать и прочее.

<мечты>
А вообще, я еще в отрочестве хотел писать игры на потоках: нужен игрок - создаешь поток, рулящий игроком; нужен враг - создаешь поток, рулящий врагом; нужно убить игрока, если здоровья стало мало - создаешь поток, следящий за здоровьем игрока. И рендерер - тоже поток, и реакция на контроллеры - тоже поток. И все объекты-потоки не ждут очередного кадра, а работают все одновременно. И когда им надо изменить картинку (то есть, свое отображение на экране) - они просто скидывают изменения в определенный глобальный буфер. А поток-рендерер просто 60 раз в секунду рендерит этот глобальный буфер на экран. И анимации - это тоже потоки: создался поток-вертолетик, а внутри себя создал поток-анимацию, которая быстро-быстро меняет его спрайт и складывает эти изменения в глобальный буфер. И потоки могут друг с другом взаимодействовать - суспендить, убивать, запускать заново и т. д. Причем любой поток может поиметь любой другой поток, какой хочет. Естесственно, это не голые потоки, а некие объекты, с состоянием и шлюхами. Но засуспендить или вообще убить их все равно можно. И вот так вот живут все потоки сами по себе, рожают, убивают друг друга, а один маленький поток рендерит всё это безобразие каждую 1/60-ую секунды.

Понятно, что эта идея бредова, но что если бы потоки были бы легковесными, как в Эрланге, и работали бы по-настоящему одновременно? Я вижу прототип таких потоков в корутинах, например.
</мечты>

c:дорога дизайнер зима отделяет читал
>> No.13543 Reply
>>13463
> >>13457
> Оно гпльное, чем оно лучше чего-нибудь еще?
Т.е. ты хочешь сказать, что осваивать ничуть не проще всего остального?
>> No.13552 Reply
File: 7122246.jpg
Jpg, 116.66 KB, 1024×1024 - Click the image to expand
edit Find source with google Find source with iqdb
7122246.jpg
>>13534
По картинкам. Я сделаю возможность загрузки пикч, содержащих рандомно расставленные текстуры и/или сетку текстур. Выглядеть это будет так:
<Pictures>
  <File fileName="Textures/shime17.png">
    <Texture name="Mami"/>
  </File>
  <File fileName="Textures/homming missile.jpg">
    <Texture name="missile" cols="20" rows="1"/>
  </File>
  <File fileName="Textures/terrain_0.png">
    <Texture name="test00" cols="8" rows="8" left="0" top="0" width="512" height="512"/>
    <Texture name="test01" left="0" top="512" width="100" height="100"/>
    <Texture name="test02" left="100" top="512" width="100" height="100"/>
  </File>
</Pictures>
Элемент <File> — это собственно пикча, имеет атрибут fileName(обязательный) — путь к файлу. Файл в свою очередь является контейнером для текстур. В общем случае текстур может быть произвольное кол-во, каждая из которых может быть сеткой текстур. Текстура имеет атрибуты:
name — обязательный, по которому к этой текстуре можно обращаться;
cols, rows — не обязательные, по умолчанию принимаются = 1, кол-во колонок и столбцов в сетке;
left, top, width, height — не обязательные, но либо все есть, либо всех нет. Расположение текстуры в файле. По умолчанию = габаритам всей пикчи.
Частные случаи: одна текстура с cols, rows — просто сетка текстур; одна текстура без необязательных атрибутов: одна пикча — одна текстура.
После загрузки текстуры хранятся в одном массиве, обращение по индексу или имени + (необязательно)колонка и столбец сетки. Принадлежность к какому либо файлу не имеет значения — текстурные координаты составной пикчи разбиваются на текстурные координаты входящих в неё пикч.

Вот тут обращаю внимание на следующий момент. Составная пикча будет загружаться в атлас вся сразу. Т.е. если понадобится только одна текстура из составной пикчи, то придется загружать её всю. Знач собирать подобные пикчи придется так, что бы они использовались только вместе.

На досуге сделаю, что бы кол-во текстурных атласов было произвольным на случай если в 1 не всё не влезет.
> Они будут выставляться перед отправкой всех координат спрайтов на видяху.
> …
> Я на то отвечаю?
Спасибо кэп. Я в курсе как работают шейдеры. Я про то, что при добавлении нового типа шейдеров, нужно дописывать рендер-менеджер. Сразу плюс новые структуры под вертексы, новый массив под эти структуры, новая функция со своими уникальными параметрами, новая запись в "главном" методе Flush (или Draw). Если тебя это не беспокоит, то все ОК, я так и сделаю.
> private IEnumerator Logic()
Ну ок такое годиться для описания последовательностей действий монстриков в играх вроде LUNARIA, которую ты скидывал раньше. Ну а зачем это все городить в объекте, которым управляешь ты? Или просто в "пульках", которые летят прямолинейно равномерно и проверяют, не попали ли они в кого-то? Или куда
тут втыкивать AI?
> Обертка над OpenGL. Типа всё равно все объекты рендерятся на экран - вот вам экран.
Нету там ни какого экрана. Есть буферы кадра и фреймбуферы с параметрами. И незачем их передавать в каждый вызов. Вот как раз тут state machine, параметры для которой устанавливаются в Камере, остальным об этом знать незачем.
> у объектов могут поменяться спрайты так, что может понадобиться другой атлас; плюс какой-нибудь из объектов может вылезти на передний план или уйти на задний
Так бы сразу и написал. Ок, будет сортировка каждый раз. Кстати, причем тут
> другой атлас
Выбор атласа лежит на рендер менеджере.
> Ты неправильно написал. Я не хочу выносить World в конструктор, иначе получится, что можно создать объект, но не добавить его в мир.
Ну значит что-то типа:
abstract class GameObject : ExistingRenderable
{
    public GameWorld World { get; private set; }
    protected bool IsInitialized { get; private set; }
    public Initialize(GameWorld world)
    {
        if (world == null)
            throw new NullReferenceException("world");
        this.World = world;
        this.IsInitialized = true;
    }
}
И проверять IsInitialize. Можно вместо public Initialize написать internal и держать их(GameWorld и GameObject) в одной сборке. Просто у тебя какой-то странный модификатор области видимости:
> /// А это доступно только GameWorld-у.
> Посему вбрасываю идею: отправлять рендер-менеджеру не спрайты, а целые анимации
Ты мои исходники вообще смотрел? GameObject'у принадлежит отдельный объект RenderAspect. GameObject изменяет и управляет своим RenderAspect'ом, а он управляет анимацией итд. И уже сам RenderAspect отправляет на отрисовку конкретный спрайт, в конкретном месте, с конкретными эффектами, в конкретной фазе, в ну ты понял.
>> No.13556 Reply
>>13534
> while (self.Pos != newPos) {
> yield return null;
Выглядит так же, как goto. Хотя, нет, это goto END и есть. В чем суть твоих елдов, если ты ими ничего не возвращаешь, а используешь для логики программы?
> потоки
Все упрется в лимит потоков, он достаточно небольшой, кстати, около 60 на процесс что ли, зависит от ос.
>>13543
Я хочу сказать, что для меня разница в освоении(что по сути вдумчивое стение референса) намного менее серьезна чем разница в лицензии, ибо в привязанности своих проектов к гпл не вижу никакого профита.
>>13552
> Составная пикча будет загружаться в атлас вся сразу.
Кстати, это решение, но что насчет пустот?
>> No.13557 Reply
>>13556
> > Составная пикча будет загружаться в атлас вся сразу.
> Кстати, это решение, но что насчет пустот?
Кстати, да, что-то я туплю. Знач сначала составная пикча разбивается на отдельные, и уже каждая из этих картинок независимо добавляются в атлас. И сразу решается проблема использования отдельных текстур из набора без необходимости загружать всё.
>> No.13591 Reply
File: JBG387kgxp296.jpg
Jpg, 60.40 KB, 450×600
edit Find source with google Find source with iqdb
JBG387kgxp296.jpg
File: priznak_koshkosti...
Jpg, 29.11 KB, 580×180
edit Find source with google Find source with iqdb
priznak_koshkosti_39.jpg

>>13552
> Конфиги спрайтов
Можно. Предлагаю еще такой вариант:
<sprites>
    <sprite id="Background" file="Common\Background.png"/>
    <sprite id="Ship" file="Common\Ship.png" cols="3" rows="1"/>  <!-- Эта запись наплодит следующие ID-шники: "Ship 1,1", "Ship 2,1", "Ship 3,1" -->
    <sprite id="Boss top arm" file="Level 1\Boss.png" left=0 top=0 width=1600 height=400/>
    <sprite id="Boss bottom arm" file="Level 1\Boss.png" left=0 top=1200 width=1600 height=400/>
</sprites>
Короче, вывернуть наизнанку ID-шники и файлы.
> Спасибо кэп. Я в курсе как работают шейдеры. Я про то, что при добавлении нового типа шейдеров, нужно дописывать рендер-менеджер. Сразу плюс новые структуры под вертексы, новый массив под эти структуры, новая функция со своими уникальными параметрами, новая запись в "главном" методе Flush (или Draw). Если тебя это не беспокоит, то все ОК, я так и сделаю.
Меня это не беспокоит. Пока не предложен вариант по-быстрее и с таким же удобством.
> Логика
Логика объекта игрока даже проще, чем логика других монстриков. Частный случай.
А AI - это вопрос. Но ведь так или иначе любая программа, будь то логика пули или AI бота в Кваке, выражается последовательностью императивных инструкций, так?
Кстати, никто не запрещает самому объекту поменять Existence на что-то другое прям из текущей логики. Так, например, теоретически можно реализовать что-то вроде прерываний:
вечно
{
    патрулируй улицы();
}
прерывание:
    если обнаружил врага, то
    {
        запомни Existence;
        Existence := УничтожитьВрага();
    }
УничтожитьВрага()
{
    пока (враг жив)
    {
        стрелять по врагу;
    }
    восстанови Existence;
}
Или вообще какие-нибудь behavioral trees (методом запоминания и комбинирования различных Existence-ий).
Кстати, еще см. ниже, ответ >>13556-куну.
> Нету там ни какого экрана.
Вот и надо его сделать. А то наплодили, понимаешь, фреймбуферов каких-то, буферов кадра, стейт-машин всяких... Вот экран, вот нормальное, удобное API к этому экрану - пожалуйста, фигачьте туда. Ну или не экран, а RenderingContext какой-нибудь (все-таки, там не совсем экран получается, больно умная структурка).
> Кстати, причем тут
> > другой атлас
> Выбор атласа лежит на рендер менеджере.
Да-да. Я в том смысле, что объекту-то пофиг, он просто указывает, какой спрайт ему нужен, а вот рендер-менеджер может начать этот объект рендерить в другом порядке, вот как раз потому, что запрошенный спрайт лежит в другом атласе. Но при правильном указании приоритетов рендеринга, повторюсь, объекту на это наплевать.
> Просто у тебя какой-то странный модификатор области видимости:
> > /// А это доступно только GameWorld-у.
Это из Eiffel-я. Очень-очень хотеть.
> Анимации
> Ты мои исходники вообще смотрел? GameObject'у принадлежит отдельный объект RenderAspect.
Почему-то не подумал о RenderAspect-ах в таком ключе. Буду думать еще.

Кстати, у меня в голове выстраивается еще одна идея, еще более гибкая. Ждите, скоро жахну.

>>13556
> В чем суть твоих елдов
Если бы вся игра была на потоках, то тот быдлокод выглядел бы так:
class ЖнецИзЛунарии : MovingObject
{
    public ЖнецИзЛунарии()
    {
        self.Pos = Vector2D(-100, 400);
        Existence = Logic();
    }
    private IEnumerator Logic()
    {
        // Вылетаем сзади.
        MoveTo(Vector2D(1000, 400), 1000/2 /* прописью: тысяча пикселей за две секунды */);
        // Пока не сдохнем...
        while (true)
        {
            // Поднимаемся...
            MoveTo(Vector2D(1000, 50), 700/1);
            // Летаем вверх-вниз.
            for (int i = 0; i < 10; i++)  // 10 раз.
            {
                MoveTo(Vector2D(1000, 750), 700/1);
                MoveTo(Vector2D(1000, 50), 700/1);
            }
            // Готовимся к удару...
            MoveTo(Vector2D(1000, 400), 700/1);
            // Ебошим!
            MoveTo(Vector2D(50, 400), 1000/1);
            // Точно ебошим!
            УдаритьКосой();
            // Летим обратно.
            MoveTo(Vector2D(1000, 400), 1000/2);
            // Повторяем все с начала.
        }
    }
    private void УдаритьКосой()
    {
        ...
    }
}
> потоки
А кто сказал, что использовать надо именно Thread-ы? Почему не корутины? Результат тот же, а нагрузка на ОС куда меньше. Единственное, в корутинах надо везде Coroutine.Pass() расставлять, чтобы другим корутинам дать поработать, но это не так страшно. Я, кстати, это и реализовал через Existence и методы, возвращающие Enumerator, только вместо Coroutine.Pass() писал yield return null.

>>13557
Тулза, собирающая атласы и мапы (имя спрайта -> {ID атласа, координаты в атласе}), должна рассматривать исходный материал от художника как набор отдельных пикчей. Плевать, что он 20 пикчей поместил в один файл, плевать, что 2 ID-шника вдруг указывают на 1 пикчу - для тулзы все это совершенно разные спрайты, никак друг с другом не связанные. И атласы должны собираться так, будто пикчи совершенно друг с другом не связаны.
>> No.13594 Reply
File: 3503883.jpg
Jpg, 104.38 KB, 1000×1250 - Click the image to expand
edit Find source with google Find source with iqdb
3503883.jpg
>>13591
> Предлагаю еще такой вариант:
Так даже проще.
> <!-- Эта запись наплодит следующие ID-шники: "Ship 1,1", "Ship 2,1", "Ship 3,1" -->
Лучше оставить возможность индексации обычным способом — пригодится для анимации. В рендерАспекте пишется что-то типа:
timer += ElapsedTime;
if (timer > 0.2)  // 5 кадров/сек
{
  timer -= 0.2;
  i++;  
}
RenderManager.DrawSprite("Ship", i, 1); // перебераем i.
В а самой отрисовке:
public RectangleF GetSubTextureLocation(int i, int j)
{
  i %= Cols;    // В случае выхода за границы идем по кругу.
  j %= Rows;    // Можно это делать и при отправке.
  …
}
В любом случае, так проще, чем прописывать "Ship 1,1", "Ship 2,1", "Ship 3,1" …
Еще предлогаю стандартизацию в терминологии: когда картинка в оперативке — это Picture; на винте — это либо Picture, либо просто File; в памяти видяхи — Texture; на экране — Sprite. Поэтому в твоем случае там скорее Texture, но уж точно не спрайт.
> Меня это не беспокоит.
Внезапно понял одну штуку. Ведь если отрисовка объектов с шейдерами идет после отрисовки остальных объектов, то они в любом случае окажутся "над" объектами без шейдеров. Тоже самое будет, если используется несколько атласов: объекты со второго атласа будут над объектами с первого. Выходы:
1) отказаться от нескольких атласов и пообъектных шейдеров;
2) зарание подбирать текстуры для второго атласа так, чтобы объекты использующие их были наверху. Тоже для шейдеров;
3) значительно усложнить процесс отрисовки введя групировку по атласам и шейдерам. Типа:
   - отрисовка всех объектов использующих первый атлас с очередностью от 0 до 25;
   - отрисовка всех объектов использующих второй атлас с очередностью от 26 до 55;
   - отрисовка всех объектов использующих первый атлас с очередностью от 56 до ...;
   - ...
Третий вариант был бы предпочтительнее, но я пока не знаю как это реализовать.
> Вот и надо его сделать.
Нет не надо. Объект через ссылку на GameWorld должен видеть RenderManager и через него все рисовать. Больше ничего не надо.
>> No.13596 Reply
>>13591
> <sprite id="Ship" file="Common\Ship.png" cols="3" rows="1"/>
А размер ячейки? Или весь спрайт - сетка?
>>13594
> понял одну штуку.
Я уже давно в это уткнулся, и жду ваших предложений. Вообще, 3 вариант тоже кажется мне более предпочтительным, но тоже пока не знаю, как реализовывать. Оптимальнее дополнительно совмещать этот вариант со вторым, тогда количество ребиндов тоже сократится.
>> No.13602 Reply
Можете унылчанский плюсокод поковырять:


http://iichantra.ru/files/iiHalloween2010src.tar.gz
>> No.13603 Reply
>>13602

БЛЯДЬ МОИ ГЛАЗА, БЛЯДЬ БЛЯДЬ БЛЯДЬ!!!! БЛЯДЬ У ЭТИХ ПИДАРАСОВ ФУНКЦИИ ГЛОБАЛЬНЫЕ И ПЕРЕМЕННЫЕ ГЛОБАЛЬНЫЕ ПРОСТО ТАК БЛЯДЬ ВАЛЯЮТСЯ ПИЗДЕЦ БЛЯДЬ!!! ЭКСТЕРН ГЛОБАЛЬНАЯПЕРЕМЕННАЯНЕЙМ И ТУ ЖЕ РЯДОМ БЛЯТЬ ПАРАША НА ТЕМПЛЕЙТАХ И ОБЬЯВЛЕНИЕ КЛАССОВ Я ХУЕЮ БЛЯДЬ НУ ПИДАРАСЫ НУ ПЛЮСОБЛЯДИ НУ УБОГИЕ БЛЯДЬ, НО ДЛЯ ВАС УБОГИХ ЕЩЁ 10 ЛЕТ НАЗАД НЕЙМСПЕЙСЫ ПРИДУМАЛИ, РАЗ УЖ НЕ УМЕЕТЕ В ООП ТО ХОТЯ БЫ УБИРАЙТЕ ВАШЕ ГОВНО ПО НЕЙМСПЕЙСАМ, ЧТОБЫ БЫЛО ЧИСТО БЛЯДЬ

Простите, но это плохо даже для говноплюсов
>> No.13604 Reply
>>13603

Да, ещё эти нехорошые гомосексуалисты, прикидывающиеся няшечками у себя на борде ХРАНЯТ ВСЁ В ЛУА СКРИПТАХ - УРОВНИ АТЛАСЫ И ПРОЧУЮ ПОЕБЕНЬ.
>> No.13605 Reply
>>13604
>>13603
>>13602

Эх, ну зачем вы так, ОП утром прочтёт этот тред и всю веру в справедливость этого мира потеряет.



Да, ОП, настало время открыть грустную байтоёбскую правду - игровой движок - это по факту скриптомашина (в 99% случаев интерпретатор) с каким-либо динамическим скриптом (в 99% случаев Луа), шурупами прикрученная к графическому, физическому, звуковому и прочим движкам, которые являются в свою очередь обобщениями и оптимизацией над API. Игры не пишут на С++, на С++ пишут бэкенды к скриптомашине. Игры пишутся на LUA, блядь, на сраном примитивном скрипте - вот на чём на самом деле пишутся игры.
>> No.13606 Reply
>>13605


Иными словами на плюсах, если рассматривать модель MVC пишется только V, ну ещё может немного С, если к контроллеру можно физический движок отнести. Всё остальное - ЛУА
>> No.13607 Reply
>>13606

Так что, если тебе кто-то будет доказывать крутость плюсов поскольку на них написана программанейм и круйзиснейм - смело ебошь в лицо. Потому что внутри круйзиснейм и сложнаяпрограмманейм кода на плюсах максимум треть, (требующая производительности часть), всё остальное - VM и на ней какая нибудь ЛУА или ПЕТОН или там ЛИСП).
>> No.13608 Reply
Программист казуалок за еду в треде.
>>13605
Дёрни себе анус, ты преувеличиваешь. Большую часть кода занимает бэкенд к луа, т.е. система сущностей и прочая поеботина. Плюс, хуйня не имеет права называться джвижком, если там нет редактора, который оставит из ручной работы только написание логики на луа. Для примера - на работе, джвижок - 5Мб кода, средняя игра - ~500 Кб луа кода.

А на чантру не пиздите, чего вы ждёте от кучки энтузиастов? Продашн-кволити кода?
>> No.13609 Reply
>>13602
А почему прошлогодняя, почему не с свна?
>> No.13610 Reply
>>13605
>>13606
Пиздец, как-будто это не было давно общеизвестным фактом.
>> No.13615 Reply
File: priznak_koshkosti_40.jpg
Jpg, 31.57 KB, 580×180 - Click the image to expand
edit Find source with google Find source with iqdb
priznak_koshkosti_40.jpg
>>13594
> RenderManager.DrawSprite("Ship", i, 1);
Идея хорошая, но есть пара проблем:
1) Я хотел рассматривать все, абсолютно все картинки (даже те, которые лежат в файлах с сеткой) отдельно друг от друга. Во имя унификации и дабы не ограничивать построитель атласов.
2) Внутреннюю структуру данных строить тяжелее.
> Порядок отрисовки
Очередности, няши, очередности. Перед каждым рендерящимся спрайтом указывается его очередность (либо в качестве параметра AddSprite(...), либо отдельной функцией SetPriority(...)). В пределах одной очередности спрайты рендерятся в произвольном порядке (единственное, если юзер сказал RenderManager.ActivateEffect(Blink); RenderManager.AddSprite(SomeSprite); RenderManager.DeactivateEffect(...);, то под эффектом Blink должен отрендериться именно SomeSprite и только он). Единственная гарантия (наряду с порядком наложения эффектов) - это что, например, спрайт, добавленный с очередностью 0, будет рендериться раньше, чем спрайт, добавленный с очередностью 1. Это как раз и позволяет сортировать спрайты по атласам за O(1).

В DobrochanTest очередность должна указываться в RenderAspect-е или передаваться им в RenderManager. GameObject про очередность (да вообще про рендеринг) там знать ничего не должен.

>>13596
> <sprite id="Ship" file="Common\Ship.png" cols="3" rows="1"/>
В этом случае весь файл - сетка. Размер ячейки определяется через размер картинки в файле и cols и rows.
> Движок - это скриптомашина
У нас скрипты будут писаться на C#. Если бы мы писали движок на C++, то да, пришлось бы прикручивать Луа.

>>13610
> как-будто
Я долго терпел, но это вывело меня из себя. Чтоб тебя граммар-наци каждую ночь гомосексуалистом делали.

Скоро выдам новую охретектуру.
>> No.13629 Reply
File: 8264064.png
Png, 182.00 KB, 500×750 - Click the image to expand
edit Find source with google Find source with iqdb
8264064.png
>>13615
> 1) Я хотел рассматривать все, абсолютно все картинки (даже те, которые лежат в файлах с сеткой) отдельно друг от друга.
Но зачем? Если они лежат сеткой, то это не случайно. Если тебе нужен только единичный спрайт из сетки, то просто пишешь: DrawSprite("Trees", 5, 2, …);
С другой стороны будет очень неудобно перебирать имена, используя шаманство над строками.
> Во имя унификации и дабы не ограничивать построитель атласов.
> 2) Внутреннюю структуру данных строить тяжелее.
Считай, что это лежит на мне, и с этим уже все ОК. И для построителя атласов таки проще, чтобы картинки были уже собраны в одну, как в случае с сеткой.

Кстати, прикрутил утилитку определения габаритов пикчи без её загрузки — по заголовку файла. Попозже оптимизирую работу сборщика атласов.
> Очередности, няши, очередности.
Ты опять о чем-то о своем.
Моделируем ситуацию. Вот кучка спрайтов, уже отсортированных по очередности:
1) Использует текстуру из 1го атласа.
2) Использует текстуру из 2го атласа.
3) Использует текстуру из 2го атласа и шейдер.
4) Использует текстуру из 1го атласа.
5) Использует текстуру из 1го атласа.
6) Использует текстуру из 1го атласа и шейдер, которому нужна карта шума, которая находиться во 2м атласе.
Таким образом, для 1,2,3 спрайтов нужны разные VBO. 4 и 5 можно сгруппировать в один VBO. С 6м я вообще хз что делать. Разумеется на месте 1) 2) и 3) будет не по одному спрайту, а по несколько подобных.
Поэтому понадобиться несколько VBO, причем их кол-во и настройки каждого из них заранее не известны и могут быть разными для каждого фрейма, и эффективный алгоритм группировки спрайтов по этим VBO.
Я бы забил на шейдеры и ограничился одним атласом. В крайнем случае, держать, например, 3 атласа: для фона, остальных объектов и интерфейса.

Алсо, в твоих SetPriority(), RenderManager.ActivateEffect() и прочих "установщиков состояния" не вижу смысла, т.к. объект рисует свои 3,5 спрайтика, для которых это можно установить и индивидуально, а между объектами сохранять это состояние нет смысла. Да и анимацией(тот же Blink) должен заниматься не рендерМенеджер.
>> No.13642 Reply
File: priznak_koshkosti_41.gif
Gif, 14.48 KB, 580×180 - Click the image to expand
edit Find source with google Find source with iqdb
priznak_koshkosti_41.gif
>>13629
SetPriority() и ActivateEffect() - это как вариант избавиться от портянки аргументов в RenderSprite(). Можно и так, и так.
> Кстати, прикрутил утилитку определения габаритов пикчи без её загрузки — по заголовку файла.
Стоп, а с какими форматами мы работать умеем?
>> No.13647 Reply
>>13642

Подключай в проект СотоНУ.Нет и будет со всеми возможными работать.
>> No.13648 Reply
>>13647
Но зачем?
>> No.13651 Reply
>>13642
> Стоп, а с какими форматами мы работать умеем?
Jpg, Png, Bmp, Gif. Я думаю хватит.
>> No.13673 Reply
У меня вот какие идеи:
Спрайтам вне зависимости от того, сетка это или картинка задавать размер(все равно это будет делать какая-нибудь утилита), сетка просто имеет дополнительные свойства cols и rows.
Преимущества:
- Можно рассчитать размеры атласов даже не трогая картинки.
- Единообразие. В атлас все равно пихать всю картинку, а проверка на сетку будет дополнительным условием а не еще одним методом.
Недостатки:
Честно говоря, я не вижу. Возможно только чуть больше ручной работы по прописыванию размеров. Но зачем ее делать руками?
Спрайты имеют необязательное поле atlas, которое позволяет задать в каком атласе должен находиться спрайт. Это важно, например, если хочется собрать однотипные спрайты в один атлас, или какие-то спрайты сгруппировать в атлас, лежащий выше/ниже какого-нибудь. Отсуствие значения сортирует текстуры в обычном порядке, отрицательное значение - реверсированный порядок(сунуть в последний, например, очень удобно для интерфейса).
>> No.13678 Reply
>>13673
> Спрайтам вне зависимости от того, сетка это или картинка задавать размер
> - Можно рассчитать размеры атласов даже не трогая картинки.
Их все равно придется потрогать.
> - Единообразие. В атлас все равно пихать всю картинку, а проверка на сетку будет дополнительным условием а не еще одним методом.
Не вижу связи размера с сеткой. И каким еще методом?
Будут только лишние проблемы, если этот размер вдруг не совпадет с фактическим.
> Спрайты имеют необязательное поле atlas
Так на каком варианте работы рендерМенеджера мы остановились?
Да и 8192х8192 это очень большой размер, может все и влезет в один. Текстуры для шейдеров можно держать просто отдельными текстурами — все равно для каждого шейдера потребуется отдельный вызов.
>> No.13679 Reply
>>13678
> Их все равно придется потрогать.
Но при этом время пребывания их в памяти в необработанном состоянии сокращается, так как все, что от них требуется - скопироваться в атлас. Загружать можно по одной, а не все сразу, как придется делать в случае неизвестного размера, чтобы посчитать размеры атласа, что сократит потребление памяти(причем значительно, у меня перегонка картинок в атласы жрет сотни мегабайт, но там какие-то sdl-костыли) на этом этапе.
> И каким еще методом
В моем представлении, когда мы загружаем картинки разных типов, это влечет за собой и разную работу с ними(ту же проверку на сетку, сначала чтобы определить размер, потом чтобы посчитать и записать ячейки), что в идеале - метод для загрузки простого изображения и метод для загрузки изображения сетки.
Хотя, да, я наверное перемудрил, не так сильно оно и отличается.
> Будут только лишние проблемы, если этот размер вдруг не совпадет с фактическим
Тогда загружаться будет часть картинки. А в картинке можно будет хранить еще какой-нибудь мусор. Например, эта трава анимированная, у нее спрайт-сетка, а эта - нет, но они крайне схожи по логическому признаку(например, в игре больше нет травы вообще), и сделаны из одного спрайта. Абсолютно никакое доказательство, я вижу, не знаю, зачем привел.
В конце концов, менять размеры спрайта меняя размеры картинки - не очень правильная идея, мне кажется, для этого нужно использовать редактор изображений, что значительно более раздражающе, чем блокнот.
> может все и влезет в один
Суть не в том, влезет - не влезет, суть в том, чтобы если не влезало, то не возникало затруднительных ситуаций, которые потом выливаются в потерю производительности с труднообнаружимой причиной.
Идеальный алгоритм такой: мы получаем размеры картинок. Считаем количество атласов, которые понадобятся(также, да, а что насчет старых видеокарт, или только yoba, только аленвары?), и если их получается больше одного, то группируем спрайты по степени использования. Идея больше не в "этот спрайт во второй атлас, этот в третий, а этот в четвертый", а в возможность спрайтам указать, что они должны располагаться в конце или в начале.
>> No.13680 Reply
>>13679
> Но при этом время пребывания их в памяти в необработанном состоянии сокращается
В последней версии я сделал так, что, для проверки габаритов, загружаются только заголовки картинок(они по несколько байт). Вся пикча загружается только при отрисовке в атлас, сразу же выгружаясь после этого.

На данный момент принцип работы такой:
Загрузка из xml-файла вида:
<Textures>
<Texture id="ID" file="FILE_NAME"/>
<Texture id="ID" file="FILE_NAME" cols="M" rows="N"/>
<Texture id="ID" file="FILE_NAME" left="X" top="Y" width="W" height="H"/>
<Texture id="ID" file="FILE_NAME" cols="M" rows="N" left="X" top="Y" width="W" height="H"/>
…
</Textures>
В первом случае текстура = всей пичкче, соответственно из её параметров и получает ширину и высоту. cols и rows просто равны "1".
Во втором cols и rows указываются.
В третем можно выбрать расположение текстуры в пикче на случай:
> А в картинке можно будет хранить еще какой-нибудь мусор.
В четвертом сетка ≠ всей пикче и её также можно отдельно указать.

Со всеми работа идет одним методом:
void AddSprite(Vector2 position, int textureId, int col, int row, Color color, float rotation, float scale, bool isCenter) с кучей перегрузок с параметрами по умолчанию. И если col и row не указываются, то они = 1, а сами текстурные координаты определяются:
RectangleF TextureLocation; // Расположение текстуры в атласе.
float sectionWidth, sectionHeight;  // ширина и высота одного прямоугольничка из сетки.

RectangleF GetSubTextureLocation(int i, int j)
{
	if (Cols == 1 && Rows == 1)
		return TextureLocation;
	i %= Cols;
	j %= Rows;
	return new RectangleF(TextureLocation.X + i * sectionWidth, TextureLocation.Y + j * sectionHeight, sectionWidth, sectionHeight);
}
> а в возможность спрайтам указать, что они должны располагаться в конце или в начале.
Хм, подумаю над этим.
>> No.13748 Reply
ОП, маленько заболел и отошел от дел. Следующий раз обещает пердуперждать.
>> No.13784 Reply
Я наконец-то освободился и готов пилить свои костыли, что у нас есть?
>> No.13787 Reply
>>13784
Почти сделал возможность использования произвольного кол-ва атласов и чють оптимизировал сборку атласа, надо только немного потестить и навести марафет.
Продумал как сделать, чтобы можно было отрисовывать спрайты в указанном порядке при использовании нескольких атласов, но в эту схему попрежнему не вписываются шейдеры для объектов. Может все-таки забьём на них?
>> No.13789 Reply
>>13787
Пока можно и забить. Не спешим же никуда.
>> No.13790 Reply
>>13787
> > чють
ну ты понел
>> No.13799 Reply
File: JBG95rqkp3s72.jpg
Jpg, 40.16 KB, 400×600
edit Find source with google Find source with iqdb
JBG95rqkp3s72.jpg
File: priznak_koshkosti...
Jpg, 78.34 KB, 580×397
edit Find source with google Find source with iqdb
priznak_koshkosti_42.jpg

И вот я вернулся. Рад, что вы еще со мной.

Я много думал, читал, мысленно экспериментировал и принес вам много замечательных идей. Пока только оцените (ничего кодировать не надо; если будет годно, то я продолжу уже с конкретикой):

1) Окончательно отделить рендеринг от логики. И вообще писать все аспекты игры отдельно. Пусть, скажем, "отдел рендеринга" занимается исключительно рендерингом и просто предоставляет архиудобное API другим отделам. "Отдел звука" пусть занимается звуком и предоставляет архиудобное API для звука. "Отдел логики" пусть занимается логикой и может быть пользуется API для рендеринга.
2) Retained mode. Никто каждый кадр ничего не перерисовывает. Просто имеется некоторый объект "сцена", описывающая текущее изображение. Меняешь "сцену" - меняется изображение. Не меняешь "сцену" - изображение остается неизменным.
3) Удалять объекты из списков можно за O(1), если у объектов есть флаг "удален".
4) Все объекты на рендерящейся сцене описываются ацикличным графом.

А теперь конкретно. API для рендеринга. Имеем некий глобальный объект экрана:
class GLScreen
{
    public static GLScreen Instance { get; }
    public void Init(...) {...}
}
Имеем спрайты, которые мы можем кидать на экран:
class Sprite
{
    public Sprite(...) { ... }  // О создании спрайтов потом.
    public Vector2D Pos { get; set; }
    public float Rotation { get; set; }
    public float Scale { get; set; }
    public int Order { get; set; }
    public Sprite AddTo(GLScreen) { ...; return this; }
    public void Remove() { ... }
    // Методы, скрытые от клиентов rendering API, но нужные
    // для работы:
    internal int TextureID { get; }
    internal Vector4D BoundsInTexture { get; }
    ...
}
Add() и Remove() я запихал в Sprite, а не в GLScreen, потому что Remove(), работающий через флаг "удален" в объекте и запиханный в GLScreen, будет работать неправильно. Об этом чуть позже.

По реализации. Спрайты сортируются по порядку (Order) и атласу (TextureID) во время добавления. Order можно менять только тогда, когда спрайт еще никуда не добавлен. Это ограничение можно и снять, но тогда реализация усложняется в разы.

Имеем составной спрайт:
class CompoundSprite
{
    // Все то же, что и в Sprite:
    public Vector2D Pos { get; set; }
    public float Rotation { get; set; }
    public float Scale { get; set; }
    public int Order { get; set; }
    public CompoundSprite AddTo(CompoundSprite) { ...; return this; }
    public void Remove() { ... }
    // плюс свои свойства и методы:
    public IEnumerable Items { get; }  // Заметка: Хотя вот это вот, наверно, ни в хуй не вперлось.
    // Еще надо добавить методы по управлению
    // отображением содержимого:
    public Vector2D CameraPos { get; set; }
    public float CameraAngle { get; set; }  // Кстати, здесь и может понадобиться GL.PushMatrix и GL.PopMatrix.
    ...
}
class Sprite
{
    public Sprite AddTo(CompoundSprite) { ...; return this; }
}
GLScreen тоже можно сделать компаундом. Или тупо форвардить все его методы в какой-нибудь дефолтный компаунд, с Order = 0.

Такая система (спрайтов и компаундов) позволит реализовать довольно сложные вещи, как-то: радар на HUD, вложенные экраны, split-mode и прочее - один и тот же спрайт добавляется в два компаунда, и рендерер будет отображать его в двух местах.

Компаундам можно выставить эффект:
class Effect
{
    public abstract void SetUp();
    public abstract void TearDown();
}
class CompoundSprite
{
    public Effect Effect { set; }  // Именно так, в количестве одна штука.
}
Любой компаунд с точки зрения клиента Rendering API рендерится так: сначала SetUp()-ится эффект (если есть), потом рендерятся все вложенные элементы, потом эффект TearDown()-ится.

Кстати, ограничение размеров компаунда (например, мини-экран, показывающий катсцену, происходящую в другом месте, обрезает все, что не влезает в него) тоже можно реализовать эффектами. Поэтому я и не вводил никаких VisibleRect в CompoundSprite.

В принципе, можно и простым спрайтам добавить поле Effect, но это снова усложняет реализацию в разы.

Да, немного о реализации. Итак, клиент Rendering API собрал сцену из спрайтов и компаундов. И что дальше? А дальше эта сцена рендерится по каждому событию GameWindow.OnRender. Параллельно в этом же событии удаляются элементы с выставленным флагом Removed (который выставляется методом Remove()).

Как все это рендерится: для каждого Order (отдельно для -1, отдельно для 0, отдельно для 1 и т. д.) мы сначала пробегаемся по всем спрайтам на экране и накапливаем вертексно-тексельный буфер, потом сливаем этот буфер, а потом отдельно вызываем Render() у каждого компаунда в данном Order. Внутри CompoundSprite.Render() делаем то же самое: накапливаем вертексный буфер из спрайтов, сливаем, потом бежим по вложенным компаундам. Да, компаунды при такой схеме получаются относительно тормозными, но программист в здравом уме будет делать их количество минимально необходимым. А значит, и тормоза будут в пределах необходимого.

А как быть с эффектами? Предположим, у нас есть такая сцена:
Compound1(Effect = TVNoise):
    Compound2(Effect = Blinking):
        PlayerSprite
Активировать сразу и TVNoise, и Blinking нельзя. Как быть? Есть вариант использовать многошаговый рендеринг с "выворачиванием сцены наизнанку":
1) На первом шаге каждый "заэффектенный" компаунд рендерит свои внутренности во временную текстуру (понятно, что текстура не будет каждый раз создаваться), причем порядок рендеринга будет от самого внутреннего компаунда к самому внешнему (если честно, плохо представляю, как это можно реализовать, но можно же ведь).
2) На втором шаге рендерятся и спрайты, и компаунды, но компаунды просто рендерят свою временную текстуру.

Вот почему я сделал поле Effect, а не Effects - с множеством эффектов на одном компаунде мы бы вообще запутались.

Еще мы имеем отдельный класс объектов сцены, которые не рендерятся, но определенным образом влияют на рендеринг:
class Other
{
    ...
}
// Эта штука занимается тем, что постоянно удаляет
// спрайт старого кадра из компаунда, в котором
// она лежит, и добавляет спрайт нового кадра.
class Animation : Other
{
    public void Play() { ... }
    public void Stop() { ... }
    public void Rewind() { ... }
    public float Speed { get; set; }
    ...
}
Немного о ресурсах. Имеется некий класс ResourceManager:
class ResourceManager
{
    public static void ClearResources() { ... }
    public static void Load(String ConfingFileName) { ... }
}
Кстати, конфиги:
<config>
    <sprite id="Airplane" file="airplane.png"/>
    <sprite id="Boss" file="boss.png" x="100" y="200" width="500" height="600"/>
    <sprite id="Tree" ... />   <!-- Короче, все варианты задания спрайтов -->
    <animation id="Tree swinging" speed="4/1">
        <sprite id="Tree" col=1 row=1/>
        <sprite id="Tree" col=2 row=1/>
        <sprite id="Tree" col=3 row=1/>
        <sprite id="Tree" col=4 row=1/>
    </animation>
</config>
А в каком виде ресурсы хранятся в программе? А вот в каком:
class ResourceManager
{
    public Sprite GetSprite(String ID) { ... }
    // Плюс перегрузки с указанием положения в сетке.
    public Animation GetAnimation(String ID) { ... }
    ...
}
class Sprite
{
    public Sprite Clone() { ... }
}
class Animation
{
    public Animation Clone() { ... }
}
// ... И так каждый вид ресурса.
// Можно ввести утилитарные конструкторы:
class Sprite
{
    public Sprite(String ID) { /* достать все данные из ResourceManager */ }
}
class Animation
{
    public Animation(String ID) { ... }
}
О логике. Я особо над ней не думал, но, думаю, вполне достаточно будет какого-нибудь глобального объекта GameWorld, и при этом можно будет обойтись без составных объектов. Параллельно GameWorld будет служить чем-то вроде менеджера корутин (то есть, игровые объекты будут фактически представлять из себя корутины). Но! Я хочу каждому объекту добавить свойство Exists:
class GameObject
{
    public bool Exists { get; }
}
Это очень удобное поле. В частности, его можно будет использовать в Rendering API: очень часто спрайты/анимации/прочее живут ровно столько же, сколько и объект, который ими управляет. Поэтому:
class IExisting
{
    public bool Exists { get; }
}
class Sprite/Animation/Anything
{
    public Sprite(..., IExisting Synchro) { ... }
}
Sprite/Animation/Anything, если он получил Synchro при создании, как только получает false от Synchro.Exists, тут же удаляет сам себя отовсюду.

Вообще, в Rendering API можно добавить кучу утилитарных свойств и методов. Тут никто не мешает.
>> No.13800 Reply
>>13799
> И вообще писать все аспекты игры отдельно.
А изначально это планировалось не так?
> Никто каждый кадр ничего не перерисовывает.
Что-то странное ты придумал.
> Order можно менять только тогда, когда спрайт еще никуда не добавлен.
Своидит на нет все потуги, ибо ничего не мешает просто добавлять спрайты в нужном порядке. Как ты собрался менять порядок спрайтов в процессе?
> спрайты
Как-то не хорошо пихать рендер в спрайты, мне кажется.
> дальше я пока тебя не понял
> конфиги
> animation
Это свойство объектов, а не картинок и должно быть в описании объектов, мне кажется.
> очень часто спрайты/анимации/прочее живут ровно столько же
В зависимости от типа игры, они могут быть просто за экраном. В итоге это у тебя разрастется в exists, visible, dead, и т.д. Но тут ничего не поделаешь.
> class IExisting
Какое-то лишнее ооп, достаточно объектманагера. Объекты удаляющие сами себя ничего кроме проблем обычно не приносят.
>> No.13808 Reply
File: 1281803626291.jpg
Jpg, 159.55 KB, 500×500 - Click the image to expand
edit Find source with google Find source with iqdb
1281803626291.jpg
>>13799
> Имеем некий глобальный объект экрана: class GLScreen
Ну вот опять. У нас и так есть глобальный "экран" любезно предоставленный openGL. Или ты под этим GLScreen понимаешь нечто среднее между камерой и тем, что я называю рендерМенеджером?
> public Sprite AddTo(GLScreen) { ...; return this; }
Вут? Какой смысл в return this; если, что бы вызвать этот метод, надо уже иметь экземпляр класса?
> Add() и Remove() я запихал в Sprite
Странно они тут смотрятся и все равно эти методы понадобятся в твоем GLScreen.
> Имеем составной спрайт: CompoundSprite
Тут надо юзать либо просто полиморфизм (со Sprite в одной иерархии), либо паттерн Composite, чтобы всех обрабатывать в одном потоке.
> public Vector2D CameraPos { get; set; }
Причем тут камера?
> public Effect Effect { set; }
Просто придирка: либо сделать это доступным для чтения, либо сделать методом.
> Как все это рендерится:
Мне кажется это накроет медным тазом весь эффект от буферов. Лучше эффект передавать с каждым спрайтом, а потом группировать по эффектам. Не представляю как сделать один эффект на составной объект, ведь надо будет пересчитывать параметры для каждого вложенного объекта.
> компаунд рендерит свои внутренности во временную текстуру
А это накроет идею с текстурным атласом и вдвое увеличит время рендеринга этого объекта.
> <animation id="Tree swinging" speed="4/1">
Тут только загрузка текстур, как они используются дело спрайтов.
> class ResourceManager
> public Sprite GetSprite(String ID) { ... }
Ресурс — это картинка, спрайт — инфа, где эту картинку отрисовать.

>>13800
> Как-то не хорошо пихать рендер в спрайты, мне кажется.
Как я понимаю, оно так и есть. Непосредственно вызов GL-функций где-то в другом месте, а в самом спрайте только инфа для этих функций.
>> No.13809 Reply
>>13808
> в самом спрайте только инфа
Одно дело, когда спрайты хранят информацию, как себя рисовать, другое - когда они еще и сами себя рисуют дергая библиотеки ядра.
>> No.13814 Reply
File: 423_1185024313.jpg
Jpg, 24.09 KB, 600×450
edit Find source with google Find source with iqdb
423_1185024313.jpg
File: priznak_koshkosti...
Jpg, 23.36 KB, 580×180
edit Find source with google Find source with iqdb
priznak_koshkosti_43.jpg

>>13800
> > И вообще писать все аспекты игры отдельно.
> А изначально это планировалось не так?
Ну, я не делал упор на этом.
> Никто каждый кадр ничего не перерисовывает.
Это с точки зрения пользователя Rendering API. Внутри Rendering API всё та же пробежка по сцене каждый кадр.
> > Order можно менять только тогда, когда спрайт еще никуда не добавлен.
> Своидит на нет все потуги, ибо ничего не мешает просто добавлять спрайты в нужном порядке. Как ты собрался менять порядок спрайтов в процессе?
> ничего не мешает просто добавлять спрайты в нужном порядке
Как не мешает? А как же игро-объекты - клиенты Rendering API - которые "вызываются" в произвольном порядке и кидают спрайты на сцену, когда захотят?
А сменить порядок отображения спрайта (кстати, когда это вообще может понадобиться?) просто: клонируешь спрайт, удаляешь исходный, у склонированного меняешь Order, потом кидаешь его обратно на сцену. Можно запихнуть это все в утилиту.
>>13808
> Ну вот опять. У нас и так есть глобальный "экран" любезно предоставленный openGL. Или ты под этим GLScreen понимаешь нечто среднее между камерой и тем, что я называю рендерМенеджером?
Да.
> > public Sprite AddTo(GLScreen) { ...; return this; }
> Вут? Какой смысл в return this; если, что бы вызвать этот метод, надо уже иметь экземпляр класса?
Просто понравилось, как фурроним сцеплял методы. Можно возвращаемый тип и на void заменить.
> > Add() и Remove() я запихал в Sprite
> Странно они тут смотрятся и все равно эти методы понадобятся в твоем GLScreen.
Я бы сказал, непривычно. Все привыкли, что Add() и Remove() имеются у контейнера (и это вполне логично, кстати), поэтому AddTo() и Remove() у подконтейнерного объекта выглядят странновато. Но, повторюсь, я пытаюсь реализовать добавление и удаление объектов за O(1), а в случае с Add() и Remove() у контейнера Remove() корректно не реализовать. В том алгоритме, который я придумал, можно удалить спрайт только из всех контейнеров сразу. За O(1).
Если честно, я бы не стал заморачиваться с "O(1) при удалении из сцены", если бы не боялся тормозов в динамичных играх с сотнями пуль и партиклей.
Да, а почему они понадобятся в самом GLScreen? Разве их нельзя просто-напросто форвардить в AddTo() и Remove() у объекта?
UPDATE: Идея. Можно реализовать Add() у контейнера, а Remove() - и у контейнера, и у объекта. Remove() у контейнера будет удалять объект только из этого контейнера, но за O(n), а Remove() у объекта - из всех контейнеров сразу, но за O(1).
> > Имеем составной спрайт: CompoundSprite
> Тут надо юзать либо просто полиморфизм (со Sprite в одной иерархии), либо паттерн Composite, чтобы всех обрабатывать в одном потоке.
Еще не известно, как это все будет рендериться. Детали реализации же. Наиболее шустрый вариант, который я вижу - это хранить спрайты, компаунды и "другие" вещи в разных списках и обрабатывать эти списки по-разному. Можно, конечно, всем рендерящимся вещам присобачить виртуальный метод Render() и запихнуть их все в один список, но это может оказаться сложнее реализовать. Задача Rendering API заключается ведь не в вызове определенных виртуальных методов в определенном порядке, а в рендеринге сцены.
> > public Vector2D CameraPos { get; set; }
> Причем тут камера?
Ну, что такое камера, и какую роль она играет для сцены, всем понятно. Но внутри компаундов может существовать своя, отдельная камера, которая меняет рендеринг только входящих в него спрайтов. Например, если мы показываем катсцены через выскакивающие мини-экраны, то мини-экран будет представляться компаундом, внутри которого будет своя система координат, указывающая на происходящее в другом месте. Или в сплит-моде: весь экран разбит на два больших компаунда, в каждом из которых свои системы координат.
Я не знал, как эту "внутреннюю" систему координат назвать получше.
> > компаунд рендерит свои внутренности во временную текстуру
> А это накроет идею с текстурным атласом и вдвое увеличит время рендеринга этого объекта.
...либо рендерится напрямую на экран (используя свои вертексно-тексельные буферы), если на нем нет эффекта. Не забывайте, что это компаунды, а не отдельные объекты, и их в типичной игровой сцене будет максимум несколько штук.
> Ресурсы
Вот, а я предлагаю:
- Избавиться от лишнего шага по преобразованию картинок и wav-ников в Sprite, Sound и прочее и получать на выходе ресурс-менеджера нужные нам объекты сразу. Все равно мы не работаем напрямую с картинками и звуками, так зачем они вообще нам нужны? Давайте работать сразу со спрайтами, sound-ами и т. д. Ресурс-менеджер выдает нам нужные объекты, а мы просто клонируем их и кидаем на сцену. Или не клонируем, так и кидаем, лол. А внутри он пусть хранит текстурные атласы, звуковые паттерны, чертей лысых - нам, пользователям его API, по барабану. Да, внутри спрайтов могут храниться ID текстурных атласов, координаты в атласе и прочее, но пусть это будут внутренние дела спрайта и ресурс-менеджера. Программист пусть видит только спрайт. А художник его конфигурирует.
- Раз уж в качестве ресурсов у нас выступают сами спрайты, а не картинки, то давайте и анимации тоже сделаем ресурсами. Заодно отделим работу программиста от работы аниматора.
И нет, я не согласен, что анимации - это свойство объектов. Само слово "анимация" ассоциируется с картинкой, а не с логикой. К тому же, мало ли как игро-объект захочет себя отобразить? Может, ему захочется две анимации запустить (два огонька, летающие вокруг жнеца в Лунарии). И раз уж мы решили отделять логику от рендеринга (и от остальных аспектов), то давайте отделять до конца.
> в самом спрайте только инфа
С точки зрения пользователя Rendering API - да. Возможно, реализовать рендеринг будет удобно через какие-нибудь виртуальные методы составных элементов сцены, но эти методы будут скрыты от глаз пользователя. Так что формально спрайты остаются структурами, хранящими инфу, как себя рисовать.
> Эффекты
Я объясню еще раз. Компаунды могут иметь эффект. Этот эффект (с точки зрения пользователя) накладывается на все составные части этого компаунда. То есть, в варианте
> Лучше эффект передавать с каждым спрайтом, а потом группировать по эффектам.
это будет аналогично тому, что всем спрайтам под компаундам выставили один и тот же эффект. Но возникает проблема, которую я описал: вложенные компаунды тоже могут иметь эффект, и пользователю хотелось бы, чтобы эти эффекты наложились друг на друга. Разберем пример: игрок нажимает на рычаг, и выскакивает окошко, показывающее изображение от шумящей камеры, которая смотрит на дверь под силовым полем. То есть, имеем общую сцену с кучей спрайтов, компаунд-окошко с эффектом, внутри которого компаунд-дверь с другим эффектом.

Я предложил все это рендерить в два шага:
1) Сначала все компаунды рендерятся в свою внутреннюю текстуру (от внутреннего к внешнему). То есть, сначала отрендерится дверь под эффектом "силовое поле" (и сформируется текстура "дверь под силовым полем"), потом окошко под эффектом "шум" (с использованием текстуры "дверь под силовым полем"; при этом сформируется текстура "зашумленное окошко").
2) Потом сцена рендерится как обычно: все элементы сцены сливают свои данные в вертексно-тексельный буфер, привязанный к их атласу, потом буфер отправляется на видяху. Компаунды рендерятся точно так же, но атлас они указывают не тот, который им выдал ресурс-менеджер (как у спрайтов), а свой собственный, который они сами сформировали.

Но такой способ целесообразен только для компаундов с эффектами. Для обезэффекченных компаундов (лол, вот это я завернул) логичнее будет просто сливать координаты вертексов и текселей своих внутренних спрайтов в общий буфер (то есть, просто форвардить запрос "скинь все координаты вот в этот вертексно-тексельный буфер" своим внутренним элементам). Ну, можно же if (Compound.Effect == null) в обоих шагах поставить.

Да, кстати, насчет формирования вертексно-тексельных буферов. Я вот думаю, как лучше сделать: сортировать спрайты по порядку и по атласам во время добавления их на сцену (но тогда возникают проблемы с обезэффекченными компаундами, им придется формировать свои собственные вертексно-тексельные буферы) или добавлять их в произвольном порядке и во время рендеринга собирать одну большую текстуру OrderedMap<Order, Map<AtlasID, VertexAndTextelPos>>. В первом случае будет в-среднем-O(1) при формировании сцены и O(1) при рендеринге, а во втором - O(1) при формировании и в-среднем-O(1) при рендеринге (что как бы хуже).
>> No.13829 Reply
>>13814
> > Или ты под этим GLScreen понимаешь нечто среднее между камерой и тем, что я называю рендерМенеджером?
> Да.
Тогда убери из названия "GL" — он тут не причем. И объект Камера уж точно не будет унаследованым объектом от GameObject, а просто методами, вызываемыми перед началом рендеринга для каждого GLScreen.
> фурроним
Что это?
> Все привыкли, что Add() и Remove() имеются у контейнера (и это вполне логично, кстати), поэтому AddTo() и Remove() у подконтейнерного объекта
> за O(1)
Что ты прицепился к этому О(1). Единственная проблема тут — это работа класса List<>, у которого операция удаления — О(n). Остальное не имеет значения. Тут либо заменять на связаный список, либо оставить как есть, так как у связного списка обход всех элементов будет медленнее и не известно еще, что будет выгоднее.
> Задача Rendering API заключается ведь не в вызове определенных виртуальных методов в определенном порядке, а в рендеринге сцены.
<Сарказм> А наша задача не кодить, а игру делать. </Сарказм>
> Но внутри компаундов может существовать своя, отдельная камера, которая меняет рендеринг только входящих в него спрайтов.
"Окно в окне" и прочее лучше делать с помощью нескольких GLScreen с изменением вьюпорта. А в составных объекта лучше использовать относительные системы координат. Типа: составной спрайт "чувачок" с координатами (X,Y); вложенные спрайты : тело(0,0), рука (-20,-20), кэпка(0,+20) итд. И координаты вложенных объектов пересчитывать относительно внешних.
> - Избавиться от лишнего шага по преобразованию
Нет никакого преобразования. Картинка — эта картинка, спрайт — это спрайт.
> анимации тоже сделаем ресурсами.
Еще раз посмотри на мои RenderAspect. Ты плодишь лишнее сущности.
> Разберем пример: игрок нажимает на рычаг, и выскакивает окошко, показывающее изображение от шумящей камеры
Глобальные эффекты для окошек можно делать для всего GLscreen одинм шейдером. Для остальных — по одному эффекту на спрайт. Рендериь в текстуру каждый уровень вложенных объектов — бред и не нужно.

Я б на твоем месте еще задумался о взаимодействии спрайта и объекта, которому этот спрайт пренадлежит.
>> No.13832 Reply
>>13814
> кстати, когда это вообще может понадобиться
Когда порядок отрисовки играет какую-то логическую роль, изометрия, например.
> клонируешь спрайт, удаляешь исходный, у склонированного меняешь Order, потом кидаешь его обратно на сцену
Пиздец. У меня нет другого слова для описания этого процесса.
> добавление и удаление объектов за O(1)
Но зачем? Добавление и удаление объектов - довольно редкий процесс.
> тормозов в динамичных играх с сотнями пуль и партиклей
Тормоза отнюдь не в добавлении и удалении.
> Само слово "анимация" ассоциируется с картинкой
Нет, картинка - это картинка. Анимация - набор меняющихся картинок, собранных каким-то объектом и характеризующих этот объект. Одна картинка из анимации совсем не имеет никакой связи с другими картинками из анимации(кроме визуальной, разумеется, но это не более, чем рюшечки).
>> No.13866 Reply
File: priznak_koshkosti...
Jpg, 25.65 KB, 580×180
edit Find source with google Find source with iqdb
priznak_koshkosti_44.jpg
File: JBGb7pd5c81wf.jpg
Jpg, 29.36 KB, 439×600
edit Find source with google Find source with iqdb
JBGb7pd5c81wf.jpg

>>13829
> И объект Камера уж точно не будет унаследованым объектом от GameObject
Я перепридумывал всю архитектуру с нуля несколько раз. В текущей инкарнации никакой связи (по крайней мере, статической) между Rendering API и Аспектом Логики нет. Понятие камеры есть только в Rendering API (если вообще есть теперь).
> Единственная проблема тут — это работа класса List<>, у которого операция удаления — О(n)
Вот эту проблему я и пытался решить. И, кажется, решил.
> "Окно в окне" и прочее лучше делать с помощью нескольких GLScreen с изменением вьюпорта. А в составных объекта лучше использовать относительные системы координат. Типа: составной спрайт "чувачок" с координатами (X,Y); вложенные спрайты : тело(0,0), рука (-20,-20), кэпка(0,+20) итд. И координаты вложенных объектов пересчитывать относительно внешних.
Да. Только я склоняюсь к тому, что будет проще реализовать Screen как CompoundSprite.
UPDATE: Не катит. А если мини-окошко круглое, или основную камеру перекосило?
> Нет никакого преобразования. Картинка — эта картинка, спрайт — это спрайт.
Как это нет? А конфиг, в котором картинке присваивается ID для спрайта? А new Sprite(String pictureID)?
> Еще раз посмотри на мои RenderAspect. Ты плодишь лишнее сущности.
Так. Ты постоянно отсылаешь меня к RenderAspect, а я постоянно смотрю только его часть. Давай разберемся. RenderAspect - это что такое? Как я понял, это нечто, чем игро-объект рендерит себя - спрайт, набор спрайтов, анимация и т. д. Я правильно понял?
У меня тоже, в общем-то, будет общий класс для всего, что попадает на Screen. Но я подозреваю, что он будет пустой и потому бесполезный.
А рендерятся игро-объекты у меня теперь так: внутри своей логики они делают var x = new Sprite("ABC").AddTo(Screen);. А когда больше не хотят отображаться, то делают x.Remove().
Полноценный пример:
class Жнец
{
    public IEnumerator Logic()
    {
        var fires = new Animation[] {
            ResourceManager.NewAnimation("Reaper fireball"),  // Можно так...
            new Animation("Reaper fireball")   // ...а можно и так.
        };
        fires[0].Pos = new Vector2D(0, 100);
        fires[1].Pos = new Vector2D(0, -100);
        foreach (var fire in fires)
        {
            fire.AddTo(Screen);
            fire.Play();
        }
        ...
        // Сдохли!
        fires[0].Stop();   // Не обязательно.
        fires[0].Remove();
        fires[1].Remove();
    }
}
> Для остальных — по одному эффекту на спрайт
А как же "чувачок" под "аурой быдлятства" (лол)?
> Я б на твоем месте еще задумался о взаимодействии спрайта и объекта, которому этот спрайт пренадлежит.
Уже начал. Один из утилитарных конструкторов (или специальный метод) синхронизирует рендерящийся итем с игро-объектом. Когда игро-объект исчезает, рендерящийся итем тоже удаляется:
class Sprite
{
    public Sprite(IExisting/GameObject synchro) { ... }
}
>>13832
> Когда порядок отрисовки играет какую-то логическую роль, изометрия, например.
Не следует путать порядок отрисовки и взаимное расположение объектов. В Крузисе (не наш случай, просто чтоб показать) деревья могут отображаться в произвольном порядке, но с учетом координаты z. Солнце там может отображаться без учета координаты z, но строго после всех деревьев.
> > клонируешь спрайт, удаляешь исходный, у склонированного меняешь Order, потом кидаешь его обратно на сцену
> Пиздец. У меня нет другого слова для описания этого процесса.
Ну, это если менять Order запрещено. А запрещено его менять может быть тогда, когда спрайты сортируются по атласу и порядку при добавлении. Если добавляются как попало, то можно Order сделать всегда мутабельным.
> Тормоза отнюдь не в добавлении и удалении.
А в чем?
> Анимации
Да, согласен, "картинка", "спрайт" и уж тем более "анимация" - это все разные понятия. Да, "анимация" - это в общем случае очень сложная вещь, определяющаяся в том числе и логикой игры. Да, ресурс-менеджер занимается только "картинками".
Но! Никто ведь не запрещает переложить работу (или хотя бы ее часть) по формированию "спрайтов" и "анимаций" из картинок на ресурс-менеджер. Мы все равно в коде игры работаем только со "спрайтами" и "анимациями" (с "картинками" - едва ли), так пусть ресурс-менеджер сразу предоставляет нам готовый материал.
Хотя, в принципе, можно оставить и ресурс-менеджер, работающий с картинками. Все равно наиболее удобный способ создания спрайта - это new Sprite(String pictureID). Но вот сборку анимаций можно и переложить на его плечи. Примерно 102% анимаций - это спрайты одинакового размера, циклично меняющиеся с определенной частотой. И описываются они классом:
class Animation
{
    public Animation(IEnumerable<Sprite> frames, float speed) { ... }
    public void Play(bool loop = true) { ... }
    public void Stop() { ... }
    public void Rewing() { ... }
    public float Speed { get; set; }
}
А frames и speed можно вынести в конфиг и получать к ним доступ по какому-нибудь ID. И нужно, ибо создавать красивые спрайты и правильно подбирать скорость - это задача аниматора, а не программиста.

UPDATE: Я вот думаю, а не сделать ли эффекты тоже "сущностью, которая тоже кидается на экран, но никак не рендерится, а только влияет на рендеринг"? Ну, то есть, если юзеру захотелось наложить эффект на что-нибудь, он кидает на Screen вот такое (в скобках указан Order):
[SimpleSprite(0), SimpleSprite(0), SimpleSprite(0), ForceField(1), DoorSprite(2), TearDownForceField(3), ForegroundSprite(4), ForegroundSprite(4), ForegroundSprite(4)]
UPDATE 2: Я все больше думаю, а не послать ли нахрен все эти супер-удобные API и писать в лоб, одним здоровенным методом через GL-команды.
>> No.13867 Reply
>>13829
> > фурроним
> Что это?
Это нульчановский фуррифаг-рубиёб.
>> No.13868 Reply
File: priznak_koshkosti_41.jpg
Jpg, 21.39 KB, 580×180 - Click the image to expand
edit Find source with google Find source with iqdb
priznak_koshkosti_41.jpg
Кстати, посоны, а насколько тяжело будет прикрутить к сисярпу Луа (и насколько тормознуто она будет работать)?
>> No.13869 Reply
>>13866
> UPDATE: Не катит. А если мини-окошко круглое, или основную камеру перекосило?
И что? Никто не заставляет зарисовывать всю прямоугольную область — рисуй себе там кружочек, он и будет кружочком поверх уже отрисованной сцены.

И вообще, обрисуй лучше, как должна выглядеть игра в конечном счете, а я скажу как это лучше сделать.
> Как это нет? А конфиг, в котором картинке присваивается ID для спрайта?
Вот именно, что спрайту от рендер менеджера нужно только ID картинки, в остальном они никакого отношения друг к другу не имеют.
> Так. Ты постоянно отсылаешь меня к RenderAspect, а я постоянно смотрю только его часть. Давай разберемся. RenderAspect - это что такое? Как я понял, это нечто, чем игро-объект рендерит себя - спрайт, набор спрайтов, анимация и т. д. Я правильно понял?
Да. Это что-то вроде твоего Sprite. Только я предлагаю иерархию классов на основе RenderAspect. Если надо только статичный спрайт, то он хранит ID картинки, координаты итд. Если анимация, то еще плюс счетчик.
Кстати, для составных объектов можно просто сделать отдельный RenderAspect, вызывающий отрисовку нескольких спрайтов, а не дерево CompoundSprite'ов.
> UPDATE: Я вот думаю, а не сделать ли эффекты тоже "сущностью, которая тоже кидается на экран, но никак не рендерится, а только влияет на рендеринг"?
Та епт, нельзя так сделать или очень сложно. Ты опять слишком абстрактно мыслишь. Как определять атрибуты и юниформы для каждого объекта, если этот эффект включен хз где? Проще сделать это отдельной анимацией для этого объекта и не трахать мозг.
> UPDATE 2: Я все больше думаю, а не послать ли нахрен все эти супер-удобные API и писать в лоб, одним здоровенным методом через GL-команды.
Давно бы так. Считаю свой подход оптимальным в этом плане. Рендер менеджер предоставляет методы для вывода спрайтов, а RenderAspect'ы их вызывают. Ну Screen'ы еще можно приделать.
>> No.13875 Reply
>>13866
> Не следует путать порядок отрисовки и взаимное расположение объектов.
А я и не путаю. В 2-д изометрии чтобы визуально показать расположение перекрывающихся объектов необходимо рисовать их в определенном порядке. Альфа совместно с глубиной работает криво, я уже говорил. А еще отключение глубины добавляет немного фпс.
> А в чем?
В их обработке и отрисовке. Обычно оти места просто криво сделаны.
>>13868
Настолько же, насколько сложно там импортить c-библиотеки. http://www.gamedev.net/page/resources/_/reference/programming/sweet-snippets/using-lua-with-c-r2275 здесь говорят, что еще проще.
Если вы решите приплести луа, я буду только рад, у меня в нем конфиги(с редактором) и скрипты(правда там это все безумно криво сделано и интерфейс нужно переписывать с нуля). Одной проблемой будет меньше.
>> No.13894 Reply
File: priznak_koshkosti_45.jpg
Jpg, 75.62 KB, 580×397 - Click the image to expand
edit Find source with google Find source with iqdb
priznak_koshkosti_45.jpg
>>13869
> И что? Никто не заставляет зарисовывать всю прямоугольную область — рисуй себе там кружочек, он и будет кружочком поверх уже отрисованной сцены.
Не понял, это как? Стенсилами, что ли?
> И вообще, обрисуй лучше, как должна выглядеть игра в конечном счете, а я скажу как это лучше сделать.
У меня много задумок. Одна из них - Тетрис с мясокровищей, вторая - стрелялка слева-направо с адовыми искажениями от взрывов и тряской. Еще есть два проекта, которые я буду делать, только если движок окажется архиудобным: огонек пытается выбраться из темного царства, теряя яркость об особо темные места, и Ranger II, с размытием невидимых областей и катсценами в мини-экранах. Все в 2D. Хотелось бы сделать что-то такое, чтоб потом можно было клепать все мои задумки пачками.
> Да. Это что-то вроде твоего Sprite. Только я предлагаю иерархию классов на основе RenderAspect. Если надо только статичный спрайт, то он хранит ID картинки, координаты итд. Если анимация, то еще плюс счетчик.
> Кстати, для составных объектов можно просто сделать отдельный RenderAspect, вызывающий отрисовку нескольких спрайтов, а не дерево CompoundSprite'ов.
Это вот я и собираюсь сделать, но RenderAspect получается каким-то пустоватым. Слишком уж разнятся его потомки.
>>13875
Я Луа зачем хочу: чтобы можно было логику писать сплошным текстом (move_to 10, 20, 4/1; move_to 20, 20, 4/1; move_to 10, 10, 4/1), не прерываясь на Coroutine.Pass() или на мой изврат с yield return. Оно получится так сделать?
c:хотет умной
>> No.13895 Reply
>>13894
> priznakkoshkosti45.jpg
Адская улыбка.
>> No.13909 Reply
>>13894
> получится так сделать
С точки зрения приложения, придется писать коротуны для луа, но это не особо проблема. С точки зрения луа, нужно эти коротуны останавливать. Т.е. удобство лишь в языке, да легкости работы с конфигами. Может есть и другой способ, но я пока до этого не дошел.
Да, конфиги тогда тоже лучше хранить в луе, дабы не плодить лишние сущности, да и работать напрямую будет удобнее.
>> No.13925 Reply
>>13894
> Не понял, это как? Стенсилами, что ли?
Что нарисуешь, то и будет поверх уже отрисованной сцены. Или ты имеешь ввиду, что бы отрисованное само отсекалось кругом/перекошенным прямоугольником? Такое просто средствами GL вряд ли сделать и я бы забил.
> У меня много задумок.
Остановись на чем-то одном или хотя бы однотипном.
> Тетрис
и
> стрелялка слева-направо с адовыми искажениями от взрывов и тряской.
наверняка потребуют разных подходов. Давай второе.
>> No.13953 Reply
File: priznak_koshkosti...
Jpg, 23.27 KB, 580×180
edit Find source with google Find source with iqdb
priznak_koshkosti_46.jpg
File: JBG02dkxqwb8z.jpg
Jpg, 31.52 KB, 450×600
edit Find source with google Find source with iqdb
JBG02dkxqwb8z.jpg

>>13909
> Т.е. удобство лишь в языке
Nah, тогда сисярпа хватит, я бэтмен.
>>13925
> Или ты имеешь ввиду, что бы отрисованное само отсекалось кругом/перекошенным прямоугольником?
Да. И забивать я не стану. Я программист, блядь, или кто?
> Остановись на чем-то одном или хотя бы однотипном.
Ну, реализовывать-то всё придется. Так что не исключено, что понадобится написать аж два движка. Но сначала надо сделать хотя бы стрелялку с температурными искажениями от взрывов и тряской. Чтобы вообще научиться игры делать.

А сейчас продолжаем. Давайте окончательно решим, как мы будем накладывать эффекты, а то у нас небольшие разногласия по этому поводу. В смысле, технически.
UPDATE: Только-только все написал и вдруг в голову пришла гениальная идея, навеянная одной статьей, прочитанной вчера мной: рендерим всю сцену в один проход в специальную текстуру (или несколько текстур), в которой помимо каналов R, G, B и A есть еще специальные каналы для шейдеров (например, XWARPVECTOR, YWARPVECTOR, ZWARPVECTOR, TEMPERATURE, STEPEN_BYDLYATSTVA и многие другие), потом рендерим эту текстуру через шейдер, который учитывает все эти каналы и должным образом искажает картинку. Но пофигу, пусть будет еще и список ниже. Не зря же я писал его, в конце концов?
0) Используем только шейдеры. Фиксированную функциональность (цвета текстур, градиент, полупрозрачность) рассматриваем как шейдеры, вшитые в видяху. Если шейдеры фиксированной функциональности чего-то не могут, пишем свои.
1) Эффекты на объектах, не зависящие от окружения (мигание цветами, электрошок): активируем шейдер эффекта, рендерим напрямую на экран.
2) Эффекты на объектах, зависящие от окружения (температурные искажения, горячая лава): рендерим всю сцену в текстуру S, потом активируем шейдер эффекта, который принимает на вход текстуру S и текстуру со спрайтом объекта, и рендерим это все на экран.
3) Полноэкранные эффекты (эффекты сломанного телевизора): активируем шейдер и рендерим все объекты напрямую на экран.
4) Полноэкранные эффекты в сочетании с эффектами на объектах (сломанный телевизор показывает сцену с электрошокированным объектом): рендерим сцену в текстуру T (при этом рендеря заэффекченный объект методом 1 или 2), потом активируем шейдер полноэкранного эффекта и рендерим текстуру T на экран.
5) Полупрозрачность и 3D:
5a) Сортируем все объекты по Z и рендерим от самого дальнего к самому ближнему.
5б) Предложение: Рендерим обычные объекты с использованием z-буфера в произвольном порядке, потом рендерим полупрозрачные объекты через пиксельный шейдер, занимающийся смешиванием. Формулы для пикселей, наверно, будут такие: zитоговое = z{ближайшего непрозрачного объекта} (то есть, z{прозрачного объекта} игнорируется); rgbитоговое = смешать(1, rgb{ближайшего непрозрачного объекта}, a{прозрачного объекта}, rgb_{прозрачного объекта}).

Я все правильно сделал?
>> No.13954 Reply
>>13953
Остальное - какое-то безумство, оставлю без комментариев.
> 5) Полупрозрачность и 3D:
> 5a) Сортируем все объекты по Z и рендерим от самого дальнего к самому ближнему.
Как-то так и приходится.
> 5б) Рендерим обычные объекты с использованием z-буфера в произвольном порядке, потом рендерим полупрозрачные объекты через пиксельный шейдер, занимающийся смешиванием.
Что такое обычный объект? Ты предлагаешь разграничить картинки по по использованию альфы и держать два вида картинок?
А рендерить через шейдер, мне кажется, будет медленней.
>> No.13971 Reply
>>13953
> Ну, реализовывать-то всё придется.
Многое может оказаться взаимоисключающим. И было бы неплохо разграничить, что нужно для текущей игры, а что просто тестим.
> рендерим всю сцену в один проход в специальную текстуру (или несколько текстур), в которой помимо каналов R, G, B и A есть еще специальные каналы
Конечный результат работы шейдеров: пиксель с цветом(R,G,B,A) + Z + параметр из стенсил буфера(с этим хз как работать), больше ты в текстуру ничего не запихнешь. И то, для кадого из этих параметров(цвет, глубина, трафарет) нужна отдельная текстура.
> 1) Эффекты на объектах, не зависящие от окружения (мигание цветами, электрошок): активируем шейдер эффекта, рендерим напрямую на экран.
Мигание можно и цветом сделать. Электрошок предварительно срендерить в картинку и использовать как анимацию(несколько картинок). Такие шейдеры сразу нафиг.
> 4)
Короче так:
1. биндиться Фреймбуфер с текстурой Т1
2. рендерятся объекты без шейдеров
3. анбинд фреймбуфера
4. бинд фреймбуфера с текстурой Т2
5. отрисовка Т1
6. поверх рисуются эфекты из твоего "2)" (кстати так они друг на друга влиять не будут)
7. анбинд фреймбуфера
8. отрисовка Т2 на экран.

Можно предусмотреть, что если нет "локальных" эффектов, то пункты 1,3 не выполняются, а 2 выполняется вместо 5. Соответственно для случаев, когда нет полноэкранных, но есть локальные итд.
> 5) Полупрозрачность и 3D:
5a) и точка.
>> No.14017 Reply
File: priznak_koshkosti...
Jpg, 40.02 KB, 580×180
edit Find source with google Find source with iqdb
priznak_koshkosti_47.jpg
File: JBGhv4b6qn8sf.jpg
Jpg, 41.64 KB, 600×450
edit Find source with google Find source with iqdb
JBGhv4b6qn8sf.jpg

>>13971
> > рендерим всю сцену в один проход в специальную текстуру (или несколько текстур), в которой помимо каналов R, G, B и A есть еще специальные каналы
Ну, то есть, рендерить может понадобиться не только из нескольких сорцов (атласов), но и в несколько таргетов. Например, у куска лавы может оказаться один атлас, в котором лежит его видимое представление и его карта температурных искажений, а рендериться он может в два прохода: сначала в текстуру видимого представления, потом в текстуру температурных искажений.
> Мигание можно и цветом сделать.
Это шейдер фиксированной функциональности. Я ведь могу эквивалентный шейдер написать, да? И если я выставлю какой-нибудь свой шейдер, закраска цветом работать уже не будет, правильно?
> 5а) и точка.
Ну, ладно, в изометрии это, может, и прокатит. Но давайте немного отвлечемся от основной темы (клепания 2D-игр). Как в полноценном 3D такое сделать? Предположим, у меня есть 3 летающие сферы, две из которых полупрозрачны. Как мне их рендерить?

А тем временем я продолжаю фонтанировать идеями.

Сегодня я посылаю retained mode нах. Главным образом из-за того, что удалять объекты со сцены тяжело (мои мысленные эксперименты показывают, что удалять объекты явно - это неудобно, что удобнее удалять их, когда игровой объект "больше не хочет" рендерить данный объект сцены). И отчасти потому, что накладывание эффектов становится каким-то хитрым и непонятным.

Сегодняшний тренд - одна большая функция Render() (или вообще хэндлер события GameWindow.OnRender) с возможно вынесенными повторяющимися кусками в отдельные функции и, может быть, даже классы. И парочкой военных хитростей.

Разберем конкретный пример. Galaxians. Имеем 100 врагов разного калибра, пули и корабль игрока. HUD-а нет. В модуле логики вся игра будет представлена синглетоном GameWorld-ом, в который запиханы враги, пули и корабль. И GameWorld на каждый GameWindow.OnUpdate пробегает по всем добавленным в него объектом, вызывая метод Exist() ("существуй!"). Ну или что-то в этом роде. Все просто.

Модуль рендеринга состоит из одной функции Render(), которая вызывается каждый кадр и рендерит GameWorld:
public static void Render()
{
    foreach (var obj in GameWorld.Instance.Objects)
    {
        if (obj is Player)
        {
            GL.BindTexture(ResourceManager.Instance.GetAtlasID("Player"));
            GL.Begin(BeginMode.QUADS);   // Сорри, если тут бред, я немного подзабыл команды просто.
            GL.Vertex(obj.X, obj.Y);
            GL.Texel(ResourceManager.Instance.GetTextureCoords("Player").X, ....Y);
            GL.Vertex(obj.X + ...Width, obj.Y);
            GL.Texel(ResourceManager.Instance.GetTextureCoords("Player").X + ...Width, ....Y);
            ... // Ну и так далее.
            GL.End();
        }
        else if (obj is PawnEnemy)
        {
            ... // Аналогично.
        }
        else if (obj is KingEnemy)
        {
            ... // Аналогично.
        }
    }
}
Выглядит как-то не очень. Предположим, что в C# есть динамическая перегрузка (то есть, если я определю две функции: f(Object) и f(MyObject), а потом сделаю f(new Object(); f(new MyObject), то C# совершенно корректно сначала вызовет f(Object), потом f(MyObject)). Выносим рендеринг объектов конкретных классов в функции:
public static void Render()
{
    foreach (var obj in GameWorld.Instance.Objects)
    {
        Render(obj);
    }
}
private static void Render(Player obj)
{
    GL.BindTexture(ResourceManager.Instance.GetAtlasID("Player"));
    GL.Begin(BeginMode.QUADS);   // Сорри, если тут бред, я немного подзабыл команды просто.
    GL.Vertex(obj.X, obj.Y);
    GL.Texel(ResourceManager.Instance.GetTextureCoords("Player").X, ....Y);
    GL.Vertex(obj.X + ...Width, obj.Y);
    GL.Texel(ResourceManager.Instance.GetTextureCoords("Player").X + ...Width, ....Y);
    ... // Ну и так далее.
    GL.End();
 }
 private static void Render(PawnEnemy obj)
 {
     ... // Аналогично.
 }
 private static void Render(KingEnemy obj)
 {
     ... // Аналогично.
 }
Неплохо. Только вот в C# нет динамической перегрузки. Ну и пофигу, сымитируем её:
public static void Render()
{
    foreach (var obj in GameWorld.Instance.Objects)
    {
        obj.Render();
    }
}
interface IRenderable
{
    void Render();
}
parial class Player : IRenderable   // В синтаксисе мог немного ошибиться.
{
    public override void Render()
    {
        GL.BindTexture(ResourceManager.Instance.GetAtlasID("Player"));
        GL.Begin(BeginMode.QUADS);   // Сорри, если тут бред, я немного подзабыл команды просто.
        GL.Vertex(obj.X, obj.Y);
        GL.Texel(ResourceManager.Instance.GetTextureCoords("Player").X, ....Y);
        GL.Vertex(obj.X + ...Width, obj.Y);
        GL.Texel(ResourceManager.Instance.GetTextureCoords("Player").X + ...Width, ....Y);
        ... // Ну и так далее.
       GL.End();
    }
 }
 partial class PawnEnemy : IRenderable
 {
     public override void Render()
     {
         ... // Аналогично.
     }
 }
 partial class KingEnemy
 {
     public override void Render()
     {
         ... // Аналогично.
     }
 }
Все, игра готова. Имеем аж целых 2 кадра в секунду. А чтоб было не 2 кадра, а 200, мы немного расширим OpenGL:
class GL
{
    public static void ClearBatch();
    public static void AddToBatch(int AtlasID, Matrix3x4 PositionsInAtlas, Matrix3x4 PositionsInScreen);
    ... // А также куча перегрузок для AddToBatch();
    public static void FlushBatch();
}
И в функциях Player.Render(), PawnEnemy.Render() и пр. будем пользоваться этими функциями расширения...

Ой, в C# же нельзя расширять не-partial классы. Ну, не проблема:
class GLAD  // Переводится как GL ADdendum.
{
    public static void ClearBatch();
    public static void AddToBatch(int AtlasID, Matrix3x4 PositionsInAtlas, Matrix3x4 PositionsInScreen);
    ... // А также куча перегрузок для AddToBatch();
    public static void FlushBatch();
}
Можно добавить еще немного полезных функций (OpenGL потому и Open, что его можно расширять; вот так я это понимаю, лол):
class GLAD
{
    public static void PushAndClearBatch();
    public static void PopBatch();
}
...и много других.

Всё. Имеем недоклон Galaxians, работающий на 200 FPS.

Плюсы такого подхода:
- Максимум гибкости. Если мне не нравится рендерить все объекты в одном цикле, я могу написать вот так:
public void Render()
{
    ...
    foreach (obj in GameWorld.Objects.Select(obj => obj.SomeCondition())
    {
        obj.Render();
    }
    foreach (obj in GameWorld.Objects.Select(obj => !obj.SomeCondition())
    {
        obj.Render();
    }
    ...
}
- Максимум расцепления. Если рассматривать только исходный код, то в модуле логики вообще отсутствуют даже намеки на рендеринг.
- Максимум скорости. лол
- Еще можно делать так:
class Animation : IRenderable
{
    public void Play() { ... }
    public void Stop() { ... }
    public void Rewind() { ... }
    public override void Render() { ... }
}
partial class Fireball : IRenderable
{
    private Animation anim = new Animation("Fireball");
    public override void Render()
    {
        anim.Render();
    }
}
Я не успел еще разобрать эффекты, но там все тривиально получается, потому что ad-hoc-но.

UPDATE: Пришла в голову идея оставить-таки retained mode, но собранную сцену не держать постоянно в памяти, а пересобирать каждый кадр. Это позволит удалять объекты сцены неявно. Но эту мысль надо прорабатывать. Пока это только идея.
>> No.14021 Reply
>>14017
> GameWindow.OnUpdate пробегает по всем добавленным в него объектом
Это должен делать объект-манагер.
Да, ты делаешь это неправильно. Зачем ты напихал гл'а во все подряд? У рендерманагера есть две штуки: 1. загруженные спрайты в виде обыкновенного списка. 2. функция render, которая идет по этому списку и рисует все по порядку. Сортируются спрайты в рендер-списке рендер-манагером. Объекты хранят ссылки на спрайты, а не сами спрайты. Где-то какая-то неувязка, но я ее не нашел, а это наиболее логичное решение, которое я вижу. Если обнаружите проблему, ткните пальцем.
>> No.14031 Reply
Да, забыл сказать. Я считаю, что:
1) Прозрачность - это частный случай эффекта. А потому прозрачные объекты
должны рендериться через шейдер (будь то самописный или являющийся частью
фиксированной функциональности).
2) Изометрия - это частный случай полноценного 3D.

Посему, >>13954,
> Ты предлагаешь разграничить
...спрайты по использованию эффектов/альфы и держать два вида спрайтов: с
эффектами/альфой и без них.
> А рендерить через шейдер, мне кажется, будет медленней.
Да. Немного. Смеситель из фиксированной функциональности, ЕМНИП, тупо
перемножает и складывает цветовые компоненты и альфы. В шейдере же будет еще
учет z-буфера. Но! Взамен ты получаешь возможность рендерить почти всю сцену
одним батчем, без сортировки по z.

Еще пара хинтов к текущему тренду:
- Динамически перегруженный метод - это не обязательно GameObject.Render(). Это может быть что угодно, в том числе и GameObject.Order.
- Внутри Render() можно сортировать объекты как угодно, можно рендерить по два раза в разные места - в общем, полная свобода действий.

Потом отвечу на остальное.
>> No.14032 Reply
>>14031
> Прозрачность - это частный случай эффекта
Не совсем, прозрачность идет прямо из картинок и эффективнее ее там же и обрабатывать.
> Изометрия - это частный случай полноценного 3D.
Тоже нет, скорее 2д на костылях.
> рендерить почти всю сцену одним батчем, без сортировки по z
Только это будет медленней, чем отсортировать. Серьезная сортировка получается первый раз, в остальные - это просто небольшие перестановки и делаются в один проход.
>> No.14044 Reply
>>14017
> Ну, то есть, рендерить может понадобиться не только из нескольких сорцов (атласов), но и в несколько таргетов.
То есть, к одному пикселю больше шести флоатов не привяжешь. Из них 4 — цвет. Конечно, оставшиеся 2 можно использовать не по назначению, но это такие костыли, что даже костыли.
> > Мигание можно и цветом сделать.
> Это шейдер фиксированной функциональности.
Не суть важно. Просто если этим можно управлять через альфу, то зачем какие-то левые параметры. Ну сделаю шейдер, аналогичный конвейеру фиксированных функций, все равно передавать дополнительные параметры — бред.
> Но давайте немного отвлечемся от основной темы (клепания 2D-игр). Как в полноценном 3D такое сделать? Предположим, у меня есть 3 летающие сферы, две из которых полупрозрачны. Как мне их рендерить?
Ну там однозначно не через альфу делается. Короче это не наш случай.
> Ой, в C# же нельзя расширять не-partial классы.
Можно, только не статические и с доступом только к паблик-членам.
И все, что ты собрался нарсаширять, относится не к GL, а менеджеру.

Вот >>14021 правильно пишет. Только надо еще учитывать, что надо собирать VBO, а не просто рендерить.
Кстати, а если объект состоит из нескольких спрайтов? Держать несколько отдельных спрайтов или один рендерАспект, вызывающий отрисовку нескольких спрайтов?
> > А рендерить через шейдер, мне кажется, будет медленней.
> Да. Немного.
Нет. В пределах погрешности измерения.
> В шейдере же будет еще учет z-буфера. Но! Взамен ты получаешь возможность рендерить почти всю сцену одним батчем, без сортировки по z.
Проблема одновременного использования глубины и альфы — это не столько косяк разработчиков, сколько особенность работы конвейера. Просто альфа и тест глубины это обновление состояния уже нарисованного пикселя текущим пикселем, без знания о последующих или предыдущих. С шейдером или без у тебя будут те же проблемы. Про z-буфер можешь забыть однозначно.
>> No.14057 Reply
File: JBGcb4zs6wfng.jpg
Jpg, 33.94 KB, 600×450
edit Find source with google Find source with iqdb
JBGcb4zs6wfng.jpg
File: priznak_koshkosti...
Jpg, 23.60 KB, 600×200
edit Find source with google Find source with iqdb
priznak_koshkosti_48.jpg

>>14021
> Это должен делать объект-манагер.
...или GameWorld.
> У рендерманагера
Да вот я думаю послать в лес рендерманагер. Так, голым GL все хреначить. С расширениями.
> Неувязочка в рендерманагере
А удалять спрайты из него как?

>>14032
> Не совсем, прозрачность идет прямо из картинок и эффективнее ее там же и обрабатывать.
Это частный случай эффекта, в который передается текстура с R, G, B и A. Так правильно?

<оффтоп>
> Изометрия - это скорее 2д на костылях.
Ключевое словосочетание - "на костылях". У меня предчувствие (только предчувствие), что если решить возникшие проблемы для полноценного 3D, то для изометрии они отпадут сами собой.
</оффтоп>
> > рендерить почти всю сцену одним батчем, без сортировки по z
> Только это будет медленней, чем отсортировать.
Да ты охуел! Как же это медленней, если в первом случае ты хреначишь по батчу на каждый z, а во-втором все посылаешь одним батчем (в обоих случаях без сортировки)?

>>14044
> Конечно, оставшиеся 2 можно использовать не по назначению
Ты будешь смеяться, но так обычно и делают. Те же пресловутые температурные искажения, например. Байтосодомия же.
> Просто если этим можно управлять через альфу, то зачем какие-то левые параметры. Ну сделаю шейдер, аналогичный конвейеру фиксированных функций, все равно передавать дополнительные параметры — бред.
Я не говорил, что обязательно надо свой шейдер писать. Я говорил, что фиксированную функциональность можно рассматривать как шейдер. В частности, она, как и любой шейдер, слетает, если ты активируешь другой шейдер. Слетает ведь? Это поможет нам безболезненно встроить ее в наш фреймворк эффектов.
> Кстати, а если объект состоит из нескольких спрайтов? Держать несколько отдельных спрайтов или один рендерАспект, вызывающий отрисовку нескольких спрайтов?
В твоем случае будет один рендер-аспект, вызывающий отрисовку нескольких спрайтов. В моем случае функция BigGameObject.Render() будет вызывать отрисовку нескольких спрайтов. Как держать несколько отдельных спрайтов и при этом не нарушить MVC, я не знаю.

<оффтоп>
> Проблема одновременного использования глубины и альфы
Падажжи ёбана. Смотри, имеем два пикселя (A=0 - полная прозрачность):
Z=0,R=10,A=0.5   Z=1,R=50,A=0.1
Цвет результирующего пикселя же не изменится, если я переставлю их места...
Изменится. Фейл. Смешивание и сокрытие невидимых поверхностей делается не через z-буфер. Оффтоп закрыт.
</оффтоп>

Алсо, настало время задуматься о звуке. Расскажите мне, пожалуйста, о подводных камнях в OpenAL.
>> No.14060 Reply
Может, с http://gamedev.ru кого-нибудь привлечь? Стоит?
>> No.14068 Reply
>>14057
> ты хреначишь по батчу на каждый z, а во-втором все посылаешь одним батчем
Нет, не хреначу, я просто один раз их сортирую с учетом z.
> настало время задуматься о звуке
Нет, не настало. О звуке нужно задумываться после того, как у тебя готова графика и скриптовый движок. В идеальной игре звук пускается из скриптов и больше никак не связан с движком.
>>14060
Но зачем? Ты не веришь в себя? Или не хочешь писать код? За тебя просто так писать все равно никто не будет. Опытные товарищи все равно уже при делах, а школьники не сильно нужны.
>> No.14090 Reply
File: priznak_koshkosti...
Jpg, 24.75 KB, 600×200
edit Find source with google Find source with iqdb
priznak_koshkosti_49.jpg
File: JBGbsp9rzn26t.jpg
Jpg, 21.03 KB, 382×438
edit Find source with google Find source with iqdb
JBGbsp9rzn26t.jpg

>>14068
> Нет, не хреначу, я просто один раз их сортирую с учетом z.
А, сортируешь, а потом все в один батч? Ну, тоже вариант... Стоп, так это ж finger-tree получается! Ну, понял, в общем.
> В идеальной игре звук пускается из скриптов и больше никак не связан с движком.
Ты няша. Расскажи мне побольше об этом. Меня главным образом интересует проблема, как останавливать звук, когда объект, издающий этот звук, исчезает. Ну, например, босс во время битвы с ним всяко материт игрока, а когда умирает, его крики прекращаются. Как это правильно сделать? Тупо писать в скрипте insults_sound.stop()?
> За тебя просто так писать все равно никто не будет.
Я не говорил, что просто так.
> школьники не сильно нужны.
А вот с этим не соглашусь. Мне ведь в первую очередь нужны рабочие руки. Мозги-то у меня есть, а вот рук всего две. К тому же, как показала моя практика, при правильной постановке задачи (читай: максимально строгой) и должном контроле высираемый школьниками код оказывается вполне юзабельный.
> Ты не веришь в себя?
Я тут наткнулся на http://wiki.gamedev.net/index.php/Lone_developer и подумал: а может, и правда стать эдаким one-man army? Это же в случае успеха можно охренительно ЧСВ повысить.
>> No.14091 Reply
Я тут придумал костыльную идею: добавить в класс Sound поле AutoStop, и если при очередном проходе никто не сказал Sound.DontStop(), то звук затыкается.
>> No.14098 Reply
>>14091
Не сильно хорошо, будет мешаться и вылезет боком в виде очень неочевидных и труднообнаружимых ошибок. Лучше повесить дефолтный таймер на звук.
А умирающие объекты просто вызывают в скрипте, в деструкторе, что-нибдудь вроде sound.play('fuck', 5). (5 - время, например, не количество раз).
>> No.14104 Reply
>>14098
Ты неправильно понял. Проблема не в том, чтобы запустить звук взрыва, когда объект исчезает, а наоборот, прекратить все звуки, которые он издавал. Например, босс вылетел и заревел в лупе моторами. И ревет, и ревет, и вдруг игрок его прихлопывает. Звуки моторов должны немедленно прекратиться.
>> No.14106 Reply
>>14104
Что мешает использовать soundmanager, у которого будет метод stop(soundid)?
>> No.14126 Reply
File: priznak_koshkosti_50.jpg
Jpg, 30.46 KB, 600×221 - Click the image to expand
edit Find source with google Find source with iqdb
priznak_koshkosti_50.jpg
>>14106
Это то же самое, что и some_sound.stop(). Проблема в том, что этот самый stop() должен кто-то вызывать. Если реализовывать объект-менеджер так, как я задумал, то у объекта будет вызываться метод Exist() при каждом проходе, а когда объект удалят, этот метод просто перестанет вызываться. И он так и останется с запущенными звуками, выделенными текстурами и еще чем-нибудь неза-Dispose()-енным. А метод OnRemove() или тем паче событие OnRemove я ему прикручивать не хочу.
>> No.14128 Reply
>>14126
Твой язык не может в деструкторы?
> метод Exist()
Это не метод, это переменная/флаг. Если ты туда что-то пихаешь на исполнение, то у тебя кривая архитектура.
>> No.14129 Reply
File: priznak_koshkosti_51.jpg
Jpg, 48.99 KB, 600×221 - Click the image to expand
edit Find source with google Find source with iqdb
priznak_koshkosti_51.jpg
>>14128
> Твой язык не может в деструкторы?
Цитирую к-к по памяти:
1. Деструкторы не использовать...
> > метод Exist()
> Это не метод, это переменная/флаг. Если ты туда что-то пихаешь на исполнение, то у тебя кривая архитектура.
А флагом у меня будет переменная IsExisting. О, а можно и правда сделать void Exist(), который будет выставлять IsExisting в false... Но это уже детали. Да, у меня есть переменная IsExisting.
>> No.14130 Reply
>>14129
> Деструкторы не использовать
Но почему? Ты думаешь их для красоты придумали?
>> No.14132 Reply
>>14129
В чем собственно проблема? Перед вызовом Exist() проверяется IsExisting. Если оно = false, то вызывается Dispose() для объекта, который вызывает Dispose() у принадлежащих ему объектов(рендерОбъектов, спрайтов, тех же звуков), и этот Dispose() останавливает звуки, освобождает если надо текстуры итд.
> Деструкторы
В языках со сборкой мусора деструкторы не совсем тоже самое, что в языках без неё. В данном случае точно не до них.
>> No.14136 Reply
File: priznak_koshkosti_52.jpg
Jpg, 20.95 KB, 600×223 - Click the image to expand
edit Find source with google Find source with iqdb
priznak_koshkosti_52.jpg
>>14130
>>14132
Проблема в том, что Dispose() принадлежащим объектам надо писать. А если я собрался упростить написание логики до упора, то все эти объекты будут локальными переменными, и Dispose() становится вообще невозможно написать. Но проблема решаема: можно синхронизировать эти подчиненные объекты с объектом, их породившим, можно в каждом объекте создать пул ресурсов, которые диспоузятся при его исчезновении, можно...

Ладно, в общем, это уже детали. Мой мозг придумает что-нибудь. Пора переходить к кодингу. Правда, не сейчас, у меня тут ремонт.
>> No.14137 Reply
Что вы придумали с биндингами и управлением? Я сейчас задумался над идеальной системой биндинга кнопок и обработки нажатий в скриптовом движке. Получается как-то коряво, с вызовами нативных методов через прослойку скриптового движка. С другой стороны, если делать наоборот, то получаются костыли на костылях, без динамики и кривой вызов методов скриптов.
>> No.14141 Reply
>>14136
> все эти объекты будут локальными переменными
В смысле "локальными"?
> Пора переходить к кодингу. Правда, не сейчас, у меня тут ремонт.
Напиши сорт оф спецификации или диаграммы классов для всего, что касается графической части, а то я теряюсь в потоке идей, и я пойду кодить потихоньку.
>> No.14191 Reply
File: 1286475032950.jpg
Jpg, 56.09 KB, 389×600
edit Find source with google Find source with iqdb
1286475032950.jpg
File: priznak_koshkosti...
Jpg, 43.97 KB, 600×223
edit Find source with google Find source with iqdb
priznak_koshkosti_53.jpg

>>14137
Ничего не придумали. Вопрос пока открытый.
>>14141
> > все эти объекты будут локальными переменными
> В смысле "локальными"?
public IEnumerator ReaperLogic()
{
    ...
    this.X = 800;
    this.Y = 200;
    // Отправляемся налево, чтобы ебнуть косой!
    var sound = new Sound("Жнец летит.wav");
    sound.Play();
    while (MoveTo(100, 200, 50/1)) yield return null;  // Это типа двигаемся.
    sound.Stop();
    // Ебошим!
    sound = new Sound("Жнец ебошит.wav");
    sound.Play();
    ...  // Тут еще анимация, все дела...
    // Отходим на исходную позицию.
    sound = new Sound("Жнец летит.wav");
    sound.Play();
    while (MoveTo(800, 200, 25/1))  // И вот где-нибудь посредине
        yield return null;          // этого цикла жнец сдыхает.
    sound.Stop();    // Кто тогда вот это будет выполнять?
    ...
}
> спецификация
Да там и писать почти нечего. ResourceManager да расширения для OpenGL (самое главное расширение - это работа с вертексо-тексельными батчами). Но спецификацию все равно предоставлю.
>> No.14212 Reply
>>14191

В таких случаях в гейдеве используют ёбнутую эвентную модель вроде, как при программировании окошек - всякие там там онмаузховер, онклик, онзалупадайс и.т.д.
>> No.14214 Reply
File: priznak_koshkosti...
Jpg, 46.37 KB, 600×223
edit Find source with google Find source with iqdb
priznak_koshkosti_54.jpg
File: 1312993671772.jpg
Jpg, 1440.63 KB, 2048×3072
edit Find source with google Find source with iqdb
1312993671772.jpg

>>14212
Ты про управление или про глушение звуков? Если про управление, то:
- Чем плоха эвентная модель?
- Если я хоть что-нибудь в геймдеве понимаю, то работа с контроллерами - это вроде как одна из процедур основного лупа:
   - Exist();
   - Draw();
   - ReadControllers();
И еще я бы хотел сделать уровень абстракции над контроллерами, который бы переводил сигналы от них во всякие игро-ориентированные действия, как-то: left, right, jump, fire и т. д. Потому, что контроллеры могут перебиндиваться. И я не допущу в своих играх отсутствие опции "define keys", потому что общепринятое управление (стрелки или WSAD) сосет у божественного QAOP.
>> No.14222 Reply
>>14214
> уровень абстракции над контроллерами, который бы переводил сигналы от них во всякие игро-ориентированные действия, как-то: left, right, jump, fire и т. д. Потому, что контроллеры могут перебиндиваться.
Вот именно это я и имел в виду в >>14137. Одни костыли получаются.
>> No.14286 Reply
File: 309756904_huge.jpg
Jpg, 32.06 KB, 300×450
edit Find source with google Find source with iqdb
309756904_huge.jpg
File: priznak_koshkosti...
Jpg, 27.34 KB, 600×223
edit Find source with google Find source with iqdb
priznak_koshkosti_55.jpg

>>14222
Ну, а почему бы не сделать в основном лупе так:
if (IsControllerSending(Binding.RightKey)) Player.Force(1, 0);
if (IsControllerSending(Binding.LeftKey)) Player.Force(-1, 0);
где Binding - это биндинги, введенные пользователем, а IsControllerSending() проверяет разом все контроллеры?

По поводу структуры проектов. У нас будет один общий проект "Dobrochan Game Utils" (или как вы назовете), и будет множество других проектов-игр, зависящих от "Dobrochan Game Utils". Да, какую систему контроля версий будем использовать?

Об IDE. Тащемта, используйте, что хотите, но скрипты сборки будут обязательно. Они будут выпускать готовый дистрибутив, со всеми оптимизациями и сжатиями. Кстати, а как правильно прописывать зависимости от OpenTK? Не пихать же его в папку проекта, право слово. %%Извиняюсь, если вопрос нубский, просто я никак не могу привыкнуть к правильному и удобному best practices .NET-а.%%

Сегодня прочитал, что сборка атласов - это, оказывается, NP-полная задача. Хотя я об этом догадывался. Так что папка "Resources" в исходниках и папка "Resources" дистрибутива будут отличаться. В дистрибутивной "Resources" будут лежать уже собранные атласы, и в конфигах к ним все до единой координаты будут указаны явно. Плюс там будут находиться сведенные проекты Audacity и Adobe Audition и, если надо, сжатые в MP3 и OGG (кому что больше нравится). Простоту можно не копировать, можно будет хард-линки на нее делать. Само собой, уже собранные атласы и сведенные проекты пересобираться и пересводиться не будут. Таймстампы же.

По поводу Dobrochan Game Utils. Я все никак не собирусь и не выложу спеку. Попробую выложить сейчас хоть что-то.

Итак, нам понадобится класс GLAD:
  
static class GLAD
{
    public static void NewBatch() { ... }
    public static void AddToBatch(...) { ... }
    public static void DrawBatch() { ... }
}
Главная проблема будет в AddToBatch() - я хочу, чтобы он принимал выхлоп ресурс-менеджера напрямую (я хочу исключить зависимость GLAD от класса ResourceManager, плюс юзер может захотеть нарисовать полосу здоровья, используя лишь часть текстуры, предоставляемой менеджером; или вообще свою собственную текстуру). Короче, надо подумать над списками аргументов перегруженных AddToBatch()-ей. И названия мне не нравятся.

Еще можно добавить:
static class GLAD
{
    public static void PushBatch() { ... }
    public static void PopBatch() { ... }
}
Но это уже желательная фича, не обязательная.

Класс ResourceManager будет работать напрямую с GL и будет требовать, чтобы OpenGL был проинициализирован. Как он будет выглядеть, я еще не придумал.

Еще понадобится класс Sound с Dispose(), заалиасенным на Stop(), и его наследник LongSound (для проигрывания музыки). Да, надо будет достать читалку MP3 и OGG для сярпа.

Потом нужен будет класс Shader. Ну, тут понятно.

Ну и пара классов для логики:
class GameWorld
{
    public void Add(GameObject obj) { ... }
    public bool Exist() { ... }
    public bool IsExisting { get; }  // Не обязательно, наверно.
}
class GameObject
{
    public bool Exist() { ... }    // Если это...
    public bool IsExisting { get; }    // ... или это вернет false, то объект удаляется из GameWorld-а.
        // А во внутренностях Exist() юзер может и елды применить, и корутины, и все, что хочет.
}
Вот, тащемта, и весь "движок".

Кстати, я тут подумываю над интерполяцией анимации. Это же будет выглядеть офигенно круто. Но пока никакого более-менее быстрого алгоритма, кроме как наплодить тысячу промежуточных спрайтов, мне в голову не приходит. Может, как-то можно шейдорами сделать?
>> No.14287 Reply
> соберусь
же.
>> No.14288 Reply
>>14286

motion blur же. Ну и другие постпроцессинговые техники.
>> No.14293 Reply
File: priznak_koshkosti_56.jpg
Jpg, 44.65 KB, 600×214 - Click the image to expand
edit Find source with google Find source with iqdb
priznak_koshkosti_56.jpg
>>14288
Не катит. Для мелких изменений это еще нормально, а для бегущего человека с тремя заданными кадрами, скажем, это уже будет выглядет как говно.
>> No.14311 Reply
>>14286
> Binding.RightKey
А теперь опиши все клавиши, а потом еще динамически меняй функции.
> У нас будет один общий проект
Я, тащемта, делаю свою ерунду на другом языке, но это можно обозвать портированием, в принципе, потому что делаю то же самое, чуть ли не строчка в строчку в некоторых местах получится.
> систему контроля версий
Лучше гит, ну или hg, но он на любителя. Главное не svn.
> "Resources" в исходниках и папка "Resources" дистрибутива будут отличаться
Не самая удачная идея, морока с учетом этой ситуации, лучше тогда сделать поддержку как запакованной, так и распакованной версий.
> юзер может захотеть нарисовать полосу здоровья
На мой взгляд, это нужно делать в другом месте, в спрайте, например.
> ResourceManager будет работать напрямую с GL
> Resource
> GL
Обзови его по другому, ресурсманагер должен отвечать за ресурсы, т.е. конфиги, картинки и т.п. Но если ты хочешь действительно дать этому манагеру доступ к гл, у меня к тебе два вопроса:
Но зачем?
Тебе действительно нравится, когда код, занимающийся одним и тем же, размазан по всему проекту и каждый поиск занимает 20 минут?
>> No.14327 Reply
File: 11422794.jpg
Jpg, 558.75 KB, 800×800 - Click the image to expand
edit Find source with google Find source with iqdb
11422794.jpg
>>14286
> Ну, а почему бы не сделать в основном лупе так:
> if (IsControllerSending(Binding.RightKey)) Player.Force(1, 0);
Только переменная должна быть не только в условии, но и в действии, т.к. "вверх" может означать и прыжок для своего персонажа, и выбор строки в меню, и еще что-нибудь.
> В дистрибутивной "Resources" будут лежать уже собранные атласы, и в конфигах к ним все до единой координаты будут указаны явно.
Ты совершенно не понимаешь сути атласов. Они нужны, чтобы соединить в одну(или в не большое кол-во штук) текстуру все необходимые в данный момент(локация, уровень) текстуры. Не больше не меньше. А если локации отличаются только фоном и парой монстров, то делать атласы, которые отличаются лишь парой текстур для каждого лвла?
> Итак, нам понадобится класс GLAD:
Нет не понадобится. Все, что ты описываешь, должно быть частью рендерМенеджера.
> public static void NewBatch() { ... }
Какой еще батч. Что общего у спрайтов входящих в один батч? Правильно, текстура, т.е. наш атлас. У нас в простейшем случае он будет один. Если таки приделать пообъектные шейдеры, то несколько, и те собираются непосредственно в рендерМенеджере.
> public bool Exist() { ... } // Если это...
Пусть void возвращает, а перед вызовом делать проверку IsExisting.
> Кстати, я тут подумываю над интерполяцией анимации.
Алгоритм следующий:
"Нам для этого спрайта нужно не 5, а 10 кадров, при той же суммарной продолжительности анимации. Дорисуй промежуточные кадры."
Среда выполнения — "художник". Псевдокод на основе русского языка.
>> No.14355 Reply
>>14286
   Систему контроля версий, я бы на ГитХабе предложил.
>> No.14357 Reply
File: 147.jpg
Jpg, 29.38 KB, 400×600
Your censorship settings forbid this file.
r-18
File: priznak_koshkosti...
Jpg, 32.21 KB, 600×214
edit Find source with google Find source with iqdb
priznak_koshkosti_57.jpg

>>14311
> А теперь опиши все клавиши, а потом еще динамически меняй функции.
В смысле, Binding.RightKey - это переменная, и опция "DEFINE KEYS" в меню игры ее меняет. А работу с меню можно захардкодить, "if (IsControllerSending(VK.UP)) { ... }", например.
> Не самая удачная идея, морока с учетом этой ситуации, лучше тогда сделать поддержку как запакованной, так и распакованной версий.
make test - распакованная. Или вообще прям с ресурсами из исходников запускается.
make - запакованная.
Ну или через MSBuild/XBuild то же самое.
> Обзови его по другому, ресурсманагер должен отвечать за ресурсы, т.е. конфиги, картинки и т.п.
А куда он эти картинки/звуки будет грузить? Не в астрал же. Я всегда думал, что ресурс-менеджер для того и нужен, чтобы загружать картинки/звуки/прочее в видео-/звукокарту.
> Обзови его по другому, ресурсманагер должен отвечать за ресурсы, т.е. конфиги, картинки и т.п.
Он и будет отвечать за ресурсы, т.е. конфиги, картинки и т.п. Просто у него в зависимостях будут настроенные GL и AL.
>>14327
> Только переменная должна быть не только в условии, но и в действии, т.к. "вверх" может означать и прыжок для своего персонажа, и выбор строки в меню, и еще что-нибудь.
Binding.MovePlayerRight, Binding.MoveMenuCursorRight. Можно сделать много Binding-ов: для меню, для игрока, для второго игрока и т. д.
> Ты совершенно не понимаешь сути атласов...
А, вон оно как. Акей, картинки в релиз будут просто хардлинкаться. Но решать NP-полную задачу в рантайме я все равно не позволю. Даже если приемлемое неоптимальное решение требует не больше секунды. Так что в релизных конфигах будут явно прописаны положения картинок в атласах.
> Нет не понадобится. Все, что ты описываешь, должно быть частью рендерМенеджера.
Да погоди ты. Давай сначала из OpenGL-я сделаем хоть какое-то подобие графической библиотеки, а не это чмо. Потом и до рендер-менеджера доберемся.
> Какой еще батч.
Парочка перегруженных функций:
GLAD.AddToBatch(int atlasID, Vector2D topLeftPosInAtlas, Vector2D rightBottomPosInAtlas, Vector2D posInScreen, bool center = true) GLAD.AddToBatch(NameMe nameMe, Vector2D posInScreen, bool center = true),
где:
struct NameMe
{
    public int atlasID;
    public Vector2D topLeftPosInAtlas;
    public Vector2D rightBottomPosInAtlas;
    
    public NameMe(...) { ... }
}
<оффтоп>
> Интерполяция анимаций
Зачем нагружать художника, когда это может сделать машина? Плюс этот алгоритм работает на этапе сборки и засирает дистрибутив, а я бы хотел это делать на этапе выполнения (и чтоб дистрибутив не засирать).
</оффтоп>

c:оргию гром греха записи радио спросила, видимо, перепутала раздел.
>> No.14359 Reply
File: 1317664770237.png
Png, 1.13 KB, 300×20 - Click the image to expand
edit Find source with google Find source with iqdb
1317664770237.png
>>14357
> Binding.MovePlayerRight, Binding.MoveMenuCursorRight
Но сама кнопка все та же. И эти вызовы должны быть взаимоисключающими. Все равно переключение режима надо как-то сделать.
> А, вон оно как. Акей, картинки в релиз будут просто хардлинкаться.
И что изменилось по сравнению с предыдущим твоим решением?
> > Какой еще батч.
> Парочка перегруженных функций:
Ну и какой в них толк? Лишний массив, лишние операции перепаковки данных — зачем это все?
> Зачем нагружать художника, когда это может сделать машина?
Нет не может. Точнее может. Но моушен блур для спрайтовой анимации выглядит как говно, а для точной прорисовки промежуточных состояний анимации потребуется кластер с системами распознавания образов, векторизации и прочее.
>> No.14360 Reply
File: priznak_koshkosti...
Jpg, 45.95 KB, 600×214
edit Find source with google Find source with iqdb
priznak_koshkosti_58.jpg
File: Rendering aspect....
Zip, 0.01 KB, 0 files
view
Rendering aspect.odg.zip
File: Rendering aspect.png
Png, 78.66 KB, 1587×1123
edit Find source with google Find source with iqdb
Rendering aspect.png

>>14359
> Все равно переключение режима надо как-то сделать.
А, ну дак в меню режим будет один, в игре - другой. И да, по-хорошему надо бы сделать детектирование конфликтов в "define keys". Но до этого еще надо дойти.
> И что изменилось по сравнению с предыдущим твоим решением?
Если локации отличаются только фоном и парой монстров, то делать атласы, которые отличаются лишь парой текстур для каждого лвла, не надо. И при этом решать NP-полную задачу в рантайме тоже не надо.
> Ну и какой в них толк? Лишний массив, лишние операции перепаковки данных — зачем это все?
Так, падажи, ебана. Мы как рендерим множество спрайтов? Сначала собираем вершинно-тексельный массив, потом биндим нужную текстуру и делаем GL.DrawArrays(), так? Но это же пиздец, братюни, XXI век на дворе, гейм-программисты до сих пор байтоёбствуют, нахуй так жить? Ну, ладно, у видео-карт нет retained mode API (и, если честно, я не представляю, как оно должно выглядеть, чтобы при этом в нем можно было бы полноценно эффектить; поэтому я его и дропнул, кстати) - это еще можно как-то стерпеть. Но отсутствие API даже для банального пидорасения фреймбуфера ("хуйнуть круг", "хуйнуть квадрат", "хуйнуть прямоугольник с вон той текстурой") - это уже перебор.

То есть, перефразирую: давайте для начала сделаем хоть какое-то API для рисования на экран (GL.DrawSquare(...), GL.DrawCircle(...), GL.DrawRectangle(String textureFileName, Vector2D pos, ...)), а не это чмо (еботня с вертексно-тексельными буферами), а потом уже будем городить поверх него всякие рендер-менеджеры-рендер-шменеджеры (если понадобятся).
> для точной прорисовки промежуточных состояний анимации потребуется кластер с системами распознавания образов, векторизации и прочее.
Да ладно! Неужели там такой сложный алгоритм? Я ж не прошу из трех фотографий бегущего человека сделать полноценную 200-кадровую анимацию, мне хватит и обычной линейной интерполяции. Для плавного анимирования винта вертолета (вид сбоку), например. Или для сглаживания взрывов в Iji.
>> No.14361 Reply
>>14360
> то делать атласы, которые отличаются лишь парой текстур для каждого лвла, не надо. И при этом решать NP-полную задачу в рантайме тоже не надо.
Ты мне лучше скажи, что надо-то? Как в таких случаях поступать, какие атласы использовать?
> Мы как рендерим множество спрайтов? Сначала собираем вершинно-тексельный массив, потом биндим нужную текстуру и делаем GL.DrawArrays(), так? Но это же пиздец, братюни, XXI век на дворе, гейм-программисты до сих пор байтоёбствуют, нахуй так жить?
У рендер менеджера есть DrawSprite(), че тебе еще надо? Все остальное должно быть в одном месте, без всяких API. Считай, что это оно и есть.
Бля, кароч, забей на внутреннее устройство всего этого. Уже всё придумано. А то тебе лишь бы костыль воткнуть.

Алсо
> "хуйнуть круг", "хуйнуть квадрат"
Не имеет смысла в контексте видеокарты.
> "хуйнуть прямоугольник с вон той текстурой"
Может иметь овер 9000 реализаций с различными преимуществами и недостатками.

Или начинай "думать как видеокарта", или переходи на готовые движки.
> Да ладно! Неужели там такой сложный алгоритм?
А то!
> обычной линейной интерполяции.
Между какими точками интерполяция? Как эти точки соединять? Что делать, если на следующем кадре этой точки уже нет? На эти и многие другие вопросы придется не только ответить, но и написать эффективный алгоритм, работающий на обычном компьютере за приемлемое время. Как минимум векторизация понадобится точно.

Я когда себе одну штуковину делал со спрайтовой анимацией, сделал модель с анимацией в 3D Max'е и потом растягивал как мне надо по времени и рендерил по отдельности каждый кадр. Либо так, либо пусть художник рисует.
>> No.14367 Reply
File: 14002703.jpg
Jpg, 87.47 KB, 450×600
edit Find source with google Find source with iqdb
14002703.jpg
File: priznak_koshkosti...
Jpg, 37.21 KB, 600×214
edit Find source with google Find source with iqdb
priznak_koshkosti_59.jpg

>>14361
> Ты мне лучше скажи, что надо-то? Как в таких случаях поступать, какие атласы использовать?
Резюмирую: художник рисует картинки и пишет к ним конфиги, как договаривались. Во время сборки все файлы картинок просто копируются в дистрибутив. Конфиги тоже, но при этом они дополняются специальными тегами atlas:
<config for="Level 1">
    <sprite id="Player" file="Player.png" rows="1" cols="4"/>
    <sprite id="Background" file="Background.png"/>
    <atlas index="0">  <!-- index - это если на один уровень больше одного атласа нужно. -->
        <sprite id="Player" row="1" col="1" atlas-x="1200" atlas-y="0"/>
        <sprite id="Player" row="1" col="2" atlas-x="1200" atlas-y="50"/>
        <sprite id="Player" row="1" col="3" atlas-x="1200" atlas-y="100"/>
        <sprite id="Player" row="1" col="4" atlas-x="1200" atlas-y="150"/>
        <sprite id="Background" atlas-x="0" atlas-y="0"/>
    </atlas>
</config>
И во время игры при загрузке уровня менеджер ресурсов будет просто грузить спрайты в атлас по указанным в конфиге координатам.
> У рендер менеджера есть DrawSprite(), че тебе еще надо?
Вот это оно и есть. Только это должно быть частью API видеокарты, а то совсем уже, блядь, пиздец - видео-карта не может в видео. А рендер-менеджер должен заниматься вещами, специфичными для игр (или даже для конкретной игры). Кстати, а что в нем еще помимо AddSprite() и Draw() будет?
> Не имеет смысла в контексте видеокарты.
> Или начинай "думать как видеокарта", или переходи на готовые движки.
Думаю как видео-карта: "так, бля, епта, тут у нас фреймбуфер, тут у нас VBO, но если мы обновляем, то текстура биндится на... А? Что? Рендеринг? Какой рендеринг?"

Алсо,
> > "хуйнуть прямоугольник с вон той текстурой"
> Может иметь овер 9000 реализаций с различными преимуществами и недостатками.
Не понял. Мы сейчас фигачим прямоугольники с текстурами через твой перегруженный DrawSprite(), так? Какие еще могут быть способы (кроме шейдеров и заведомо тормозных вариантов)? И нужны ли нам эти способы вообще?

<оффтоп>
> Интерполяция анимации
Хм. Акей. Но все равно меня терзают смутные сомнения. Я же видел, как быстро работает Ulead Morph Studio $199 Skachat Besplatno. И морфинг получался вполне правдоподобный. Специально погуглил "анимация по ключевым кадрам", "tweening", "keyframing" и прочее, но ничего толкового не нашел.
</оффтоп>
>> No.14370 Reply
>>14367
> И во время игры при загрузке уровня менеджер ресурсов будет просто грузить спрайты в атлас по указанным в конфиге координатам.
ОК. Понял.
> что в нем еще помимо AddSprite() и Draw() будет?
А что еще надо?
> Какие еще могут быть способы
Ну я преувеличил конечно. Те же дисплейные списки, массивы без VBO. Это все внутри может иметь множество настроек. Сколько данных на вершину, как это все упаковано: в одном массиве или в нескольких, нужна ли вообще текстура или ты хочешь просто прямоугольник с градиентом нарисовать. Если отображение спрайта сделать удобным и универсальным, то получится тот же GDI со всеми его тормозами.
>> No.14389 Reply
File: priznak_koshkosti_60.jpg
Jpg, 43.61 KB, 600×214 - Click the image to expand
edit Find source with google Find source with iqdb
priznak_koshkosti_60.jpg
>>14370
> А что еще надо?
Я не знаю. Первый раз игру с ОО подходом делаю, могу запросто чего-нибудь не знать. Сейчас мне кажется, что ничего, кроме этих двух функций, рендер-менеджеру не надо. Если это так (и ничего специфичного для игр, а не для рендеринга, в рендер-менеджере больше не нужно), то, значит, ничего и не надо.
> Какие еще могут быть способы
Верю, но примеры ты привел неудачные. Все это скорее разные способы реализации, нежели кастомизации.

Смотри. Задача: нарисовать прямоугольник с текстурой. Не без текстуры, не треугольник, не затененный прямоугольник, а именно прямоугольник с текстурой. С углом поворота и масштабированием. Заказчику (то бишь, пользователю движка) абсолютно наплевать, как это внутри будет реализовано. Всё, что он хочет - это задать текстурный атлас, координаты в текстурном атласе, координаты прямоугольника, угол поворота, масштабы по осям и отрисовать всё это. Что тут вообще можно кастомизировать? Лично мне на ум приходит только формат, в котором будут передаваться координаты: float, double или half. Что еще заказчик может захотеть поменять (в рамках указанной задачи)?
>> No.14401 Reply
>>14389
> Задача: нарисовать прямоугольник с текстурой. Не без текстуры, не треугольник, не затененный прямоугольник, а именно прямоугольник с текстурой. С углом поворота и масштабированием.
Это уже достаточно специфичная задача для видеокарты заточенной под 3D.
> Что тут вообще можно кастомизировать?
Группировать в батчи(те же VBO) или нет. Если вся текстура = спрайт, то выбор прямоугольника из текстуры это лишние расходы. Это у нас тексель = пиксель, а частенько ведь используют систему координат вида: (0,0)-центр, (-1,-1)-лев. угол, итд; и каждый раз масштабировать будет не удобно. Если объект статичный, то можно один раз отправить на видеокарту, а потом только вызывать отрисовку. Частенько-таки надо передавать и цвет для спрайта — плюс float на вершину.
Или опять неудачные примеры?… О чем мы вообще спорим?
>> No.14411 Reply
File: priznak_koshkosti_61.jpg
Jpg, 35.71 KB, 600×214 - Click the image to expand
edit Find source with google Find source with iqdb
priznak_koshkosti_61.jpg
>>14401
> > Что тут вообще можно кастомизировать?
> О чем мы вообще спорим?
А мы и не спорим. Я просто попросил примеры по-убедительнее.

В общем, да. Такие, казалось бы, примитивные операции, как: "хуйнуть круг", "хуйнуть квадрат", "хуйнуть прямоугольник" - могут иметь овер 9000 параметров и настроек. Но проблема в том, что в API видеокарты они тоже не реализоаны. В нем вообще не реализовано ничего, связанного с рисованием (вместо этого там поебота, которую я описывал в первых своих постах). Поэтому, если мы хотим рисовать с помощью видеокарты, нам придется писать какие-то обертки для него, будь то универсальные или предметно-специфические. Универсальные писать долго и дорого, да и не нужны они. Будем писать предметно-специфические. Первые две такие обертки мы уже наметили: это операция "хуйнуть прямоугольник с текстурой из атласа" (с группировкой подобных задач) и работа с шейдерами.

Так, пора решить пару организационных вопросов. Давайте договоримся называть меня Альфа, >>14401-куна - Браво, >>14068-куна - Чарли. Те, кто захочет присоединиться, пусть сразу сообщают, что они Дельта, Эхо и т. д. Не бойтесь, 26 букв нам хватит за глаза. Тем более, если я собрался работать в режиме one-man army.

Разработка у нас будет задачно-ориентированная (я по-другому не умею; стыдно): в исходниках или в багтрекере любой может написать тудушку, и любой может ее взять на себя. Когда берем на себя тудушку - ассигним ее на себя (если в багтрекере) или дописываем свой позывной ("TODO: Delta, Please implement this..."). И сразу же, сразу же коммитим, дабы исключить условие гонки хотя бы частично.

Делать тудушки и тикеты я никого не заставляю. Но если уж взялись, заассигнили на себя, то извольте довести дело до конца. Мы же ждем, думаем, что вы делаете.

Правила оформления исходного кода. Я думал над ними и решил не выпендриваться и взять микрософтовские соглашения (не нашел ссылку) за некоторым исключением: никаких копирайтов, номеров ревизий и прочего говна. В исходных кодах должен быть только исходный код. Плюс таски в нашем случае. Все остальное - удел документации, файлов с лицензиями и системы контроля версий.

В ближайшее время создам-таки проект на гитхабе и выложу структуру папок.

Ой, еще надо ж конфиги окончательно оговорить... Ну, в следующий раз уже.

А пока первая таска: найти библиотеки для работы с OGG и MP3 и убедиться, что Mono умеет работать с WAV.
>> No.14412 Reply
>>14411
Забыл добавить - если есть ник, то в качестве позывного пусть используется он. Не страшно.
>> No.14446 Reply
>>14411
> Правила оформления исходного кода.
Вот http://www.rsdn.ru/article/mag/200401/codestyle.XML практически полностью соответствуют мелкосовтовским по C#. Мне только не нравиться имена приватных переменных-членов класса со знаком подчеркивания.
>> No.14514 Reply
File: priznak_koshkosti_62.jpg
Jpg, 36.28 KB, 600×214 - Click the image to expand
edit Find source with google Find source with iqdb
priznak_koshkosti_62.jpg
>>14446
Не надо подчеркиваний. Микрософт, ЕМНИП, советует поля и переменные писать с маленькой буквы, а все остальное - с большой.

Я перестраиваю режим сна и бодрствования. Скоро буду.
>> No.14656 Reply
>>14446
Одна проблема, я не пишу на шарпе.

Да, я вернулся после пары недель отсуствия, за это время потыкал свой редактор, сейчас пытаюсь в нем реализовать подход "спрайты отдельно, сущности отдельно". Да, единственная вещь, которая требует изменения для затачивания под вашу задачу - это lua<->python преобразователь, который запросто меняется на какую-нибудь lxml, потому что единственная задача его - преобразование структур данных в питон-структуры. Все остальное - спокойно натыкивается дизигнером. Вот только формат хранения конфигов немного специфичен, но мне нравится такое устройство и я не вижу смысла его менять. Суть в следующем: отдельные файлы конфигов имеют соответствующее расширение, например first.sprites, second.sprites, third.map в каждом таком конфиге может быть сколько угодно записей, которые имеют имя(отображаемое, для лучшего восприятия в процессе редактирования), тип(например, "эльф", "стража дворца", "злодей". Описываются по разному, но по сути имеют общего абстрактного предка entity, поэтому все лежат в файле korovani.entity, редактируются одной и той же вкладкой редактора), id(тип_имя_рандомноечисло (формирование имени пока как затычка), служит для внутреннего обращения и генерится редактором), все остальное никак не влияет на что-то кроме свойств самого объекта и спокойно крутится в любую сторону под любые нужды.


Password:

[ /tv/ /rf/ /vg/ /a/ /b/ /u/ /bo/ /fur/ /to/ /dt/ /cp/ /oe/ /bg/ /ve/ /r/ /mad/ /d/ /mu/ /cr/ /di/ /sw/ /hr/ /wh/ /lor/ /s/ /hau/ /slow/ /gf/ /vn/ /w/ /ma/ /azu/ /wn/ ] [ Main | Settings | Bookmarks | Music Player ]