Nexeon , поэтому всю работу по отслеживанию занятых битов и все обеспечение удобства работы перекладывают на компилятор. Ни один человек в здравом уме не начнет следить за обеспечением уникальности номеров битов для компонентов. :)
Суть такова: компоненты для ECS сперва регистрируются. Это нужно не только для их индексации, но и для оптимизации хранения компонентов, и для оптимального управления компонентами для сущности.
Nexeon , да, правильно. :)
Смотри, в EntityX, Autodesk Stingray, Artemis и у меня в моем фреймворке применяются маски и индексирование компонентов.
Коротко: на этапе компиляции (ага, снова метапрограммирование) для каждого типа компонента рассчитывается битовый индекс - это всего один поднятый бит на участке из N бит (int32_t, int64_t, 128, 256..). В EntityX, к примеру, это номер бита для std::bitset. Я предпочитаю снова все делать на этапе компиляции.
У каждой сущности есть битовое поле - маска компонентов. Когда компонент добавляется, в маске поднимается его бит, при удалении - снимается.
При этом, проверка наличия компонента делается через проверку соответствующего компоненту бита. А для проверки группы компонентов делается битовая маска группы, проверка все так же делается через одну операцию.
В Artemis и у меня есть возможность производить сложные проверки: найти сущность строго с такими компонентами (операция "и"), а еще с любым набором других компонентов (операция "или") и чтоб без третьих компонентов (операция "не").
Это уже потребует некоторой библиотеки метапрограммирования - MPL. Без нее сделать это все становится сложнее.
Nexeon , весь этот код уже можно отнести к разделу метапрограммирования в C++... Да, я все время забываю что это необычная тема.
Не прямо такой, а подобный код я имею обыкновение создавать и использовать в своей работе. Он работает. :)
Общая суть кода такова. Если мы можем проверить наличие одного компонента, то мы точно так же можем проверить и наличие множества компонентов сразу. Для этого нам надо знать функцию проверки каждого компонента из произвольного списка, после чего вызвать набор этих функций, аккумулируя результат.
std::all_of - простая замена цикла по итерируемому множеству с аккумулятором через операцию `&&`.
В качестве множества для std::all_of хорошо подходит массив указателей на функции проверки одного одиночного компонента.
В результате компилятор пишет код проверки группы компонентов за нас. :)
И еще вот наглядная демонстрация работы этого метода. cpp.sh/8b5xo
Folding expressions безусловно удобнее... Все жду начала широкой поддержки 17го стандарта всеми популярными компиляторами...
Airat1995 , тогда сразу меняй эти старые ненужные define-guard-ы на #pragma once.
И не забудь пожалуйста отметить ответ fshp как решение. Чтобы люди не агрились на вопрос. :)
Nexeon , я специально засунул лямбду в all_of, чтобы создать простор для модификаций.
На деле у тебя ведь `HasComponent` является member function? В этом случае тип предиката будет таким: using CheckingPred = bool (Entity::*)();
В лямбде нужно замыкание на this от Entity, ну и вызов предикатов из листа будет немного другим:
MiiNiPaa , со всеми бывает. :)
Я на самом деле тоже не сразу ее увидел, у меня пальцы просто сами не смогли назвать вариативный шаблон `HasComponent`. ))
Александр Синицын , фантазия - штука очень хорошая и безоговорочно полезная. :)
Однако. Увлекаться нельзя. Понимаешь, я сам маялся этим делом с самого начала карьеры. А с ростом проф. уровня мои загоны становились только круче. Строго оговоренный MVP в этом случае решает. romy4 , пожалуй ближе всего к ответу, т.к. правильно все описал.
Итого, с привычкой усложнять боремся через самоограничение. Работаем не дальше оговоренных рамок задачи. Чувство границы - это тот момент, когда тебе хочется хоть что-то продумать наперед (за пределами MVP) без железно отработанного опыта.
nkorobkov , не, из-за чего-то другого, парень просто так тебе написал это. :)
Система сборки проекта у тебя какая? У тебя многофайловый проект, тебе надо задать сценарии сборки всех файлов исходного кода и линковки их всех в бинарный файл.
Margo1964 , комп в целом не сбалансирован.
Мать слабая, очень слабая, офисная. Процессор для офиса, а не для игр. Оперативная память обычная.
Плюс, базового разгона нет 100%, т.е. комп сейчас выдает только номинальную производительность, а не рядовую и точно не крейсерскую. Охлаждение не обозначено, но скорее всего оно тоже слабое.
В общем, я бы такой комп игроку не собрал бы.
Ну и... AMD. Как бы хорошо я не относился к этой фирме (и видеокарты у них лучше, и SoC для мобильников производительнее), но игры сейчас оптимизируются под запуск на процессорах Intel (это фигня, но от этого пока не уйти).
Андрей , в этом случае лучше самостоятельно ответить на свой вопрос и пометить ответ как решение. Не стоит саботировать правила тостера.
Детально ответ лучше оформить так, чтобы всем было понятно где ты ошибся. Что-то вроде такого:
В своем списке ты хранил объекты типа Person по значению, при добавлении в список объекта типа Adult происходило копирование только данных Person. После этого приведение типа Person к типу Adult становилось бессмысленным, а вызов функции `GetDescription()` приводил к выходу за границы памяти объекта и вызывал ошибку доступа к памяти.
Кстати, это выдает незнание/непонимание самых базовых моментов работы с языком. Поэтому Джеффа Элджера тебе в помощь.
muzclubs , да не, не надо.
Сложность задачи от разнообразия препятствий не меняется. К тому, же, даже если все препятствия могут двигаться на любую из 8 клеток вокруг себя, то если два препятствия стоят вплотную рядом, у них уже появляется специфика перемещения. Они уже не могут перемещаться на клетки друг друга. И так далее.
Случай с шахматными фигурами никак не усложняет поиск, ведь цель передвижения препятствий - освободить оптимальный путь перемещения.
Может нам лучше перевести обсуждение непосредственно в область задачи? А то я так и чую что ты стараешься обойтись только наводящими вопросами. :)
muzclubs , таких игр море - это жанр "push the box" или "sokoban". :) Только, да, в жанре предусмотрено непосредственное взаимодействие игрока с коробкой.
Можно подумать, наверное, так.
Можно построить взвешенный граф оптимального перемещения. В этом графе должны быть не только свободные клетки, но и все препятствия на пути оптимального перемещения. По этому графу станет видно, нужно ли вообще двигать препятствия. Пусть изначально переход на место препятствия будет вдвое дороже перехода на свободную клетку.
А далее начинается "оптимизация" графа. Армянское Радио правильную мыслю подсказывает.
Оптимизация заключается в том, чтобы попробовать отодвинуть самые "дешевые" препятствия, всякий раз пересчитывая стоимость всего пути.
Еще можно упростить себе жизнь, задав потенциальное поле удорожания маршрута на клетке каждого препятствия. В этом случае первым этапом будет создание потенциального поля. Оно создается от наиболее близких к свободным клеткам препятствий к центру их массы и буквально определяет удорожание пути при движении сквозь препятствия. А вторым шагом будет простой A*.
muzclubs , Мне это напоминает один жанр игрушек. Уж не бота ли ты решил для таких игрушек сделать? :)
Тебе надо немного подольше покурить предложенные материалы. Я чую там разгадку. Только ты дал очень мало информации по своей задаче.
Скажем, пусть препятствиями будут коробки. Игрок их только от себя толкать может? А что если на пути толчка вплотную еще одна коробка стоит? Или же игрок может просто взять коробку и переместить ее на любую другую свободную клетку вокруг себя? А ходить можно так же в 8 направлениях? А если хочется сходить по диагонали когда противоположная диагональ занята коробками, то что? Взаимодействие с коробкой является ходом или нет? И при взаимодействии игрок перемещается на место коробки или нет?
Я так весь день вопросы задавать могу. :) Думаю, если выделишь максимум возможных правил - решение с A* само подтянется.
LittleBuster , читерить - плохо. За это приходит злой одмин и люто банит. :)
Плюс, если ты выяснил что там есть защита, то неплохо было бы ее назвать.
Плюс, DirectInput/XInput никто не отменял, а с ними уже только хирургически сладить можно.
Плюс, раз уж там есть защита ввода, то и DRM должен быть, а это значит что и хирургически без тайных скиллов вмешаться вряд ли получится.
Чтобы уловить это все, тебе стоит почитать о том, как делался Autodesk Stingray.
bitsquid.blogspot.ru/2014/09/building-data-oriente...
Там 4 или 5 статей в блоге, далее по датам после вот этой.
Суть такова: компоненты для ECS сперва регистрируются. Это нужно не только для их индексации, но и для оптимизации хранения компонентов, и для оптимального управления компонентами для сущности.