Разработка алгоритма
В начале игры нужно должным образом распределить игроков по командам.
В отличие от игр с симметричным распределением по командам, где игроки делятся поровну, ассиметричное распределение означает, что количество игроков в каждой команде будет относительным. Иначе говоря, игроки должны распределяться в относительных соотношениях.
К примеру, может потребоваться, чтобы в одной команде всегда было вдвое больше игроков, чем в другой. По мере присоединения игроков вам нужно перераспределять игроков по командам так, чтобы поддерживать это соотношение. В режимах игры, где одна команда более сильная или обладает способностями, отличающимися от способностей другой команды, асимметричное распределение обеспечивает более сбалансированный игровой процесс за счёт разумного распределения игроков по командам.
В этом примере нужно обеспечить, чтобы в командах с большим максимальным количеством игроков (в данном случае в команде защитников) всегда было больше игроков, чем в командах с меньшим максимальным количеством (например, в команде захватчиков).
Для надлежащего распределения игроков нужно включать каждого игрока в команду с наибольшей разницей относительно максимально возможного количества игроков в этой команде.
Для этого при появлении каждого нового игрока вам нужно будет проверять каждую команду и хранить ссылку как на максимальное, так и на текущее количество игроков в этой команде, а также на команду, в которую нужно назначить этого игрока. Чтобы получить разницу относительно максимального количества, нужно вычесть максимальное количество игроков из текущего количества. Когда вы найдёте команду с наибольшей разницей, нужно будет включить игрока в эту команду.
Перебрав все команды, вы гарантируете, что найдёте команду с наибольшей разницей.
Реализация алгоритма
На этом шаге описано, как ассиметрично распределить игроков по командам в начале игры.
- Добавьте новый метод
BalanceTeams()
в классtriad_infiltration_game
. Этот метод позволит назначить игрока в команду с наибольшей разницей относительно максимального количества игроков.# Распределить всех игроков по всем командам в игре BalanceTeams():void= Logger.Print("Начинаем выравнивать состав команд")
- Настройте получение всех игроков в игре и сохранение их в массиве переменных
AllPlayers
. Затем перемешайтеAllPlayers
. Это позволит сделать так, чтобы все игроки были назначены в команды случайным образом, а не в порядке, в котором они присоединились к игре.# Распределить всех игроков по всем командам в игре BalanceTeams():void= Logger.Print("Начинаем выравнивать состав команд") var AllPlayers:[]player := GetPlayspace().GetPlayers() set AllPlayers = Shuffle(AllPlayers)
- Теперь нужно перебрать всех игроков и назначить их в команду с наибольшей разницей относительно максимального количества игроков. Это можно сделать с помощью вспомогательной функции
FindTeamWithLargestDifference()
, которую вы создадите на следующем шаге, но сначала инициализируйте переменную типа option с именемTeamToAssign
, где будет хранится команда для назначения игрока, и присвойте ей значение, возвращаемоеFindTeamWithLargestDifference()
.for (TeamPlayer:AllPlayers): var TeamToAssign:?team = false set TeamToAssign = FindTeamWithLargestDifference()
- В определении класса
triad_infiltration_game
создайте функциюFindTeamWithLargestDifference()
. Эта функция находит команду с наибольшей разницей в количестве игроков относительно максимально возможного и возвращает значение option типаteam
. Возвращаемая переменнаяteam
должна иметь типoption
, чтобы исключить перевод игрока в другую команду, когда он уже находится в команде с наибольшей разницей.# Найти команду с наибольшей разницей в количестве игроков относительно # максимального количества игроков FindTeamWithLargestDifference():?team = Logger.Print("Пытаемся найти самую маленькую команду")
- Инициализируйте опциональную переменную типа команды с именем
TeamToAssign
, которая будет хранить ссылку на команду с наибольшей разницей в игроках, и целочисленную переменнуюLargestDifference
для отслеживания этой разницы.# Найти команду с наибольшей разницей в количестве игроков относительно # максимального количества игроков. FindTeamWithLargestDifference():?team = Logger.Print("Пытаемся найти самую маленькую команду") var TeamToAssign:?team = false var LargestDifference:int = 0
- Теперь пройдитесь по списку команд и получите как текущее, так и максимальное количество игроков в команде.
var TeamToAssign:?team = false var LargestDifference:int = 0 for: CandidateTeam:Teams CurrentTeamSize := GetPlayspace().GetTeamCollection().GetAgents[CandidateTeam].Length MaximumTeamSize := TeamsAndTotals[CandidateTeam]
- Рассчитайте для каждой команды
DifferenceFromMaximum
— разницу между максимальным и текущим количеством игроков в команде. Если разница больше, чемLargestDifference
, присвойте переменнойLargestDifference
значениеDifferenceFromMaximum
и поместитеTeamToAssign
вoption
.for: CandidateTeam:Teams CurrentTeamSize := GetPlayspace().GetTeamCollection().GetAgents[CandidateTeam].Length MaximumTeamSize := TeamsAndTotals[CandidateTeam] do: Logger.Print("Проверяем команду…") Logger.Print("Максимальное количество игроков в этой команде: {MaximumTeamSize}") DifferenceFromMaximum := MaximumTeamSize - CurrentTeamSize Logger.Print("Разница относительно максимального количества составляет {DifferenceFromMaximum}") if(LargestDifference < DifferenceFromMaximum): set LargestDifference = DifferenceFromMaximum set TeamToAssign = option{CandidateTeam} Logger.Print("Найдена команда с количеством игроков меньше максимального на {DifferenceFromMaximum}")
- Наконец, задайте возврат
TeamToAssign
. Теперь ваш кодFindTeamWithLargestDifference()
должен выглядеть так:# Найти команду с наибольшей разницей в количестве игроков относительно # максимального количества игроков. FindTeamWithLargestDifference():?team = Logger.Print("Пытаемся найти самую маленькую команду") var TeamToAssign:?team = false var LargestDifference:int = 0 for: CandidateTeam:Teams CurrentTeamSize := GetPlayspace().GetTeamCollection().GetAgents[CandidateTeam].Length MaximumTeamSize := TeamsAndTotals[CandidateTeam] do: Logger.Print("Проверяем команду…") Logger.Print("Максимальное количество игроков в команде {CandidateTeamIndex + 1} = {MaximumTeamSize}") DifferenceFromMaximum := MaximumTeamSize - CurrentTeamSize Logger.Print("Разница относительно максимального количества: {DifferenceFromMaximum}") if(LargestDifference < DifferenceFromMaximum): set LargestDifference = DifferenceFromMaximum set TeamToAssign = option{CandidateTeam} Logger.Print("Найдена команда с количеством игроков меньше максимального на {DifferenceFromMaximum}") return TeamToAssign
- Вернитесь в
BalanceTeams()
и назначьте игрока в новую команду с помощью функцииFortTeamCollection.AddToTeam[]
. Если назначение не удастся, значит, игрок уже в самой маленькой команде.var TeamToAssign:?team = false set TeamToAssign = FindTeamWithLargestDifference() if (AssignedTeam := TeamToAssign?, FortTeamCollection.AddToTeam[TeamPlayer, AssignedTeam]): Logger.Print("Пытаемся назначить игрока в новую команду")
- Ваша функция
BalanceTeams()
должна выглядеть следующим образом:# Распределить всех игроков по всем командам в игре BalanceTeams():void= Logger.Print("Начинаем выравнивать состав команд") var AllPlayers:[]player := GetPlayspace().GetPlayers() set AllPlayers = Shuffle(AllPlayers) Logger.Print("Длина AllPlayers составляет {AllPlayers.Length}") for (TeamPlayer:AllPlayers): var TeamToAssign:?team = false set TeamToAssign = FindTeamWithLargestDifference() if (AssignedTeam := TeamToAssign?, FortTeamCollection.AddToTeam[TeamPlayer, AssignedTeam]): Logger.Print("Игрок назначен в новую команду")
Телепортация игроков в зоны появления
Даже при условии, что игроки окажутся в команде с наибольшей разницей, они могут появиться в неверном месте. Всё потому, что игроки появляются до распределения в новую команду. Чтобы это исправить, нужно создать новую функцию, которая будет телепортировать игроков в зону появления после распределения по командам.
- В определении класса
triad_infiltration_game
создайте функциюTeleportPlayersToStartLocations()
. Эта функция будет телепортировать игроков в зону появления их команд после завершения распределения.# Телепортирует игроков в зону появления их команды после завершения выравнивания состава команд. TeleportPlayersToStartLocations():void= Logger.Print("Телепортируем игроков в начальные точки")
- В цикле
for
переберите все команды в массивеTeams
, получив индекс каждой команды и сохранив его в переменнойTeamIndex
.# Телепортирует игроков в зону появления их команды после завершения выравнивания состава команд. TeleportPlayersToStartLocations():void= Logger.Print("Телепортируем игроков в начальные точки") for: TeamIndex -> PlayerTeam:Teams
- Задайте получение игроков в
PlayerTeam
с помощью вызоваGetAgents[]
с аргументомPlayerTeam
. Затем задайте получение телепорта, связанного с этой командой, указав индексTeamIndex
в массивеTeleporters
, и сохраните его в переменнойTeamTeleporter
. Сохраните преобразование этого телепорта в переменнойTransform
.# Телепортирует игроков в зону появления их команды после завершения выравнивания состава команд. TeleportPlayersToStartLocations():void= Logger.Print("Телепортируем игроков в начальные точки") for: TeamIndex -> PlayerTeam:Teams TeamPlayers := GetPlayspace().GetTeamCollection().GetAgents[PlayerTeam] TeamTeleporter := Teleporters[TeamIndex] Transform := TeamTeleporter.GetTransform()
Порядок команд в
Teams
должен совпадать с порядком телепортов вTeleporters
. Если захватчики — это команда 1, то первый телепорт вTeleporters
должен быть назначен для захватчиков. Дважды проверьте эти значения в редакторе. - Во втором цикле
for
переберите всех игроков вTeamPlayers
и возродите их с помощью функцииRespawn()
в месте, соответствующем преобразованию телепорта, используя перенос и поворот изTransform
. Ваша функцияTeleportPlayersToStartLocations()
должна выглядеть следующим образом:# Телепортирует игроков в зону появления их команды после завершения выравнивания состава команд. TeleportPlayersToStartLocations():void= Logger.Print("Телепортируем игроков в начальные точки") for: TeamIndex -> PlayerTeam:Teams TeamPlayers := GetPlayspace().GetTeamCollection().GetAgents[PlayerTeam] TeamTeleporter := Teleporters[TeamIndex] Transform := TeamTeleporter.GetTransform() do: for(TeamPlayer:TeamPlayers): TeamPlayer.Respawn(Transform.Translation, Transform.Rotation) Logger.Print("Этот игрок телепортирован в начальную точку")
- Добавьте вызов
BalanceTeams()
в функциюOnBegin()
после перемешиванияAllPlayers
. Так мы обеспечим распределение игроков в случайном порядке, т. е. игроки не будут попадать каждый раз в одну и ту же команду. После этого телепортируйте игроков в начальные позиции, вызвавTeleportPlayersToStartLocations()
.OnBegin<override>()<suspends> : void = # Получить все команды set Teams = GetPlayspace().GetTeamCollection().GetTeams() # Сохранить команды для последующего обращения set MaybeInfiltrators = option{Teams[0]} set MaybeAttackers = option{Teams[1]} set MaybeDefenders = option{Teams[2]} if: Infiltrators := MaybeInfiltrators? Attackers := MaybeAttackers? Defenders := MaybeDefenders? Logger.Print("Найдены все три команды") set TeamsAndTotals[Infiltrators] = MaximumInfiltrators set TeamsAndTotals[Attackers] = MaximumAttackers set TeamsAndTotals[Defenders] = MaximumDefenders Logger.Print("Все три команды заданы в TeamsAndTotals") then: BalanceTeams() TeleportPlayersToStartLocations() else: Logger.Print("Не удаётся найти все команды. Убедитесь, что вы задали правильные команды в настройках острова.")
-
Сохраните сценарий, скомпилируйте его и нажмите Запуск сеанса на панели инструментов UEFN, чтобы протестировать уровень в игре. Во время игрового теста уровня каждый игрок должен попасть в команду с наибольшей разницей и появиться в зоне появления этой команды. Проверьте это по записям в журнале. Вы можете настроить максимальное количество игроков в команде в
triad_infiltration_game
, чтобы протестировать эту функциональность, когда количество игроков меньше максимального. Например, при тестировании с одним игроком попробуйте задать такое максимальное количество игроков в команде, в которую вы хотите попасть, которое будет больше, чем в двух других командах. Если вы хотите попасть в команду атакующих, увеличьтеMaximumAttackers
. Если вы хотите попасть в команду захватчиков, увеличьтеMaximumInfiltrators
.
Что дальше
Дальше вы узнаете, как выдавать игрокам оружие в начале игры и в момент их появления.