Пятница, 29 Ноября 2024, 17:00

Приветствую Вас Гость

[ Новые сообщения · Игроделы · Правила · Поиск ]
  • Страница 1 из 1
  • 1
Результаты поиска
NanotentacleДата: Среда, 12 Февраля 2014, 09:32 | Сообщение # 1 | Тема: Ищу художника, геймдизайнера
был не раз
Сейчас нет на сайте
Добрый день
Некоторое время веду разработку игры для социальной сети. Игра представляет из себя пошаговую стратегию в стиле настольной игры Battletech (известной по играм Mechwarrior), правда, с достаточно сильно переработанной идеей.

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

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

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

Заинтересованным готов провести экскурсию по "преальфа" версии игры.

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

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



Сообщение отредактировал Nanotentacle - Среда, 12 Февраля 2014, 11:04
NanotentacleДата: Среда, 04 Сентября 2013, 19:20 | Сообщение # 2 | Тема: Требуется гейм-дизайнер
был не раз
Сейчас нет на сайте
Итак, имеются планы на пошаговую стратегию, которая будет размещена в социальных сетях. Пока что над проектом я работаю в одиночку, на данный момент уже есть скелет игры, частично готов сервер и база данных. Ураганную скорость разработки обеспечить я не в состоянии, предупреждаю сразу. Работы, конечно, осталось много, но начинаю ощущать, что требуется помощь в гейм-дизайне, так как не всегда хватает времени и возможности обдумать все детали игры.

Что требуется от геймдизайнера:
1. Хорошо отвечать на вопросы "Зачем?", "Почему?", "Как?" и тому подобные.
2. Опыт не обязателен, но приветствуется.
3. Очень желательно наличие опыта и хотя бы поверхностное знакомство с настольными варгеймами, такими как Warhammer и Battletech.

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

NanotentacleДата: Среда, 26 Июня 2013, 17:54 | Сообщение # 3 | Тема: Обратится к свойству объекта на другой форме
был не раз
Сейчас нет на сайте
А какую именно ошибку выдает? Access violation? Если да, то надо смотреть, как и в какой момент у тебя создается CheckBox1
NanotentacleДата: Пятница, 28 Декабря 2012, 14:03 | Сообщение # 4 | Тема: Delphi:Вопрос-Ответ
был не раз
Сейчас нет на сайте
Там именно a := random(2000). Перед всеми рандомами стоит randomize.

Я и раньше замечал, что с помощью рандома не получается делать случайные события. Допустим, после x := random(100) все попытки разделить вероятности, например, по 20 путем
if x <= 20
if (x > 20) and(x <=40)
ни к чему не приводило, приходилось подбирать некие коэффициенты, чтобы получать те самые 20 процентов, которые мне требовались. Возможно, дело в том, что у меня не 10 миллионов итераций, а порядка 100-1000.


Сообщение отредактировал Nanotentacle - Пятница, 28 Декабря 2012, 14:08
NanotentacleДата: Пятница, 28 Декабря 2012, 09:15 | Сообщение # 5 | Тема: Delphi:Вопрос-Ответ
был не раз
Сейчас нет на сайте
Да, сейчас проверил собственноручно, вы правы. Но тогда возникает вопрос: в моей программе при создании объекта вычисляется случайная величина, и каждый раз она оказывается как раз в промежутке 1700-2000. Не было ни одного случая, чтобы значение оказывалось меньше 1700. С чем такое может быть связано?
NanotentacleДата: Четверг, 27 Декабря 2012, 06:59 | Сообщение # 6 | Тема: Delphi:Вопрос-Ответ
был не раз
Сейчас нет на сайте
Встроенный в Delphi 7 генератор случайных чисел дает достаточно кучный результат. Если мне надо получить случайное число из диапазона 0-2000, то с вероятностью в 95% эти числа попадают в промежуток 1700-2000 (randomize используется, если что). Есть ли более "случайные" генераторы для Делфи или лучше написать его самостоятельно?

