Алгоритм для клиент-серверных игр
Для автономных игр основной игровой цикл (источник: wikipedia)
while( user doesn't exit )
check for user input
run AI
move enemies
resolve collisions
draw graphics
play sounds
end while
Но что, если я разрабатываю клиент-серверные игры, такие как Quake, Ragnarock, Trackmania и т.д.,
Что такое Loop/Algorithm для клиентских и серверных частей игры?
Ответы
Ответ 1
Это будет что-то вроде
Клиент:
while( user does not exit )
check for user input
send commands to the server
receive updates about the game from the server
draw graphics
play sounds
end
Сервер:
while( true )
check for client commands
run AI
move all entities
resolve collisions
send updates about the game to the clients
end
Ответ 2
Клиент:
connect to server
while( user does not exit && connection live)
check for user input
send commands to the server
estimate outcome and update world data with 'best guess'
draw graphics
play sounds
receive updates about the game from the server
correct any errors in world data
draw graphics
play sounds
end
Сервер:
while( true )
check for and handle new player connections
check for client commands
sanity check client commands
run AI
move all entities
resolve collisions
sanity check world data
send updates about the game to the clients
handle client disconnects
end
Проверка работоспособности клиентских команд и мировых данных заключается в устранении любых "невозможных" ситуаций, вызванных либо преднамеренным обманом (слишком быстрым движением, через стены и т.д.), либо задержкой (через дверь, которую клиент считает открытой, но сервер знает, что закрыт и т.д.).
Чтобы обрабатывать задержку между клиентом и сервером, клиент должен наилучшим образом догадаться о том, что будет дальше (используя его текущие мировые данные и клиентские команды). Затем клиенту придется обрабатывать любые несоответствия между тем, что оно предсказанное произойдет, и то, что сервер позже сказал, на самом деле произошло. Обычно это будет достаточно близко, чтобы игрок не заметил разницы - но если отставание значимо, или клиент и сервер не синхронизированы (например, из-за обмана), тогда клиенту потребуется сделать резкую коррекцию, когда он получает данные с сервера.
Также существует множество проблем, связанных с разделением разделов этих процессов на отдельные потоки для оптимизации времени отклика.
Один из лучших способов начать - захватить SDK из одной из игр с активным сообществом моддинга - вникая в то, как это работает, даст хороший обзор того, как это должно быть сделано.
Ответ 3
Это действительно не простая проблема. На самом базовом уровне вы можете сказать, что сеть предоставляет те же данные, что и элемент MoveEnemies в исходном цикле. Поэтому вы можете просто заменить свой цикл:
while( user doesn't exit )
check for user input
run AI
send location to server
get locations from server
resolve collisions
draw graphics
play sounds
end while
Однако вам нужно учитывать задержку, поэтому вы не хотите приостанавливать свой основной цикл вызовами в сети. Чтобы преодолеть это, нет ничего необычного в том, что сетевой движок сидит во втором потоке, опроса для данных с сервера как можно быстрее и размещения новых местоположений объектов в пространстве общей памяти:
while(connectedToNetwork)
Read player location
Post player location to server
Read enemy locations from server
Post enemy locations into shared memory
Тогда ваш основной цикл будет выглядеть так:
while( user doesn't exit )
check for user input
run AI
read/write shared memory
resolve collisions
draw graphics
play sounds
end while
Преимущество этого метода заключается в том, что ваш игровой цикл будет работать как можно быстрее, но информация с сервера будет обновляться только после завершения полной записи на сервер и с сервера. Конечно, у вас теперь есть проблемы с совместным использованием объектов по потокам и потерей с помощью блокировок и т.д., Которые поставляются вместе с ним.
На стороне сервера цикл одинаков, есть одно соединение для каждого игрока (нередко каждый игрок также находится в отдельном потоке, чтобы латентность одного не повлияла на остальных) для каждого соединения, которое оно будет запускать петля вроде
while (PlayerConnected)
Wait for player to post location
Place new location in shared memory
Когда клиентская машина запрашивает местоположение врагов, сервер считывает все остальные местоположения игроков из общего блока памяти и отправляет их обратно.
Это чрезвычайно упрощенный обзор, и есть много других настроек, которые повысят производительность (например, может быть, стоит сервер, отправляющий позиции противника клиенту, а не клиент, запрашивающий их), и вам нужно решить, где определенные логические принимаются решения (решает ли клиент, был ли он застрелен, потому что у него самая последняя позиция для себя или сервер, чтобы прекратить обман)
Ответ 4
Клиентская часть в основном такая же, за исключением замены
run AI
move enemies
resolve collisions
с
upload client data to server
download server updates
И сервер просто делает:
while (game is running)
{
get all clients data
run AI
resolve collisions
udpate all clients
}
Ответ 5
Вы можете использовать почти то же самое, но большинство из вас будет на сервере, вы можете поместить в клиентское приложение таймеры, звуки, графику и другие компоненты пользовательского интерфейса.
Любое бизнес-правило (AI, Movements) идет на стороне сервера.
Ответ 6
Очень полезно, и я хотел бы утверждать, что следующая статья: Архитектура клиент-сервер
Я прочитал его и многому научился, было много смысла. Разделив свою игру на стратегически определенные компоненты или слои, вы можете создать более удобную архитектуру. Программа легче кодировать и более надежную, чем обычная линейная программная модель, подобная той, которую вы описали.
Этот мыслительный процесс появился в предыдущем сообщении здесь об использовании "общей памяти" для разговора между различными частями программы и, таким образом, преодоления ограничений, связанных с одной нитью и логикой шага за шагом.
Вы можете потратить месяцы на идеальную архитектуру и поток программ, прочитать одну бумагу и понять, что вы лаяли неправильное дерево.
TL;DR; прочитайте его.