Как организовать параллельную обработку пересечения нескольких Rectangle в WPF?
Здравствуйте! Пытаюсь на C# сделать что-то типа игры Жизнь. У меня на Canvas бегают много клеток (Rectangle) и я столкнулся с парой проблем.
1. Хочу обработать их пересечения. На данный момент делаю так: когда появляется новая клетка она добавляется в список всех клеток и живет своей жизнью. Каждый раз когда какая-то клетка двигается она в цикле пробегается по этому списку и сравнивает свое положение с положением клетки из списка и если совпадают, то возникает событие их пересечения. И получается, что куча клеток постоянной бегает по этому списку и мне кажется, что это очень не оптимально. Может есть какой-то более оптимальный способ отследить их пересечения?
2. Если пересеклись Cell 1 и Cell 2, то события возникают в обоих объектах, т.е. два раза и хотелось бы обработать их одновременно, т.е. чтобы возникли не два события, а одно, что столкнулись две клетки. Но не могу придумать как это обработать. Ведь таких событий одновременно могут возникать десятки. Думаю, может нужен какой-то класс, который отслеживает эти пересечения и обрабатывает события, но это должно все быть одновременно.
а может plinq посмотрите?
в любом случае это осмысленно только при большом количестве ядер.. и тяжелой обработке события..
а еще стоит подумать о конкурентных событиях и риске одновременных противоречивых решений..
если событий всего десятки (а не миллионы), а обработка событий не требует тяжелых вычислений, вообще не факт что стоит заморачиватся
ps вариант избежать противоречий - своего рода покадровое вычисление поколения. матричная обработка следующей версии, потом замена текущей на новую. это гарантирует НЕпротиворечия в решении. ну и при необходимости уже можно смелее пробовать методы распараллеливания - на момет даже параллельной обработки, исходное поколение гарантированно неизменно. а вот при попытке параллельно обновлять по месту это скорее гарантия ошибочных решений
.. да еще и с непредсказуемой вероятностью )))
pps если не используете биндинг, можно логику обратного времени - копируем текущее поколение в фоновый массив/матрицу, далее используем вычисление следующего поколения на основе неизменных исходных данных.
.. и еще о производительности - на сколько я помню жизнь, у вас затраты на визуализацию все равно не соизмеримо больше обсчета ;)))
Спасибо за ответ! У меня игра не много попроще. Я ее для себя делаю и для ребенка, для развлечения))) Вряд-ли у меня буду миллионы этих событий. Я как думал. Например, у класса клетка есть поле Сила и метод Съесть. Столкнулись две клетки, произошло событие(на данный момент, это событие возникает в двух эти клетках, что мне не очень нравится), по этому событию вызывается метод Съесть. Та клетка, у которой Силы больше съедает, более слабую и слабая исчезает из списка клеток из с Canvas. А более сильная становится еще сильнее. Что-то типа этого. И клетки встретившись могут подраться, спарится, просто разойтись, слипнуться в многоклеточный организм. Еще что-нибудь. И таких событий событий может быть много одновременно, но до миллионов я уж не буду доводить. Вот я и думаю как их обрабатывать одновременно. При этом получается, что возможны одновременные обращения к списку этих клеток, например, двух клеток одновременно съели и они должны быть удалены из списка, ну это можно сделать асинхронно. Но в это время все остальные пробегаются по этому списку и ищут с кем они пересекаются. Тогда могут быть какие-то коллизии. Одним словом, возникает много нюансов.
ПС. Думаю plinq вполне может подойти запроса по пересечению.
Dima231, любопытно ))
.. ну смотрите:
- все таки надежнее матричный просчет "между поколениями сцены"
- принцип надежности данных прошлого поколения
- принцип НЕконфликта на запись точечной клетки будущего поколения (ранее не упомянул, но это не менее важно)..
- в любом случае, на вскидку, загрузка просчета все равно ничтожна с нагрузкой визуализации (все что под капотом wpf)..
- ну еще измерение.. как тренинг кодинга, почему нет? скорее классный )).. с учетом советов выше )).. и мне все равно видится plinq как наиболее оптимальный вариант для вас.. в случае понимания идеи покадровости поколений .. и исходник, и цель, вполне в рамках функциональной парадигмы.. тогда и plinq на 99% самый интересный инструмент для применения ;))
И клетки встретившись могут подраться, спарится, просто разойтись, слипнуться в многоклеточный организм. Еще что-нибудь. И таких событий событий может быть много одновременно, но до миллионов я уж не буду доводить. Вот я и думаю как их обрабатывать одновременно. При этом получается, что возможны одновременные обращения к списку этих клеток, например, двух клеток одновременно съели и они должны быть удалены из списка, ну это можно сделать асинхронно. Но в это время все остальные пробегаются по этому списку и ищут с кем они пересекаются. Тогда могут быть какие-то коллизии. Одним словом, возникает много нюансов.
.. не внимательно прочитал сразу.. ))
.. НЕТ СПОСОБА принятия решения в мультитаскинге за 2 или более соседних клеток..
поверьте на слово ))
ну или осознайте через умные книги
или методом проб и ошибок ))
.. моя предварительная оценка (не претендую на гуру в конечной инстанции).. но.. возможно вам надо подумать даже о промежуточном слое )))
- "прошлое поколение" => "предварительные решения"
- слой вероятных конфликтов..
- и только уже с промежуточного слоя выхлоп следующего поколения..
самое смешное, что алгоритмически это все матричное.. и несоизмеримо надежнее БЕЗ попыток параллелить.. как то так ))