Сообщение отредактировал Nanotentacle - Четверг, 27 Декабря 2012, 06:59
NanotentacleДата: Четверг, 13 Декабря 2012, 12:43 | Сообщение # 7 | Тема: Delphi:Вопрос-Ответ
был не раз
Сейчас нет на сайте
Возникла необходимость поработать с указателями(pointer) и хотелось бы узнать, как делать правильно. Ситуация такова: имеется динамический массив данных. При удалении элемента не из конца массива происходит смещение всех элементов на один в сторону уменьшения путем простого присвоения. Т.е., в моем понимании, происходит копирование элемента в новую "ячейку" оперативной памяти, а старая "ячейка" затирается данными от следующего элемента. При такой операции расположение в памяти меняется, и указатели, которые были расставлены ранее, уже ведут в лучшем случае не к требующемуся элементу.
Внимание, вопрос: правильно ли я понимаю ситуацию с указателями, и если да, то есть ли возможность присвоить переменной не значение, а адрес в памяти?

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

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

SOLVED: Все решено. В моем случае, после каждого изменения внутри массива буду переписывать связанные с ними указатели. Единственный вариант, на мой взгляд.


Сообщение отредактировал Nanotentacle - Четверг, 13 Декабря 2012, 14:25
NanotentacleДата: Вторник, 11 Декабря 2012, 11:21 | Сообщение # 8 | Тема: Free Pascal: проеверка с 2-мя вариантами
был не раз
Сейчас нет на сайте
В данном случае case неприменим. Он не работает со String. "Ordinal expression expected" - если не вдаваясь в буквоедческий перевод, то он требует, чтобы переменная была исчислимого типа. Т.е., например, integer, каждый элемент которого можно последовательно посчитать (один, два, три и т.д.). В данном примере придется обойтись конструкцией if - then.
NanotentacleДата: Воскресенье, 09 Декабря 2012, 10:16 | Сообщение # 9 | Тема: Delphi:Вопрос-Ответ
был не раз
Сейчас нет на сайте
Если не ошибаюсь, то движок - это все же набор классов, иногда и компонентов, которые позволяют любому программисту создавать игры, не вникая в суть того же DirectX или OpenGL, пользуясь лишь методами уже созданных классов. По сути же, если глядеть в глубину любого движка, то чаще всего они как раз и представляют собой те самые DirectX и\или OpenGL. По сути, как для приятной и комфортной езды на автомобиле не требуется знать, как работает двигатель внутреннего сгорания, так обстоит дело и тут. Не стоит только забывать, что если не умеешь рулить и выбирать скорость в поворотах, то это закончится плачевно.

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

Сам я начинал создание игр сначала с простого - DelphiX, потом мне стало нехватать функционала и я попробовал Andorra2D. Жаль, что оба этих движка приказали долго жить. В общем-то, если преследуешь целью только сделать игру, а не движок, то я бы рекомендовал поискать что-то подобное.
NanotentacleДата: Четверг, 29 Ноября 2012, 15:53 | Сообщение # 10 | Тема: Создание сервера на Delphi
был не раз
Сейчас нет на сайте
Успехи пока что меня вдохновляют :). Бота почти дописал, скоро начну тесты. Дополнительно продолжил искать возможные подводные камни, о которых сразу не подумал. Про динамические списки - это великолепно, я подумаю, как их можно применить в моем случае. На самом деле, о таком простом и элегантном способе я и не думал. Дополнительно мне посоветовали почитать про хэш-списки, тоже сейчас вникаю и разбираюсь, как они могут мне помочь.

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

Итак, хотелось бы отписаться о программе-боте и небольшом изменении сетевого движка. Программа-бот будет представлять собой динамически создаваемые ClientSocket, их кол-во зависит от моих потребностей. Каждый бот-клиент присоединится к серверу, и будет совершать действия, похожие на действия игрока - давать команды на перемещения, на стрельбу, в идеале - умирать и воскрешаться. Зная структуру запросов к серверу, ничего сложного здесь нет. Хватит всего лишь задать обработку пары-тройки случайных событий.

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

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

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

А вот что делать с выстрелом я пока не придумал. На данный момент обсчет выстрела, столкновения, взрыва и повреждений ведет сервер, сообщая об этих события клиенту. Но система, как я и писал выше, нежизнеспособна. Видимо, придется доверить клиенту обсчет и этих вещей. Хотя обсчет повреждений я намерен оставить серверу, даже если информация будет приходить с задержкой. Я очень надеюсь, что мне удастся сделать так, что столкновения снаряда и игрока и на сервере, и на клиенте будут максимально приближены друг к другу и тогда ситуации, когда клиент показывает игроку, что он попал и повредил соперника, а сервер это не подтверждает, будут крайне редки.
Возможно, есть более элегантные способы?

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

