Ответы пользователя по тегу Разработка игр
  • Выбор игрового движка для C++?

    @MarkusD Куратор тега C++
    все время мелю чепуху :)
    Много решений подходит под такие критерии. Смотри, изучай, выбирай.

    Cocos2d-x является одним из самых популярных открытых движков. У него большое сообщество и масса поклонников. Есть документация и все нужное для старта.

    Godot Engine не менее популярен и не менее поднят по возможностям. В чем-то Godot даже будет лучше чем Cocos. Сообщество у него тоже большое. Документация тоже присутствует.

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

    Дальше пойдут не такие популярные решения, однако и проходить мимо них тоже не стоит.

    Urho3D является нареченной Open-Source альтернативой Unity. Движок используется многими энтузиастами. По разным уголкам сети раскиданы многочисленные группы обсуждения этого движка. Документация и примеры у него на месте.

    GDevelop - это довольно популярное решение для небольших игр. Документация на месте.

    Panda3D - тоже довольно популярное решение со своим сообществом. Документация имеется.

    Hazel Engine - один разработчик - один движок. Полностью вся разработка изложена в видео на youtube. Пользоваться можно... на свой страх и риск.

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

    GZDoom - современная инкарнация движка DOOM.

    Дальше решения пойдут или сложные, или экзотические. Всё на свой страх и риск.

    CryEngine - от Crytek.
    X-Ray - движок S.T.A.L.K.E.R.
    UE 3 - для коммерческих проектов использовать нельзя.
    Lumberyard - от Amazon. Да-да, тот самый.
    Banshee Engine - он просто существует.
    Diligent Engine - у него есть свое сообщество.
    Atomic Engine - на нем тоже выпускают игры.
    Lumix Engine - тоже что-то может.
    Horde 3D - просто существует и этого уже достаточно.
    Ответ написан
    Комментировать
  • Как программно рассчитать коллайдеры для спрайтов?

    @MarkusD
    все время мелю чепуху :)
    Существует семейство алгоритмов под названием Convex Hulling, позволяющих с требуемой точностью обернуть изображение в примитив.
    Полученный контур примитива уже можно использовать для заполнения коллайдерами, тоже с требуемой точностью.
    Для заполнения примитива коллайдерами может подойти алгоритм из семейства Bin Packing. Они позволяют учитывать перекрытие и неточность заполнения контура.
    В результате, при подборе реализаций и при подстройке критериев ты можешь получить результат, сравнимый с приведенными на изображениях.

    Однако, лично я рекомендовал бы остановиться уже на контуре примитива изображения. Если это все действительно коллайдеры, то проверка одного замкнутого многоугольника будет дешевле проверки потенциально бесконечной коллекции окружностей.
    Ответ написан
    1 комментарий
  • Как сделать разрушаемость?

    @MarkusD
    все время мелю чепуху :)
    Коротко о разрушаемости в Noita излагается в презентации разработчиков на GDC.
    Детальное описание разрушаемости в Jelly in the sky от автора игры: [1], [2], [3].

    В Червяках же реализация разрушаемости довольно простая.
    Мат. модель уровня состоит из битовой матрицы (где поднятый бит является заполненным, а снятый - пустым), и набора функций рисования в этой матрице. В этой битовой матрице изначально генерируется уровень и эта битовая матрица модифицируется в процессе игры. Функции рисования являются стандартными - это рисование линии от точки и до точки с заданной шириной, а так же рисование залитой окружности. Само рисование происходит нулевыми битами.
    По своей сути Червяки являются таким замысловатым редактором для рисования.
    Ответ написан
    4 комментария
  • Какие есть способы реализации системы внешних скриптов?

    @MarkusD Куратор тега C++
    все время мелю чепуху :)
    Инструментов для решения такого вопроса очень много.
    Методика решения всегда одна: необходимо выбрать и интегрировать в свой проект скриптовой движок.

    Вопрос выбора скриптового движка является очень сложным и зависит от множества неочевидных критериев. Ответ на такой вопрос сможет дать только опытный инженер, неоднократно имевший дело с разными скриптовыми движками. Потому что даже между Lua, LuaJIT и Terra разница по функциональности и особенностям интеграции является очень существенной.
    И, тем не менее, я этот вопрос оставлю открытым. На крайний случай всегда можно взять простой и легкий Lua, если глаза разбегаются, а решения нет.

    Как производят интеграцию. Например - так, так, так, так, так или вот так.
    После интеграции скриптового движка в свой проект, функциональность своего проекта можно прокинуть на сторону скриптов используя непосредственно API скриптового движка.

    Одним из критериев выбора скриптового движка является его производительность. Чтобы не занимать специалистов подобной рутиной, когда-то давно уже были проведены замеры версий различных скриптовых движков. Результаты замеров доступны всем желающим.
    Однако, стоит напомнить, что не всегда самое быстрое решение является самым оптимальным.
    Ответ написан
    1 комментарий
  • Как организовать Tween систему в рамках ECS (entt)?

    @MarkusD Куратор тега C++
    все время мелю чепуху :)
    Одним компонентом и одной системой в таком случае не обойтись. Когда затронуто произвольное количество иных компонентов, связывать их все с каким-то одним компонентом - это зарывать ECS обратно в землю.

    Почему дизайн с одним компонентом обречен. Каждая система в ECS должна работать с выборкой по компонентам. В EnTT это делается с помощью представления потока компонентов - entt::registry::view.
    Такое представление оптимальным образом организует последовательность сущностей, в которых точно присутствуют обозначенные в представлении компоненты. Если начать проверять наличие у сущности иных компонент, помимо того что это противоречит концепции ECS, это затронет выборку из памяти за пределами отображения и сильно снизит производительность системы. Поэтому системе не стоит работать с компонентами за пределами своей выборки.

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

    Как быть в таком случае. Нужно выделять функциональность в более локальные системы вместо одной большой системы интерполяции. Вот есть у тебя компонент цвета сущности - ColorComponent, и этот цвет у тебя может интерполироваться. Значит тебе нужен компонент интерполируемости цвета - ColorInterpolationComponent. В этом компоненте интерполируемости нужно определить закон интерполяции, начальное и конечное значение, а так же время интерполяции. ColorInterpolationComponent говорит о том, что все данные ColorComponent интерполируются по определенному закону между определенными значениями и за определенное время.

    Функции интерполяции у тебя всегда чистые, т.е. зависят только от переданных им аргументов. Для любого типа данных, от скаляра и до матрицы, можно определить функцию интерполяции между двумя значениями. Это все - внешние относительно ECS вещи, а внутри ECS на каждый ***InterpolationComponent у тебя будет своя система, которая делает выборку по целевому компоненту и по компоненту интерполируемости. Таким образом, уже на стадии выборки компонентов у тебя останутся только подходящие сущности, а все остальные - отфильтруются.
    Заметить стоит еще то, что такой подход позволяет одно конкретное значение интерполировать только одной функцией за раз. Если для одного значения требуется несколько одновременных интерполяций, такой подход уже не подходит. С другой стороны, для того чтобы правильно свести несколько таких анимаций для одного значения, требуется значительно более сложная система, чем просто функция интерполяции.
    Ответ написан
    2 комментария
  • Разработка игр для андроид на языке С++?

    @MarkusD Куратор тега C++
    все время мелю чепуху :)
    C++ не является полноценно "родным" языком для Android. Но для этой платформы можно вести разработку на C++.
    Такие движки, как cocos2d-x [?], Urho 3D [?], Unreal Engine 4 [?], Godot Engine [?] и, буквально, море менее известных проектов, позволяют вести разработку игр с использованием языка C++.

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

    Если использование C++ для тебя является важным, о Unity можно забыть. Это взаимоисключающие инструменты.
    И это не важно. Тот же Urho 3D позиционируется как Open Source Unity. Godot Engine обладает не меньшей свободой и гибкостью, но предлагает больше.
    Ответ написан
  • Как связать игровое клеточное поле в Entity Component System?

    @MarkusD
    все время мелю чепуху :)
    Вообще, пространство игрового поля не очень хорошо выражать в терминах ECS. Игровое поле - это, как правило, монолитный участок логики, для которого лучше подошел бы подход CBSE(COP). Обычно игровое поле представляется композицией нескольких пространств, в которых работают механики игры. Такие пространства удобнее выражать компонентами из CBSE, а не компонентами из ECS.

    Однако, не смотря на это все, есть хороший способ реализации игрового поля терминами ECS. Особенно если игровое поле дискретно.
    Чтобы начать думать в этом направлении, сперва требуется изучить клеточные автоматы: [1], [2].
    Когда с принципами работы клеточных автоматов станет понятнее, стоит обратить свое внимание на шаблон инверсии контроля. При прямом контроле всем твоим миром руководит квант времени, который спускается с главного цикла до каждой сущности. Такой подход неприемлем на игровом поле в терминах ECS.

    Клеточный автомат оперирует возбужденными и пассивными клетками. За счет инверсии контроля системы обрабатывают не все клетки автомата, а только возбужденные. Во время своего кванта времени, клетка может перейти в спокойное состояние, остаться в возбужденным или передать возбуждение соседней клетке.
    В терминах ECS это все решается компонентами. Возбужденная клетка игрового поля имеет компонент возбужденности, спокойная - не имеет его. У каждой клетки есть компонент с соседними клетками. Если компонента нет - клетка - это остров.

    И теперь самое интересное. Игровые сущности теперь тоже являются компонентами игрового поля. И за счет все той же инверсии контроля игровые сущности теперь обновляться могут только для возбужденных клеток поля. Если клетка спокойна, стоящий на ней персонаж не получает квант обновления. Это - важное правило, которое требуется соблюдать чтобы не нарушать целостность реализации игрового поля через ECS.
    Любое управление персонажем может только возбуждать клетку игрового поля, где стоит персонаж. Когда персонаж перемещается в другую клетку, между клетками переходит не сам персонаж, а его компоненты. Буквально, сперва делается перемещение данных компонентов персонажа в сущность целевой клетки, а потом происходит удаление компонентов персонажа в текущей клетке.

    Касательно сущностей. Для дискретного поля сущностью является клетка. При этом, согласно терминологии ECS сущность - это эфемерный объект, лишь идентифицирующий свои компоненты. Иными словами, клетка дискретного поля может быть выражена идентификатором своих координат. Запрашивая тот или иной компонент, запуская квант системы или ссылаясь на сущность через идентификатор ее координат, мы всегда будем точно знать геолокацию своих действий в игровом поле. Однако, для реализации такого механизма требуется разработать собственную реализацию ECS.
    Сущностью ECS может быть и не только одна клетка игрового поля, а, скажем, один чанк 16х16 клеток, в котором сохраняются все правила клеточного автомата.

    Через такой подход вполне возможно реализовать что-нибудь вроде Factorio.
    Ответ написан
    Комментировать
  • Как организовать структуру игры Монополия на ECS?

    @MarkusD
    все время мелю чепуху :)
    Самой главной ошибкой начинающих работать с ECS людей является попытка засунуть в ECS сразу и вообще всё.

    У тебя игра по типу монополии. Что есть в монополии?
    В игре заявлены игроки, дискретное поле, активы и события. Еще могут быть заявлены дополнительные правила.
    Игроки и активы имеют свои эффекты и могут быть деактивированы событиями. Собственно, это и есть сущности игрового ECS-мира.

    И тут важно понять, что не сами игроки и активы являются сущностями ECS, а лишь свойства игроков и активов являются сущностями.
    Сами игроки являются внешними к ECS, для каждого игрока в ECS заводится сущность, идентификатор которой сразу прикрепляется к объекту игрока. Теперь игрок может взаимодействовать с миром игры через данные своей сущности. Точно так же делается и для активов.

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

    По своей сути, в монополии ECS будет выполнять задачу документооборота между сущностями. Добавить компонент владения, убрать компонент владения, зачислить деньги, списать деньги, добавить компонент активности, убрать компонент активности. ECS управляет только общими свойствами между полностью обезличенными сущностями, где между игроком и купленным им активом нет фактической разницы.
    Механизм перевода хода тоже является полностью отдельным от ECS, он может только опираться на набор компонент игроков и данные компонент.
    Ответ написан
    3 комментария
  • Entity Component System + ООП подход?

    @MarkusD
    все время мелю чепуху :)
    ECS является подходом декомпозиции не только логики и данных, но и подходом отказа от агрегации и наследования в пользу косвенной композиции. Явной композиции в ECS тоже не предусматривается, а косвенная композиция не намекает на связность или структурированность данных. Косвенная композиция обозначает только наличие каких либо данных по некоторым косвенным признакам.
    Более того, в рамках ECS сторонний код и с данными нормально работать не способен. Для стороннего кода в ECS предусматривается уровень абстракции для чтения и записи данных.

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

    К примеру есть сущность игрок с набором компонентов наследованная от Entity,

    Нет, это сразу будет не ECS. Сущность игрок - это и есть entity, являющаяся эфемерной единицей в мире ECS.
    И методов у entity быть не может. Вся логика сущностей распределена по системам и сильно зависит от имеющихся у сущности компонент.
    Более того. Если ты говоришь о том, что в твоем мире может существовать сущность с характеристикой игрока, таких сущностей в твоем мире может быть до 100% всего ECS мира. Если игрок у тебя должен быть представлен единичной сущностью, значит это уже не сущность, а внешний объект, по ошибке введенный в ECS мир.

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

    Про состояния, пустые компоненты добавлять удалять в entity как флаги что сущность в каком либо состоянии, и отдельные системы для обработки каждого состояния это нормальный подход ?!

    Битовые компоненты - это рядовая оптимизация для хранения пустых компонент. Да, так делают и обеспечивают правильную работу систем, чтобы фильтры компонент одинаково обрабатывали как полноразмерные компоненты, так и битовые тоже.
    Ответ написан
  • OpenGL и C++. Как лучше отсортировать полигоны?

    @MarkusD
    все время мелю чепуху :)
    Честно говоря, странно видеть в заголовке и тегах вопрос об OpenGL, а в теле вопроса - про коллизии и, возможно, физику.

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

    Тебе надо иметь два набора вершин. Один - набор вершин для визуализации объекта. Второй - набор вершин для симуляции его физики, не только коллизий. И таких наборов может быть много. Для симуляции повреждений и деформаций, для скиннинга, для хитбоксов, для постройки маршрутов перемещений, для звуков...
    BSP подходят больше для отсечения видимой геометрии. В наши дни этот подход не оправдывает своих затрат, его не используют. Для эффективной симуляции коллизий лучше подходят QTree, OTree или KD-списки.

    Почитать начать можно отсюда: Study path for game programmer. Твой раздел: 9. Game Physics and Animation.
    Далее, тебе сюда: https://gamedev.ru/code/articles/?physics
    Да, геймдев все еще жив, хоть уже и не принадлежит Сереге Ваткину.
    Следом лучше пойти на хабр: [1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11].
    У Фабьена Сангларда есть набор статей о внутреннем устройстве DOOM 3 и Quake 3, там есть материал и про столкновения.

    На этом этапе у тебя уже должно сформироваться представление о предметной области симуляции коллизий.
    Ответ написан
    Комментировать
  • Game-dev путь. Что мне делать?

    @MarkusD
    все время мелю чепуху :)
    Вот держи: Game developer roadmap и Study path for game programmer.
    Этих двух ссылок тебе лет на 15 усерднейшего запоя хватит. :)
    Подробнее, чем там, больше негде.
    Ответ написан
    Комментировать
  • Какую технологию использует Steam для создания игроками серверов?

    @MarkusD
    все время мелю чепуху :)
    Steamworks API предлагает специальный слой абстракции сети - Steam Networking.
    В рамках этого слоя соединение устанавливается между конкретными пользователями по их Steam идентификаторам. Тип соединения между пользователями зависит от конкретных настроек сети. При соединении в открытой сети или в присутствии несимметричного NAT соединение между хостами пользователей будет установлено напрямую. В случае присутствия симметричного NAT соединение будет установлено через специальный Relay-сервер. Steam берет на себя всю рутину с определением типа сети, выбором типа соединения и с его поддержкой во время сеанса игры.

    Сама техника определения соединения и установки подключения является широко известной и общепринятой. Это - NAT Punchtrough. Описывать технологию в ответе бессмысленно, т.к. в сети по этому названию есть очень много документов [1][2][3][4].
    Для определения типа сети у Steam есть набор региональных STUN-серверов, а так же набор Relay-серверов, выступающих посредниками при соединении в присутствии симметричного NAT.

    Примерно в прошлом году Valve начали выделять Steam Networking в отдельный продукт с открытым кодом. Продукт явно будет лишен поддержки серверов Steam, однако его открытый код уже сейчас содержит достаточно информации об организации сети подобного уровня.
    Ответ написан
    Комментировать
  • Как начинать в геймдеве?

    @MarkusD
    все время мелю чепуху :)
    Когда ты молодой и еще только учишься в школе, начинать в геймдеве проще простого!
    Держи дорожную карту: A Study Path for Game Programmer.

    Изучай на здоровье! :)
    Ответ написан
    2 комментария
  • Как ограничить FPS в OpenGL и glut?

    @MarkusD Куратор тега C++
    все время мелю чепуху :)
    Само ограничение частоты кадров делается очень просто. Снаружи idle-функции нужно содержать переменную с временем последнего вызова idle-функции, а в самой функции нужно просто накопить дельту частоты кадров и вызвать glutPostRedisplay.
    double GetCurrentTime()
    {
    	using Duration = std::chrono::duration<double>;
    	return std::chrono::duration_cast<Duration>( 
    		std::chrono::high_resolution_clock::now().time_since_epoch() 
    	).count();
    }
    
    const double frame_delay = 1.0 / 60.0; // 60 FPS
    double last_render = 0;
    void OnIdle()
    {
    	const double current_time = GetCurrentTime();
    	if( ( current_time - last_render ) > frame_delay )
    	{
    		last_render = current_time;
    		glutPostRedisplay();
    	}
    }


    Данный код является сильно упрощенным механизмом, лишь показывающим общий принцип ограничения частоты кадров. Его можно применять там, где не требуется точный контроль дельты между кадрами. К слову, представление времени в типе double помогает легче находить дельту между кадрами и контролировать ошибку дельты.
    Для более точного контроля частоты кадров стоит обратиться, например, к такому материалу.
    Ответ написан
    1 комментарий
  • OpenGL не сразу отображает данные из кадрового буфера?

    @MarkusD Куратор тега C++
    все время мелю чепуху :)
    Я не вижу в твоем коде вызова glutIdleFunc. В документации написано что GLUT будет постоянно вызывать переданную функцию в свободное от обработки системных сообщений время. А если в glutIdleFunc передан nullptr (или idle-функция не была задана), то GLUT будет строго ждать следующего системного сообщения.

    Если я все правильно помню, то передача настоящей функции, в которой будет вызываться функция glutPostRedisplay, в glutIdleFunc приведет и к регулярной перерисовке экрана.
    Как правило, в качестве idle-функции в GLUT передают update-функцию, в которой обновляется состояние объектов перед рендерингом.
    Ответ написан
    5 комментариев
  • Как создается единая физическая-графическая модель?

    @MarkusD Куратор тега C++
    все время мелю чепуху :)
    И почему крупные компании не могут реализовать свою такую технологию, а покупают ее у других?

    Ответ будет таков
    5a2b8fc21c685856187802.jpeg

    Если компания крута, она, как мыслящий организм, прекрасно поймет, на что время тратить разумно, а на что - нет.

    А почему так мало игр ее использует?

    Скажем прямо, с "еще парой игр" ты слегка промахнулся, ведь Morpheme и Euphoria от Natural Motion используется далеко не в паре просто игр. Полный список игр не раскрывается и не может быть раскрыт по простым причинам своей масштабности. Это очень распространенный и очень мощный инструмент.

    Теперь стал интерисовать вопрос - как прикрутить к этому всему физику.

    Это архитектурные вопросы. Решение очень сильно зависит от того, как у тебя построена математическая модель мира. Мат. модель производит связь в принципе всех компонентов мира между собой.
    Для снижения трудоемкости операций, сетку коллизии нередко делают более разреженной, нежели сетку графической модели. Бывает, что это никак не сказывается на внешнем виде модели. Бывает, что это сильно сказывается. По своей форме коллизионная модель очень часто и очень сильно отличается от графической.

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

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

    Более подробно можно узнать в соответствующих источниках. Нужна секция: "Game engine development".
    Часть этих книг есть в русском переводе.
    Ответ написан
    Комментировать
  • Стоит ли заранее заботится о возможности поддержки предыдущих версий многопользовательской мобильной онлайн игры? И как?

    @MarkusD
    все время мелю чепуху :)
    В процессе сопровождения игры может измениться протокол клиент/серверного взаимодействия или еще что-то, после чего предыдущие версии игры перестанут поддерживаться.

    Честно говоря, изменение и обновление протокола между версиями продукта - это норма жизни. Только не путай с выпуском обновлений контента, это другой вопрос.

    Можно сказать так: сетевой протокол полезно периодически полностью менять. Это хорошая профилактика от разного рода паразитов твоего проекта. Этакая мера гигиены.

    В процессе обновления протокола мы обычно приходим к одному из двух вариантов:
    • Меняется именно протокол - т.е. набор и содержание пакетов.
    • Меняется сервисный код протокола - т.е. сервисный код для сериализации данных в пакеты.


    В первом случае проблем особых не возникает. Второй случай действительно приводит к нарушению совместимости.
    Чтобы в первом случае добиться совместимости между версиями клиентов и сервера, разработчик обычно использует библиотеки сериализации с поддержкой обратной (или/и прямой) совместимости.
    Примерами таких библиотек являются Google Protobuf, Google Flatbuffers и Cap'N Proto. (да, тега C++ нет, но делу это не мешает)
    Еще я сталкивался с самостоятельно разработанными решениями, которые в разной степени обладают достоинствами приведенных библиотек.

    Есть ли статистика по влиянию обязательных обновлений игры на заинтересованность пользователей?

    Статистика по влиянию обязаловки на желание пользователя играть есть - очень большое влияние. Буквально это выливается в последовательность: запустил - просят обновить клиент - удалил, т.к. играть хочу, а не обновлять.
    Так поступает очень много пользователей в странах, где мобильный интернет очень дорогой и одно обновление на 10Мб буквально означает дыру в кошельке.

    Поэтому очень важно предоставить пользователю, по возможности, доступ к уже обновленному серверу с еще старого клиента. Отключай новые функции для игрока, отменяй отсылку пакетов, шли тексты ошибок вроде: "Эта новая фича будет доступна после обновления вашего клиента". Все что угодно, но игрок должен иметь возможность пользоваться тем, что ему доступно сейчас.

    Если мы ведем проект для мобильных платформ, то там ситуация с обновлениями еще интереснее. Тебе никто никогда не скажет, когда в конкретном маркете обновится твоя версия клиента. Выкладка версии - это долгий процесс, синхронизировать его между разными маркетами невозможно. Если у тебя в охвате только GooglePlay и AppStore, то это еще половина проблемы. Обычно маркетов десятки, куда обязательно входит Я.Стор для Android, маркеты от Самсунга, сотовых операторов, мелких лавочников и тому подобного. А если мы заходим в Китай, то число маркетов начинает достигать сотен. И каждый из них твое приложение обновит только когда захочет.
    Это все говорит о том, что обновление сервера и мобильных клиентов - дело несинхронизируемое. Сервер сразу должен быть готов принять обновленные клиенты, поэтому его надо обновить одномоментно с выкладкой версий в маркеты. И в то же время этот новый сервер должен уметь впускать старые клиенты, потому что новые еще не прошли проверку и не выложились для скачивания пользоавтелям.

    Реально ли создать игру таким образом, что бы вносимые изменения не влияли на предыдущие версии и срок службы каждой версии оставался максимальным? И как это сделать?

    Да, реально, примеры таких игр уже лет 8 с лишним бороздят просторы Appstore и GP. Названий не дам, рекламой не занимаюсь, пеарить не привык.
    Я в своей работе использую Cap'N Proto и Flatbuffers. Эти две библиотеки покрывают задачи обратной совместимости для протокола и бинарных ресурсов. Использования этих библиотек хватает для свободы изменять данные не боясь потерять клиентов.
    В общем, для решения этой проблемы нужны инструменты обеспечения обратной и прямой совместимости.

    Важно понимать, что совместимость обеспечивать надо не только для протокола, но и для ресурсов клиента.
    Ресурсы могут быть залиты на локальный CDN провайдера пользователя и поставляться по каналу связи с льготным тарифом, но у пользователя может не быть возможности зайти в Appstore и обновить само приложение клиента.
    Поэтому, старый клиент должен иметь возможность запускаться с новыми ресурсами в режиме совместимости.
    Именно эту задачу и решает библиотека Flatbuffers. Она дает возможность обновлять формат бинарных данных вперед и сохранять очень эффективный доступ к ним через старую версию формата.

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

    Может ли задача сопровождения предыдущих версий сильно влиять на архитектуру ПО, скорость и процесс разработки?

    Если сгрузить часть работы (ту часть, где надо заниматься непосредственно обеспечением совместимости) на ребят из OpenSource сообщества (и обязательно стать его частью, кстати), то задача сопровождения становится легкой.

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

    Если сказать в общем. Да, обеспечивать совместимость - это тяжело. Это ряд архитектурных решений, которые должны быть сделаны правильно. Но если навыки уже есть, если есть опыт, если есть видение проекта, то обеспечение совместимости - штука посильная.
    Ответ написан
    1 комментарий
  • Как стать художником в геймдеве?

    @MarkusD
    все время мелю чепуху :)
    Юра Березовский , читать сгодится все то, что полезно для укрепления знаний. Книги по архитектуре, машиностроению, анатомии животных и людей, бодибилдингу (т.к. там хорошо рассказывают про моторику и мышцы).

    Конкретнее... Вот, что глазом у жены с полок ухватил:
    * Джеймс Гани - Цвет и свет.
    * Готтфрид Баммес - Образ человека
    * Ф. Делавье - Анатомия силовых упражнений.

    И, как всегда, изучать первым делом надо всё. Но укрепляться желательно только в тех направлениях, которые тебя увлекают. Тогда твои навыки попрут в гору.

    Основные инструменты артиста имеют или вот такое название:
    Логотипчики
    148715.gif
    или вот такое:
    huion-logo-1421263547.jpg


    Wacom - дороже и считаются более крутыми. Huion - молодые, дерзкие, все время норовят куснуть у вакома долю.
    Бытует мнение, что даже если сейчас у тебя не получается работать с планшетом, все равно работе с ним стоит уделять минимум 2 часа в день. Привыкнешь.

    ArtStation хорошо мотивирует самообучаться.
    Роман Гура, вроде, иногда берет учебные группы за денежку. Навык Ромка поднимать умеет как у тех, у кого все кисло, так и у тех, кто уже чего-то добился.
    Лео Хао, вроде бы, тоже недавно занимался обучением начинающих.

    А вот на счет того, как развивать свои навыки, есть вот такой совет:
    i9Cbdc9K9XA.jpg

    Кстати, советую запиннить группу "Берешь и рисуешь", она полезная.

    Как-то так, в общем. Дерзай.
    Ответ написан
    Комментировать
  • Что такое анимация и с чем ее кушать если OpenGL?

    @MarkusD Куратор тега C++
    все время мелю чепуху :)
    Spine C runtime.
    https://github.com/EsotericSoftware/spine-runtimes...
    Это не серебряная пуля и не идеальные практики. Пожалуй, в плане кода это пример наоборот, как код писать точно не надо.
    Но вот в плане реализации анимаций эта репка тебе очень поможет.

    Суть такова. Есть модель, она статична. Есть отрезок времени (таймлайн), на этом отрезке есть точки - ключевые кадры. Ключевой кадр несет в себе информацию о том, какую часть модели и как сместить. Чем проще инструкция в ключевом кадре, тем удобнее. Масштаб, поворот и смещение многие любят разделять по разным таймлайнам.
    OGL в этом деле не нужен, до поры.

    С помощью SRT таймлайнов можно анимировать объекты в пространстве целиком, но если тебе захочется точно так же анимировать части меша модели, то впереди тебя будут ждать трудности.
    Анимацию меша лучше реализовать на основе скелета. Это дело в двух словах уже не описать, тут лучше читать статьи.
    www.gamedev.ru/code/terms/SkeletalAnim
    www.gamedev.ru/code/articles/skeletal_animation
    https://habrahabr.ru/post/219509/
    https://habrahabr.ru/post/304042/
    www.gamedev.ru/code/articles/?id=4182

    Самое зерно скелетной анимации в том, что модель остается моделью, анимируются только кости скелета. И именно анимация кости приводит к перемещению фрагмента меша.

    Только на одной скелетной анимации далеко все равно не уедешь. Когда требуется на одной модели одновременно задействовать сразу несколько скелетных анимаций, если сделать в лоб, то меш поплывет во все стороны.
    Для смешивания различных скелетных анимаций применяют так называемые Blend Trees (ссылок под рукой нету, так что сорри).

    В общем, как то так анимация выглядит. Анимируем в цикле обновления, вершины трансформируем в момент формирования кадра. OGL нам нужен, собственно, чтобы нарисовать раскоряченый анимацией меш.
    OGL для непосредственного анимирования мешей тебе понадобится только тогда, когда ты достаточно глубоко нырнешь в анимации, в тот же момент ты уже полностью поймешь что от OGL понадобится для этого.
    Ответ написан
    2 комментария
  • Как сделать управляемый интерфейс?

    @MarkusD
    все время мелю чепуху :)
    Макар Герасимов , такс, для начала отключись от рисования и восприятия процесса глазами.

    Первое, что тебе надо - это модель игрового поля. Модель - от слова "данных". В первую очередь тебе надо представить игру в виде модели данных, а не визуального представления. Вот давай пробуем...

    Тетрадный лист в клетку напоминает что? - правильно, двухмерный массив. Стало быть, игровое поле удобно представить в виде двухмерного массива. А какой тип ячейки массива? - раз у нас игра про слова, которые по буквам пишутся в клетках, то, пожалуй, в ячейках надо хранить символы.

    Крутяк, придумали игровое поле, в котором хранятся символы! Только заметь, символа в ячейке может и не быть.

    Хорошо, идем дальше. У нас есть два игрока, которые могут писать слова.
    Ага... Если писать, то надо знать - куда. Пользователю нужно указание, куда он сейчас будет писать - указать ячейку, в которую он сейчас поставит символ. А ячейки у нас в двухмерном массиве. Удобнее всего будет хранить координаты текущей ячейки пользователя!

    Стало быть, пользователь у нас, как минимум, определяется координатами выбранной им ячейки на поле.

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

    Когда пользователь вводит слово, нужно ограничивать движение его выделения только соседними клетками. Поставил пользователь первый символ, все, он вводит слово.

    И заметь, это все полностью отвязано от графического представления. Сперва всегда надо продумывать именно модель данных.
    На данном этапе описания у нас есть поле, пользователи с их выделениями и введенные слова. Модель данных дает полное представление как ее представлять пользователю.

    Ну разве проблема отрисовать двухмерный массив символов? А по координатам закрасить другим цветом выделенную пользователем ячейку?

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

    Когда твоя модель данных игры будет хоть немного готова, ее можно будет без труда хоть в консоль рисовать, хоть на поверхности окна.
    Модель - это набор классов со связями. Поле, игра, игрок, ход, слово, словарь, таблица введенных слов... символ слова(?). Полный список сущностей ты знаешь лучше меня. Просто думай на уровне данных. Тогда и управлять ими сможешь. :)
    Ответ написан
    4 комментария