Zasada działania algorytmu
Po rozpoczęciu gry chcemy zrównoważyć poszczególne drużyny tak, aby liczba należących do nich graczy była odpowiednia.
W przeciwieństwie do gier, w których równoważenie graczy odbywa się symetrycznie i graczy dzieli się równomiernie między drużyny, równoważenie asymetryczne oznacza, że każda drużyna powinna mieć względną liczbę graczy. Innymi słowy, przy doborze liczebności drużyn powinno się zachować względne proporcje.
Możesz na przykład chcieć, aby jedna drużyna zawsze liczyła dwukrotnie więcej graczy niż inna. W miarę dołączania graczy, musisz ich równoważyć w sposób, który pozwoli zachować te proporcje. W trybach gry, w których jedna drużyna jest silniejsza lub ma inne zdolności niż inna drużyna, równoważenie asymetryczne pozwala tworzyć lepiej dopracowane przygody, umożliwiając precyzyjne dobieranie liczby graczy w poszczególnych drużynach.
W tym przykładzie musisz się upewnić, że drużyny, w których maksymalna liczba graczy jest większa (w tym przypadku obrońcy), zawsze będą liczyć więcej graczy niż drużyny, w których maksymalna liczba graczy jest mniejsza (na przykład infiltratorów).
Aby uzyskać prawidłowy rozkład graczy, trzeba umieszczać każdego gracza w drużynie, w której różnica między rzeczywistą a maksymalną liczbą graczy jest największa.
W tym celu w przypadku każdego nowego gracza trzeba sprawdzić każdą drużynę, a następnie zapisać odwołanie do zarówno maksymalnej, jak i bieżącej liczby graczy w drużynie, oraz drużyny, do której gracz zostanie przypisany. Aby uzyskać różnicę względem wartości maksymalnej, można odjąć maksymalną liczbę graczy od bieżącej liczby graczy. Gdy znajdziesz drużynę, w której różnica względem maksymalnej liczby graczy jest największa, ustawisz przypisanie gracza do tej drużyny.
Wykonując iterację przez poszczególne drużyny, zyskujesz pewność, że znajdziesz drużynę, w której ta różnica jest największa.
Definiowanie algorytmu
W tym kroku zaprezentowano, jak równoważyć drużyny graczy asymetrycznie, na początku gry.
- Dodaj nową metodę o nazwie
BalanceTeams()
do klasytriad_infiltration_game
. Metoda ta przypisuje gracza do drużyny, w której różnica między rzeczywistą a maksymalną liczbą graczy jest największa.# Równoważy wszystkich graczy we wszystkich drużynach w grze BalanceTeams():void= Logger.Print("Zaczynam równoważyć drużyny")
- Pobierz wszystkich graczy w grze i zapisz ich w tablicy zmiennych
AllPlayers
. Następnie pomieszaj losowo zawartość tablicyAllPlayers
. Dzięki temu gracze będą przypisywani do drużyn losowo, a nie w kolejności dołączania do gry.# Równoważy wszystkich graczy we wszystkich drużynach w grze BalanceTeams():void= Logger.Print("Zaczynam równoważyć drużyny") var AllPlayers:[]player := GetPlayspace().GetPlayers() set AllPlayers = Shuffle(AllPlayers)
- Teraz chcesz wykonać iterację po wszystkich graczach i przypisać ich do drużyny, w której różnica między rzeczywistą a maksymalną liczbą graczy jest największa. Wykorzystasz do tego funkcję pomocniczą
FindTeamWithLargestDifference()
, którą utworzysz w następnym kroku, ale najpierw zainicjuj zmienną opcji o nazwieTeamToAssign
, do której przypiszesz gracza, i ustaw dla niej wartość zwróconą przezFindTeamWithLargestDifference()
.for (TeamPlayer:AllPlayers): var TeamToAssign:?team = false set TeamToAssign = FindTeamWithLargestDifference()
- Utwórz funkcję
FindTeamWithLargestDifference()
w definicji klasytriad_infiltration_game
. Zadaniem tej funkcji będzie znalezienie drużyny, w której różnica między aktualną i maksymalną liczbą graczy jest największa, i zwrócenie opcjonalnej wartościteam
. Zwrócona wartośćteam
powinna być opcjonalna, aby uniemożliwić ponowne przypisanie gracza, gdy należy on już do drużyny, w której ta różnica jest największa.# Znajduje drużynę, w której różnica między aktualną liczbą graczy # a maksymalną liczbą graczy jest największa FindTeamWithLargestDifference():?team = Logger.Print("Próbuję znaleźć najmniejszą drużynę")
- Zainicjuj opcjonalną zmienną drużyny o nazwie
TeamToAssign
, w której będzie przechowywane odwołanie do drużyny o największej różnicy w liczbie graczy, oraz liczbę całkowitą (integer)LargestDifference
do śledzenia tej różnicy w liczbie graczy.# Znajduje drużynę, w której różnica między aktualną liczbą graczy # a maksymalną liczbą graczy jest największa. FindTeamWithLargestDifference():?team = Logger.Print("Próbuję znaleźć najmniejszą drużynę") var TeamToAssign:?team = false var LargestDifference:int = 0
- Teraz wykonaj iterację po liście drużyn, pobierając zarówno aktualną, jak i maksymalną liczebność drużyny.
var TeamToAssign:?team = false var LargestDifference:int = 0 for: CandidateTeam:Teams CurrentTeamSize := GetPlayspace().GetTeamCollection().GetAgents[CandidateTeam].Length MaximumTeamSize := TeamsAndTotals[CandidateTeam]
- Dla każdej drużyny oblicz
DifferenceFromMaximum
, czyli różnicę między maksymalną liczebnością tej drużyny a aktualną liczbą należących do niej graczy. Jeśli wartość tej różnicy dla drużyny jest większa niżLargestDifference
, ustaw dlaLargestDifference
wartośćDifferenceFromMaximum
i uwzględnijTeamToAssign
woption
.for: CandidateTeam:Teams CurrentTeamSize := GetPlayspace().GetTeamCollection().GetAgents[CandidateTeam].Length MaximumTeamSize := TeamsAndTotals[CandidateTeam] do: Logger.Print("Sprawdzanie drużyny...") Logger.Print("Maksymalna liczebność tej drużyny wynosi {MaximumTeamSize}") DifferenceFromMaximum := MaximumTeamSize - CurrentTeamSize Logger.Print("Różnica względem wartości maksymalnej wynosi {DifferenceFromMaximum}") if(LargestDifference < DifferenceFromMaximum): set LargestDifference = DifferenceFromMaximum set TeamToAssign = option{CandidateTeam} Logger.Print("Znaleziono drużynę, w której liczba graczy jest niższa od maksymalnej: {DifferenceFromMaximum}")
- Na końcu zwróć
TeamToAssign
. Otrzymany kodFindTeamWithLargestDifference()
powinien wyglądać następująco:# Znajduje drużynę, w której różnica między aktualną liczbą graczy # a maksymalną liczbą graczy jest największa. FindTeamWithLargestDifference():?team = Logger.Print("Próbuję znaleźć najmniejszą drużynę") var TeamToAssign:?team = false var LargestDifference:int = 0 for: CandidateTeam:Teams CurrentTeamSize := GetPlayspace().GetTeamCollection().GetAgents[CandidateTeam].Length MaximumTeamSize := TeamsAndTotals[CandidateTeam] do: Logger.Print("Sprawdzanie drużyny...") Logger.Print("Maksymalna liczebność drużyny {CandidateTeamIndex + 1} wynosi {MaximumTeamSize}") DifferenceFromMaximum := MaximumTeamSize - CurrentTeamSize Logger.Print("Różnica względem wartości minimalnej wynosi {DifferenceFromMaximum}") if(LargestDifference < DifferenceFromMaximum): set LargestDifference = DifferenceFromMaximum set TeamToAssign = option{CandidateTeam} Logger.Print("Znaleziono drużynę, w której liczba graczy jest niższa od minimalnej: {DifferenceFromMaximum}") return TeamToAssign
- Wróć do
BalanceTeams()
i przypisz gracza do nowej drużyny za pomocą funkcjiFortTeamCollection.AddToTeam[]
. Jeśli to przypisanie się nie powiedzie, będzie to oznaczać, że gracz należał już do najmniejszej drużyny.var TeamToAssign:?team = false set TeamToAssign = FindTeamWithLargestDifference() if (AssignedTeam := TeamToAssign?, FortTeamCollection.AddToTeam[TeamPlayer, AssignedTeam]): Logger.Print("Próbuję przypisać gracza do nowej drużyny")
- Otrzymana funkcja
BalanceTeams()
powinna wyglądać następująco:# Równoważy wszystkich graczy we wszystkich drużynach w grze BalanceTeams():void= Logger.Print("Zaczynam równoważyć drużyny") var AllPlayers:[]player := GetPlayspace().GetPlayers() set AllPlayers = Shuffle(AllPlayers) Logger.Print("Długość AllPlayers wynosi {AllPlayers.Length}") for (TeamPlayer:AllPlayers): var TeamToAssign:?team = false set TeamToAssign = FindTeamWithLargestDifference() if (AssignedTeam := TeamToAssign?, FortTeamCollection.AddToTeam[TeamPlayer, AssignedTeam]): Logger.Print("Przypisano gracza do nowej drużyny")
Teleportowanie graczy do ich stref spawnu
Nawet jeśli gracze wylądują w drużynie, w której różnica w liczbie graczy jest największa, mogą nie zespawnować się we właściwym miejscu. Przyczyną jest to, że spawnowanie graczy odbywa się przed przypisaniem do nowej drużyny w celu zrównoważenia. Aby rozwiązać ten problem, utworzysz nową funkcję do teleportowania graczy do strefy spawnu już po zrównoważeniu drużyn.
- Utwórz funkcję
TeleportPlayersToStartLocations()
w definicji klasytriad_infiltration_game
. Funkcja ta będzie teleportować graczy do strefy spawnu ich drużyny po zakończeniu równoważenia.# Teleportuje graczy do strefy spawnu ich drużyny po zakończeniu równoważenia drużyn. TeleportPlayersToStartLocations():void= Logger.Print("Teleportuję graczy do lokalizacji startowych")
- W pętli
for
wykonaj iterację po każdej pozycji tablicyTeams
, pobierając indeks danej drużyny i zapisując go w zmiennejTeamIndex
.# Teleportuje graczy do strefy spawnu ich drużyny po zakończeniu równoważenia drużyn. TeleportPlayersToStartLocations():void= Logger.Print("Teleportuję graczy do lokalizacji startowych") for: TeamIndex -> PlayerTeam:Teams
- Pobierz graczy należących do
PlayerTeam
, wywołując funkcjęGetAgents[]
z użyciemPlayerTeam
. Następnie pobierz teleporter powiązany z daną drużyną, indeksując tablicęTeleporters
z użyciemTeamIndex
i zapisując go w zmiennejTeamTeleporter
. Zapisz przekształcenie tego teleportera w zmiennejTransform.
# Teleportuje graczy do strefy spawnu ich drużyny po zakończeniu równoważenia drużyn. TeleportPlayersToStartLocations():void= Logger.Print("Teleportuję graczy do lokalizacji startowych") for: TeamIndex -> PlayerTeam:Teams TeamPlayers := GetPlayspace().GetTeamCollection().GetAgents[PlayerTeam] TeamTeleporter := Teleporters[TeamIndex] Transform := TeamTeleporter.GetTransform()
Upewnij się, że kolejność drużyn w tablicy
Teams
jest zgodna z kolejnością teleporterów w tablicyTeleporters
. Jeśli infiltratorzy są drużyną nr 1, wówczas pierwszy teleporter w tablicyTeleporters
powinien być przeznaczony dla infiltratorów. Dla pewności sięgnij do edytora i sprawdź dokładnie, czy te wartości są prawidłowe. - Teraz w drugiej pętli
for
wykonaj iterację po poszczególnych graczach w tablicyTeamPlayers
i wykonaj ich respawn w przekształceniu teleportera z użyciemRespawn()
oraz translacji i obrotu przekształceniaTransform
. Otrzymana funkcjaTeleportPlayersToStartLocations()
powinna wyglądać następująco:# Teleportuje graczy do strefy spawnu ich drużyny po zakończeniu równoważenia drużyn. TeleportPlayersToStartLocations():void= Logger.Print("Teleportuję graczy do lokalizacji startowych") 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("Ten gracz został teleportowany do jego lokalizacji startowej")
- W
OnBegin()
dodaj wywołanie doBalanceTeams()
po losowym ustawieniu kolejnościAllPlayers
. Dzięki temu gracze będą równoważeni w kolejności losowej i nie będą za każdym razem trafiali do tej samej drużyny. Następnie teleportuj graczy do ich lokalizacji początkowych, wywołującTeleportPlayersToStartLocations()
.OnBegin<override>()<suspends> : void = # Pobierz wszystkie drużyny set Teams = GetPlayspace().GetTeamCollection().GetTeams() # Zapisz drużyny, aby móc się później do nich odwołać set MaybeInfiltrators = option{Teams[0]} set MaybeAttackers = option{Teams[1]} set MaybeDefenders = option{Teams[2]} if: Infiltrators := MaybeInfiltrators? Attackers := MaybeAttackers? Defenders := MaybeDefenders? Logger.Print("Znaleziono wszystkie trzy drużyny") set TeamsAndTotals[Infiltrators] = MaximumInfiltrators set TeamsAndTotals[Attackers] = MaximumAttackers set TeamsAndTotals[Defenders] = MaximumDefenders Logger.Print("Ustaw wszystkie trzy drużyny w TeamsAndTotals") then: BalanceTeams() TeleportPlayersToStartLocations() else: Logger.Print("Nie udało się znaleźć wszystkich drużyn. Pamiętaj, aby przypisać właściwe drużyny w ustawieniach wyspy.")
-
Zapisz skrypt, skompiluj go, a następnie na pasku narzędzi UEFN kliknij opcję Uruchom sesję, aby przetestować poziom w grze. W trakcie testowania poziomu w grze każdy gracz powinien trafiać do drużyny, w której różnica liczebności graczy jest największa, a także spawnować się w strefie pojawiania się tej drużyny. Zweryfikuj to zachowanie na podstawie dziennika. Możesz zmienić maksymalną liczbę graczy w drużynie w
triad_infiltration_game
, aby przetestować tę funkcjonalność, gdy masz do dyspozycji mniej graczy niż wynosi maksymalna liczba. Gdy na przykład przeprowadzasz test samodzielnie, w drużynie, do której próbujesz trafić, spróbuj ustawić maksymalną liczbę graczy większą niż w pozostałych dwóch drużynach. Jeśli chcesz trafić do drużyny atakujących, ustaw wyższą wartośćMaximumAttackers
. Jeśli chcesz trafić do drużyny infiltratorów, ustaw wyższą wartośćMaximumInfiltrators
.
Następny krok
W następnym kroku tego samouczka dowiesz się, jak przyznać graczom bronie na początku gry oraz w momencie spawnu.