Update:
После полунедельного затишья продолжил работу. Сейчас, как и хотел, переписал сервер и привел его в более удобный вид. Начал оптимизировать с самого начала - например, определился с необходимыми типами данных, чтобы не было лишнего выделения памяти. Как результат - сервер начал есть в два раза меньше оперативной памяти, а код выглядит более строго и "архитектурно". Последовал совету TimKruz и уменьшил код запроса до одного символа. На данный момент хватает за глаза.

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

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

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


Сообщение отредактировал Nanotentacle - Пятница, 14 Декабря 2012, 14:21
NanotentacleДата: Понедельник, 26 Ноября 2012, 09:49 | Сообщение # 11 | Тема: Создание сервера на Delphi
был не раз
Сейчас нет на сайте
Большое спасибо за ответ, был приятно удивлен.

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


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

Quote (TimKruz)
Вот запросы нужно сильно оптимизировать. Чтобы не слать огромные структуры с кучей мусора каждую миллисекунду. Только самое важное, только в свёрнутом виде. Просто интересно узнать формат запросов. В идеале это должно представлять собой строго определённый код, где каждый байт имеет своё имя и назначение. А то я где-то тут видел, как кто-то шлёт огромные XML-файлы с информацией, которую можно сжать в пару десятков байт.


Средний запрос у меня стандартизирован. Первые три байта - код команды или запроса, затем "тело" запроса с данными, со строгим размером данных. Например, при перемещении передается только четыре вектора направления в булевых переменных. Для передачи использую один байт, который передается в виде числа в шестнадцатеричной системе. Если же есть изменения в направлении (например, игрок нажал или отпустил кнопку), то передается еще две координаты положения, по 6 байт в каждой координате. Учитывая, что целая часть будет не больше 4х симоволов, точность получается приемлимая. Правда, как там ужать данные пока не сообразил и, честно говоря, не сильно и обдумывал, оставив на потом. Оптимизация - это для меня вопрос серьезный, но который я пока решил оставить до полного написания сервера.

Quote (TimKruz)
Переменная типа Boolean занимает 1 байт (потому что меньше нельзя, адресуются только байты), но значение имеет только один бит. Используй битовый сдвиг. Если, например, используется 8 булевых переменных, их можно свернуть в один байт битовым сдвигом, а потом снова развернуть (для удобства использования). Но если используешь 7 булевых переменных, по-любому останется 1 "лишний" бит, который никуда не используешь, если все остальные данные занимают целые байты. Однако есть ли смысл задумываться о каком-то лишнем бите, когда скорости передачи данных гораздо быстрее?


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

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


На данный момент как раз пишу такую программу-бота. Единственно чего опасаюсь - что мои иллюзии о том, что код написан хорошо, являются лишь иллюзиями :).

Quote (TimKruz)
Не понимаю смысла многопоточности в таких ситуациях. Всё равно реально процессор параллельно обрабатывает столько инструкций, сколько у него ядер, т.е. для двухъядерного процессора реальный прирост скорости может быть только от двух параллельных потоков вместо одного, который выполняет функции этих двух, но подряд. А потоки ещё нужно синхронизировать с ядром программы и вообще контролировать, так что проще без них...


А вот тут вопрос спорный. Если я не ошибаюсь, то вопрос идет даже не в том, что они должны выполняться параллельно, а в процессорном времени. Все дальше написанное - это то, как я понимаю многопоточность. Поток, сам по себе, представляет собой программу в программе. Поэтому процессорное время выделенное на программу в общем, при применении потоков, увеличивается. Плюс, в моем исполнении один поток отрабатывает свой цикл просчетов, и после этого уходить в sleep на 30 мс, тем самым освобождая процессорное время соседнему потоку. С синхронизацией все проще. Я сейчас воплощаю систему, где основной поток и остальные потоки не используют совместных переменных, чтобы полностью избежать подвисаний и проблем. Хотя вплотную я этим вопросом не занимался, и могу ошибаться. В любом случае, попробовать на практике это стоит :).
NanotentacleДата: Среда, 21 Ноября 2012, 12:58 | Сообщение # 12 | Тема: Выбор движка\конструктора для онл.игры
был не раз
Сейчас нет на сайте
Я немного перефразирую aalla: вопрос создания игр - это не просто поиск движка и втыкивание в него своих картинок, зачастую (и я пока не встречал исключений) это трудная работа по написанию скриптов, создания полного дизайна игры и прочих крупных и мелких деталей. В любом случае, ты уже должен представлять, что такое алгоритм и обладать навыками составления этих самых алгоритмов.

