|
|
Регистрация Восстановить пароль |
Регистрация | Задать вопрос |
Заплачу за решение |
Новые сообщения |
Сообщения за день |
Расширенный поиск |
Правила |
Всё прочитано |
|
|
Опции темы | Поиск в этой теме |
14.04.2016, 19:05 | #1 |
Форумчанин
Регистрация: 06.10.2011
Сообщений: 181
|
Проблема с многопоточностью
Уважаемые форумчане. Помогите решить проблему.
Хочу попробовать написать какой-то простейший аналог рпг. Суть проста. Есть локация, на ней находятся агрессивные и не агрессивные мобы. На данный момент пробую организовать атаку агрессивным мобом неагрессивного. Вот часть наработок, касающихся сего. Код:
Так вот. Проблема в следующем. Когда агрессивный моб подходит к пассивному, то успевает один раз ударить и все. Потом пассивный начинает идти бесконечно, а при отладке получается, что код в метод Thinking() больше не заходит. Может кто подскажет, в чем я не прав. |
15.04.2016, 13:15 | #2 |
Форумчанин
Регистрация: 27.01.2014
Сообщений: 115
|
Давайте блок-схему
Решать вопрос "почему" когда речь идет о коде и каком-то алгоритме можно только тогда, когда у алгоритма есть какое-то оформление. Если у вас кроме кода ничего нет - значит код написан правильно, а вот вы неправильно его интерпретируете Можно зайти с обратной стороны - вы дали кусок кода, я восстановил по нему алгоритм, проверяю - совпадает, задаю вопрос - а что не так? Вы пишите, что не так, но это не соответствует алгоритму, в первую очередь. Хотя бы на псевдокоде напишите, что ли, сидеть разбираться с кодом без эталона вообще никто не будет, я думаю. |
15.04.2016, 14:17 | #3 |
Форумчанин
Регистрация: 06.10.2011
Сообщений: 181
|
Я пытаюсь реализвать стандартную машину состояний. В первом приюлижении, есть перечисление состояний State {Idle; Move; Atack}. Для простоты CastSpell пока не трогаем. В классе моба есть переменная currentState, которая отображает то, чем моб занимается на данный момент.
- Idle - ничего не делает; - Move - двигается; - Atack - наносит физический урон. В методе Thinking() описан алгоритм действий моба. Допустим, он ничем не занят. Тогда у него есть несколько вариантов развития. 1) с шансом в 25% он может прогуляться в соседние координаты в радиусе видимости (переход в состояние Move), в оставшиеся 75% - он останется на месте, и так же продолжит ничего не делать (остается в состоянии Idle). 2) Если он обнаруживает, что в радиусе его видимости есть враг (Target), и враг находится на расстоянии меньшем, чем радиус атаки - то моб начинает его бить. (переходит в состояние Atack) 3)Если он обнаруживает в радиусе видимости врага, но он дальше чем, дальность атаки, то он будет подходить к врагу (переходит в состояние Move). В принципе все логично. Теперь рассмотрим состояние Move. 1) Моб идет, и доходит до координат на которые он двигался, то он заканчивает движение (переходит в состояние Idle). 2) Моб идет, и вдруг увидел врага, но он дальше чем дальность атаки, то начинает приближаться к нему, или вдруг враг переместился на другую координату, то моб меняет конечные координаты своего пути, дабы преследовать врага (остается в Move, но меняет координаты) 3) Моб подходит к врагу на расстояние атаки, и начинает атаковать его (переходит в Atack). Ну и 4 положение - Atack: 1) Если цель умерла, то стоит просто так (переходит в состояние Idle). 2) Если цель выбежала за пределы атаки, начинает преследовать ее (переходит в Move). 3) Если цель стоит в радиусе атаки, то потрошит ее до смерти (остается в состоянии Atack). Вот тут я сейчас глянул, и действительно косяк. У меня нет цикла в Task`е внутри Atack(). Но не суть. Проблема в другом. Получается, что после одного удара у меня Task заканчивается Exception`ом, т.е. пишется строка "{0} stop attack.", но после этого цель начинает все время куда уходить, а моб который его атаковал, остался стоять на месте. Скажу большее. После вызова Exception`а в Atack(), у меня код вообще больше не заходит в Thinking(), как будто главный поток где-то застрял. Добавил картиночку для большей наглядности. P.S. Спасибо большое за помощь. Боялся, что мало кто откликнется, увидев такое большое количество букв. Последний раз редактировалось max_prorok; 15.04.2016 в 15:13. Причина: Дописал благодарность |
15.04.2016, 22:10 | #4 |
Форумчанин
Регистрация: 06.10.2011
Сообщений: 181
|
Кажется нашел проблему. Проблема заключается в следующем. После того, как у меня агрессивный моб подходит к пассивному на расстояние удара, его передвижение в параллельном потоке останавливается (по средством CancellationTokenSource stateStop) и вызывается асинхронный метод Atack(), в котором выполняется Task.Run() до того момента, пока цель не умрет, или пока не будет отмены с помощью все того же stateStop. Только вот в нем в свойстве IsCancellationRequest уже стоит true, и получается, что как только код заходит в Task.Run(), то тут же выходит с Exception`ом. Можно ли как-нибудь поменять это значение, кроме как убиения токена и заново вызывать его конструктор?
|
22.04.2016, 14:08 | #5 |
Участник клуба
Регистрация: 04.04.2010
Сообщений: 1,554
|
А нафига тебе параллельные потоки? 0_0
Делай всё в одном. |
22.04.2016, 14:41 | #6 |
Форумчанин
Регистрация: 06.10.2011
Сообщений: 181
|
Эт как же так??? Представь, есть у тебя 10 локаций, на каждой по 50 мобов. И что? Пока один моб не пройдет три клетки на какой-нибудь локации, все другие будут стоять мясом? Или другой вариант. Ты подходишь, начинаешь бить моба, он начинает бить в ответ. А вокруг все остальные мобы просто стоят в сторонке и смотрят бой не на жизнь, а на смерть. И видимо ставки делают, кто кого убьет в конце концов.
|
22.04.2016, 15:11 | #7 |
Участник клуба
Регистрация: 04.04.2010
Сообщений: 1,554
|
max_prorok В квейк 2 играл? Он в одном потоке работает.
1. Считываешь инпут. 2. Просчитываешь для всех мобов поведение. 3. Двигаешь их. И по кругу. А треды тяжёлые, и не предсказуемые. Фиг знает когда и какому треду и в какой момент ОС передаст управление. |
22.04.2016, 16:55 | #8 |
Форумчанин
Регистрация: 06.10.2011
Сообщений: 181
|
Тогда не совсем понятно, как контролировать время... Чтобы мобы не портались по локации???
|
22.04.2016, 17:04 | #9 | |
Старожил
Регистрация: 28.01.2009
Сообщений: 21,000
|
Цитата:
часто это 60 раз в секунду, dt=1sec/60. сейчас в некоторых играх разделяют эти понятия(FPS и UPS) явно. в вашем случае у вас сервер же? в любом случае внутри локации параллельность не хорошо. больше потеряете на синхронизации. Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел. Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите. |
|
22.06.2016, 12:05 | #10 |
Форумчанин
Регистрация: 06.10.2011
Сообщений: 181
|
Прошу прощения, что поднимаю старую и забытую тему.
Но что-то я не могу допереть до конца как реализовать UPS. Точнее я понял, как его реализовать, но не понял как потом наложить действия. Т.е. после создания локации запускаем (псевдо)бесконечный цикл, в котором: 1. Каждый моб (персонаж пока не трогаем) думает, и если что, меняет свой статус. 2. В зависимости от статуса, он либо продолжает делать то, что делал, либо начинает новое действо. Но вот вопрос по поводу пункта 2. Локация разделена на клетки (скажем 200х200). Скажем, на переход с одной клетки на другую мобу необходимо потратить 400 мс. А при атаке задержка между ударами составляет 200 мс. Как это чудо организовать в одном потоке. Добавлять в класс моба какой-то счетчик (если конечно таковой имеется)? Или может вернее сделать это как-то на событиях? Только подпните меня в нужном направлении. Очень хочется именно самому допереть до конца, а не взять готовый кусок и скопи-пастить его. |
|
Похожие темы | ||||
Тема | Автор | Раздел | Ответов | Последнее сообщение |
Снова я и снова геморрой, только уже с многопоточностью | FleXik | Общие вопросы Delphi | 26 | 07.07.2013 16:48 |
Неблокирующий сокет Си проблема с закрытием, проблема с закрытием сокетов в цикле | mnx_vol | C/C++ Сетевое программирование | 0 | 06.11.2012 13:57 |
нужно разобраться с многопоточностью с ThRead Object | Толян1 | C++ Builder | 1 | 16.07.2012 09:52 |
Проблема с многопоточностью | Kapitan4ik | Работа с сетью в Delphi | 3 | 29.02.2012 21:46 |