Флеш - это уже язык программирования, а не движок (ну, вернее, as3 точно им является, голый флеш мало кому нужен). В общем-то, если ты собираешься писать онлайн игру, то этого будет недостаточно. Ты на нем сможешь написать только клиент. Поэтому куда полезнее будет для начала поизучать вопросы попроще, и сделать свой "Hello, world".

Ну а в дальнейшем можно почитать тут: http://gcup.ru/forum/47-2030-1


Сообщение отредактировал Nanotentacle - Среда, 21 Ноября 2012, 13:00
NanotentacleДата: Среда, 21 Ноября 2012, 10:13 | Сообщение # 13 | Тема: Создание сервера на Delphi
был не раз
Сейчас нет на сайте
Здравствуйте, уважаемые форумчане.

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

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

Возможно, этот текст поможет кому-нибудь быстрее пройти тот путь, и не отказаться от своих мечтаний. Итак, приступим.

Работать я начал с Delphi 7, как наиболее знакомой и обеспечивающей, на данном этапе, достаточные возможности. Первым делом я определился, что хочу получить в результате: это была обычная флеш-игра (про клиент я пока ничего говорить не буду, так как не по теме, затрону только разработку серверной части), игроки могут присоединяться в игровые комнаты и вести там сражения. Максимум - 8 игроков в одной комнате. Соответственно, надо было создать классы для игрока, и для комнаты. Чтобы избежать задержек, обусловленных динамическими массивами, в основном модуле создавался массив для игроков на 1000 человек, и массив комнат на 100 комнат. Да, вполне вероятно, что это будет занимать больше оперативной памяти, но для меня на данном этапе это не сильно критично (кстати, если кто-то в курсе, подскажите, насколько это станет критичным при больших нагрузках?). Обслуживать все подключения, по первоначальному плану, должен был единственный ServerSocket, прослушивающий один порт. Само приложение хотел сделать однопоточным. Увы, в таком виде это было нежизнеспособно.

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

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

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

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

А вот "бутылочное горлышко" дало о себе знать. Во-первых, я попытался работать напрямую с массивом игроков и комнат из потока, а во-вторых, я попытался отправлять сообщения клиентам прямо из потока, используя наш один-единственный сервер на одном единственном порту. Даже при 6ти игроках весь сервер начинало колбасить и передвижения игроков стали больше походить на пошаговую стратегию. Временным (потому как трудно предположить, что будет при большой загрузке), и на данный момент действующим, решением стало:

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

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

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

4) Слегка оптимизировал запросы. Ранее клиент каждый обработанный фрейм (а при 50 фпс это 50 сообщений в секунду) отправлял информацию о направлении перемещения, координатах. Теперь же отправка идет исключительно при изменении направления движения. Сервер считает перемещение, и при изменениях выдает координаты игрока, где он должен находиться. В общем-то, удалось "синхронизировать" клиент и сервер по скоростям так, что отправлять клиенту его положение в каждый фрейм нет необходимости.

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

На данный момент сервер без труда держит 8 игроков, загружая процессор не более 1% при заполненной комнате (учитывая, что процессор тут отнюдь не самый мощный). Мне пока очень трудно предсказать, как же игра поведет себя не в лабораторных условиях, но радует, что пока все выглядит оптимистично и мне интересно работать над проектом, узнавать новые вещи и решать сложившиеся трудности.

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


Сообщение отредактировал Nanotentacle - Среда, 21 Ноября 2012, 10:24
  • Страница 1 из 1
  • 1
Поиск:

Все права сохранены. GcUp.ru © 2008-2024 Рейтинг