Il est temps de codifier la dernière phase du jeu : le nettoyage et le réinitialiser. Le code dans cette phase garantit que les boucles de jeu s'arrêtent à l'intermission et que les matchs futurs commencent pour chaque joueur.
Mise à jour de linterface utilisateur graphique
Avant de nettoyer et de réinitialiser, informez les joueurs comment le jeu s'est terminé en utilisant le Gestionnaire d'affichage pour montrer le statut approprié.
Obtenir le nom du gagnant
Commencez par obtenir le nom du joueur gagnant s'il y en avait un. Auparavant, le code vérifiait si la taille de la table des joueurs actifs était réduite de 1. Pour obtenir le nom du joueur restant, retournez le nom au premier index de cette table.
Dans PlayerManager, commencez une nouvelle fonction de module nommée getWinnerName() .
function PlayerManager.getWinnerName()end-- ÉvénementsPlayers.PlayerAdded:Connect(onPlayerJoin)Ajoutez une if statement qui s'exécute si quelque chose existe dans activePlayers[1]. Bien que le nombre de tables ait été vérifié auparavant, le joueur pourrait avoir quitté ou quitté le jeu.
function PlayerManager.getWinnerName()local winningPlayer = activePlayers[1]if winningPlayer thenendendDans la déclaration if :
- Renvoie le nom du joueur.
- Pour l'autre, renvoyez une chaîne d'erreur.
function PlayerManager.getWinnerName()local winningPlayer = activePlayers[1]if winningPlayer thenreturn winningPlayer.Nameelsereturn "Error: No winning player found"endend
Obtenir le statut de fin
Utilisez une fonction de module pour prendre les informations de l'état correct, soit que le minuteur se termine, soit qu'un joueur quitte. Ensuite, envoyez cette variable d'état à DisplayManager pour mettre à jour le GUI de statut avec le message approprié.
Dans MatchManager , codez une nouvelle fonction de module nommée getEndStatus() avec un paramètre nommé endState . Pour stocker le message qui sera envoyé, ajoutez une variable vide nommée 1> statusToReturn1> .
function MatchManager.prepareGame()playerManager.sendPlayersToMatch()matchStart:Fire()endfunction MatchManager.getEndStatus(endState)local statusToReturnendmatchStart.Event:Connect(startTimer)matchEnd.Event:Connect(stopTimer)return MatchManagerDéfinissez la valeur de statusToReturn en utilisant les déclarations if et elif. Vérifiez les variables d'état final : FoundWinner et TimerUp. Pour le débogage, incluez un else à la terminer.
function MatchManager.getEndStatus(endState)local statusToReturnif endState == gameSettings.endStates.FoundWinner thenelseif endState == gameSettings.endStates.TimerUp thenelseendendAjoutez les éléments suivants pour chaque condition :
FoundWinner
- Un variable pour le gagnant en utilisant playerManager.getWinnerName() .
- Mise à jour statusToReturn avec une chaîne annonçant le gagnant.
TimerUp
- Mise à jour statusToReturn avec une chaîne annonçant le temps écoulé.
Else
- Mise à jour statusToReturn avec un message d'erreur dans le cas où il y a des problèmes pour obtenir le message de fin de partie.
function MatchManager.getEndStatus(endState)local statusToReturnif endState == gameSettings.endStates.FoundWinner thenlocal winnerName = playerManager.getWinnerName()statusToReturn = "Winner is : " .. winnerNameelseif endState == gameSettings.endStates.TimerUp thenstatusToReturn = "Time ran out!"elsestatusToReturn = "Error found"endendEnvoyez le message en entrant return statusToReturn .
function MatchManager.getEndStatus(endState)local statusToReturnif endState == gameSettings.endStates.FoundWinner thenlocal winnerName = playerManager.getWinnerName()statusToReturn = "Winner is : " .. winnerNameelseif endState == gameSettings.endStates.TimerUp thenstatusToReturn = "Time ran out!"elsestatusToReturn = "Error found"endreturn statusToReturnend
Affichage et test
Obtenez l'annonce mise à jour dans GameManager et affichez-la aux joueurs en utilisant le Gestionnaire d'affichage.
Ouvrez GameManager . In while true do loop, delete the last print statement. Then, create a variable named endStatus. Set it equal to calling matchManager.getEndStatus(endState) .
while true dodisplayManager.updateStatus("Waiting for Players")repeattask.wait(gameSettings.intermissionDuration)until #Players:GetPlayers() >= gameSettings.minimumPlayersdisplayManager.updateStatus("Get ready!")task.wait(gameSettings.transitionTime)matchManager.prepareGame()local endState = matchEnd.Event:Wait()local endStatus = matchManager.getEndStatus(endState)endPour afficher le message renvoyé dans l'étiquette GUI, appelez displayManager.updateStatus() et passez en endStatus .
local endStatus = matchManager.getEndStatus(endState)displayManager.updateStatus(endStatus)Le jeu s'arrête pour permettre aux joueurs de voir le message, ajoutez un temps d'attente en utilisant transitionTime.
local endStatus = matchManager.getEndStatus(endState)displayManager.updateStatus(endStatus)task.wait(gameSettings.transitionTime)Démarrez un testeur de serveur et vérifiez que les joueurs voient les messages suivants pour le temps écoulé et les conditions de gagnant.
Conseils de débogage
À ce stade, vous n'êtes pas en mesure de voir les messages, essayez l'un des éléments suivants.
- Si votre message de statut final est « Erreur trouvée », aucune des conditions n'a été réussie. Vérifiez le code dans MatchManager.getEndStatus() contre les exemples de code.
- Si l'état de fin ne s'affiche pas, vérifiez que task.wait(gameSettings.transitionTime) est après l'envoi du message à displayManager.
Démarrer de nouvelles matchs
Avant de commencer une nouvelle correspondre, il y aura une transition rapide. Cela donne aux joueurs le temps de voir le statut de fin et rend le fait d'être téléporté dans le lobby moins soudain.
À la fin de la transition, les joueurs restants seront retirés de l'arène, et tout le code sera réinitialiser. Cela garantit que les joueurs commencent la prochaine partie avec une version propre du jeu.
Gestion des transition
Lorsque les joueurs se transforment en état de transition, enlève leurs armes.
Dans PlayerManager, trouvez les fonctions locales. Copiez et collez le code en surbrillance pour removePlayerWeapon() ci-dessous. Le code supprime l'arme d'un joueur individuel s'il est activement équipé ou dans le sac à dos du joueur.
local function removePlayerWeapon(whichPlayer)-- Vérifiez si un joueur existe au cas où il se serait déconnecté ou quitté.if whichPlayer thenlocal character = whichPlayer.Character-- Si le joueur l'a actuellement sur son personnagelocal weapon = character:FindFirstChild("Weapon")if weapon thenweapon:Destroy()end-- Si le joueur a l'arme dans son sac à doslocal backpackWeapon = whichPlayer.Backpack:FindFirstChild("Weapon")if backpackWeapon thenbackpackWeapon:Destroy()endelseprint("No player to remove weapon")endendDémarrez une nouvelle fonction de module nommée removeAllWeapons() .
function PlayerManager.removeAllWeapons()end-- ÉvénementsPlayers.PlayerAdded:Connect(onPlayerJoin)return PlayerManagerDans cette fonction, utilisez un for loop pour aller à travers la table des joueurs actifs. Dans le loop, appelez removePlayerWeapon() et passez dans le joueur trouvé.
function PlayerManager.removeAllWeapons()for playerKey, whichPlayer in activePlayers doremovePlayerWeapon(whichPlayer)endend
Nettoyage entre les matchs
Le nettoyage sera sa propre fonction dans MatchManager. Pour l'instant, le nettoyage utilisera simplement cette fonction créée précédemment pour supprimer les armes des joueurs. Au fur et à mesure que vous élargissez le jeu, plus peut être ajouté, comme des fonctions pour réinitialiser une carte qui a changé pendant un correspondre.
Ouvrez MatchManager. Ajoutez une nouvelle fonction de module nommée cleanupMatch() . Dans cette fonction, appelez playerManager.removeAllWeapons() .
function MatchManager.cleanupMatch()playerManager.removeAllWeapons()endmatchStart.Event:Connect(startTimer)matchEnd.Event:Connect(stopTimer)return MatchManagerEnsuite, appelez la fonction de nettoyage. Ouvrez GameManager et trouvez le while true do loop. Ainsi, les joueurs ont des armes supprimées pendant l'intermission de fin, appelez matchManager.cleanupMatch() avant le dernier task.wait() .
while true dodisplayManager.updateStatus("Waiting for Players")repeattask.wait(gameSettings.intermissionDuration)until #Players:GetPlayers() >= gameSettings.minimumPlayersdisplayManager.updateStatus("Get ready!")task.wait(gameSettings.transitionTime)matchManager.prepareGame()local endState = matchEnd.Event:Wait()local endStatus = matchManager.getEndStatus(endState)displayManager.updateStatus(endStatus)matchManager.cleanupMatch()task.wait(gameSettings.transitionTime)endDémarrez un serveur de test et exécutez un correspondre. Attendez que le minuteur se termine et confirmez que l'arme du joueur est retirée pendant l'intermission de la fin du jeu.
Réinitialisation des matchs
Vous avez peut-être remarqué quelques autres choses dans le jeu, comme les joueurs qui restent dans l'arène après la fin d'un match. Avec le match nettoyé, le jeu réinitialise ensuite. Cela inclut l'envoi de joueurs dans l'arène et le nettoyage de la table des joueurs actifs. Avec un réinitialisation en emplacement, un boucle de jeu peut s'exécuter infiniment.
Tout d'abord, commencez une fonction pour envoyer les joueurs dans le lobby.
Dans PlayerManager :
- Créer une fonction de module nommée resetPlayers() .
- Ajoutez un for loop pour itérer à travers les joueurs actifs.
- Dans la boucle, appelez respawnPlayerInLobby() et passez le joueur en tant que paramètre.
function PlayerManager.resetPlayers()for playerKey, whichPlayer in activePlayers dorespawnPlayerInLobby(whichPlayer)endend-- ÉvénementsPlayers.PlayerAdded:Connect(onPlayerJoin)return PlayerManagerAssurez-vous que la table activePlayers est vide pour le prochain match en laissant-la équivalente à {}, ce qui est un moyen rapide de réinitialiser à une table vide.
function PlayerManager.resetPlayers()for playerKey, whichPlayer in activePlayers dorespawnPlayerInLobby(whichPlayer)endactivePlayers = {}endOuvrez MatchManager. Codez une nouvelle fonction de module nommée resetMatch() et appelez playerManager.resetPlayers().
function MatchManager.resetMatch()playerManager.resetPlayers()endmatchStart.Event:Connect(startTimer)matchEnd.Event:Connect(stopTimer)return MatchManagerRetournez à GameManager . Au bout du compte-à-rebours, appelez matchManager.resetMatch() .
while true dodisplayManager.updateStatus("Waiting for Players")repeattask.wait(gameSettings.intermissionDuration)until #Players:GetPlayers() >= gameSettings.minimumPlayersdisplayManager.updateStatus("Get ready!")task.wait(gameSettings.transitionTime)matchManager.prepareGame()local endState = matchEnd.Event:Wait()local endStatus = matchManager.getEndStatus(endState)displayManager.updateStatus(endStatus)matchManager.cleanupMatch()task.wait(gameSettings.transitionTime)matchManager.resetMatch()endDémarrez un serveur de test et exécutez un correspondre. Confirmez que vous pouvez au moins passer à travers deux boucles de jeu sans aucune erreur.
Scripts terminés
Ceux-ci sont des scripts terminés pour vérifier vos travaux.
Script de GameManager
-- Serviceslocal ServerStorage = game:GetService("ServerStorage")local Players = game:GetService("Players")-- Scripts de modulelocal moduleScripts = ServerStorage:WaitForChild("ModuleScripts")local matchManager = require(moduleScripts:WaitForChild("MatchManager"))local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))local displayManager = require(moduleScripts:WaitForChild("DisplayManager"))-- Événementslocal events = ServerStorage:WaitForChild("Events")local matchEnd = events:WaitForChild("MatchEnd")while true dodisplayManager.updateStatus("Waiting for Players")repeattask.wait(gameSettings.intermissionDuration)until #Players:GetPlayers() >= gameSettings.minimumPlayersdisplayManager.updateStatus("Get ready!")task.wait(gameSettings.transitionTime)matchManager.prepareGame()local endState = matchEnd.Event:Wait()local endStatus = matchManager.getEndStatus(endState)displayManager.updateStatus(endStatus)matchManager.cleanupMatch()task.wait(gameSettings.transitionTime)matchManager.resetMatch()end
Script de MatchManager
local MatchManager = {}
-- Services
local ServerStorage = game:GetService("ServerStorage")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Scripts de module
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local playerManager = require(moduleScripts:WaitForChild("PlayerManager"))
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
local displayManager = require(moduleScripts:WaitForChild("DisplayManager"))
local timer = require(moduleScripts:WaitForChild("Timer"))
-- Événements
local events = ServerStorage:WaitForChild("Events")
local matchStart = events:WaitForChild("MatchStart")
local matchEnd = events:WaitForChild("MatchEnd")
-- Valeurs
local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")
local timeLeft = displayValues:WaitForChild("TimeLeft")
-- Crée un nouvel objet de minuterie à utiliser pour suivre le temps du match.
local myTimer = timer.new()
-- Fonctions locales
local function stopTimer()
myTimer:stop()
end
local function timeUp()
matchEnd:Fire(gameSettings.endStates.TimerUp)
end
local function startTimer()
myTimer:start(gameSettings.matchDuration)
myTimer.finished:Connect(timeUp)
while myTimer:isRunning() do
-- Ajouter +1 fait en sorte que l'afficheur de temps s'affiche à 1 au lieu de 0.
timeLeft.Value = (math.floor(myTimer:getTimeLeft() + 1))
-- En ne définissant pas le temps d'attente, il offre un meilleur suivi
task.wait()
end
end
-- Fonctions de module
function MatchManager.prepareGame()
playerManager.sendPlayersToMatch()
matchStart:Fire()
end
function MatchManager.getEndStatus(endState)
local messageToReturn
if endState == gameSettings.endStates.FoundWinner then
local winnerName = playerManager.getWinnerName()
messageToReturn = "Winner is : " .. winnerName
elseif endState == gameSettings.endStates.TimerUp then
messageToReturn = "Time ran out!"
else
messageToReturn = "Error found"
end
return messageToReturn
end
function MatchManager.cleanupMatch()
playerManager.removeAllWeapons()
end
function MatchManager.resetMatch()
playerManager.resetPlayers()
end
matchStart.Event:Connect(startTimer)
matchEnd.Event:Connect(stopTimer)
return MatchManager
Script PlayerManager
local PlayerManager = {}
-- Services
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Modules
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
-- Événements
local events = ServerStorage:WaitForChild("Events")
local matchEnd = events:WaitForChild("MatchEnd")
-- Variables de carte
local lobbySpawn = workspace.Lobby.StartSpawn
local arenaMap = workspace.Arena
local spawnLocations = arenaMap.SpawnLocations
-- Valeurs
local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")
local playersLeft = displayValues:WaitForChild("PlayersLeft")
-- Variables du joueur
local activePlayers = {}
local playerWeapon = ServerStorage.Weapon
local function checkPlayerCount()
if #activePlayers == 1 then
matchEnd:Fire(gameSettings.endStates.FoundWinner)
print("Found winner")
end
end
local function removeActivePlayer(player)
print("removing player")
for playerKey, whichPlayer in activePlayers do
if whichPlayer == player then
table.remove(activePlayers, playerKey)
playersLeft.Value = #activePlayers
checkPlayerCount()
end
end
end
local function respawnPlayerInLobby(player)
player.RespawnLocation = lobbySpawn
player:LoadCharacter()
end
local function preparePlayer(player, whichSpawn)
player.RespawnLocation = whichSpawn
player:LoadCharacter()
local character = player.Character or player.CharacterAdded:Wait()
-- Donnez un outil au joueur
local sword = playerWeapon:Clone()
sword.Parent = character
local humanoid = character:WaitForChild("Humanoid")
humanoid.Died:Connect(function()
respawnPlayerInLobby(player)
removeActivePlayer(player)
end)
end
local function onPlayerJoin(player)
player.RespawnLocation = lobbySpawn
end
local function removePlayerWeapon(whichPlayer)
-- Vérifiez si un joueur existe au cas où il se serait déconnecté ou quitté.
if whichPlayer then
local character = whichPlayer.Character
-- Si le joueur l'a actuellement sur son personnage
local weapon = character:FindFirstChild("Weapon")
if weapon then
weapon:Destroy()
end
-- Si le joueur a l'arme dans son sac à dos
local backpackWeapon = whichPlayer.Backpack:FindFirstChild("Weapon")
if backpackWeapon then
backpackWeapon:Destroy()
end
else
print("No player to remove weapon")
end
end
function PlayerManager.sendPlayersToMatch()
local availableSpawnPoints = spawnLocations:GetChildren()
for playerKey, whichPlayer in Players:GetPlayers() do
table.insert(activePlayers,whichPlayer)
-- Obtient un lieu d'apparition et le supprime de la table pour que le prochain joueur obtienne le prochain lieu d'apparition
local spawnLocation = table.remove(availableSpawnPoints, 1)
preparePlayer(whichPlayer, spawnLocation)
end
playersLeft.Value = #activePlayers
end
function PlayerManager.getWinnerName()
local winningPlayer = activePlayers[1]
if winningPlayer then
return winningPlayer.Name
else
return "Error: No player found"
end
end
function PlayerManager.removeAllWeapons()
for playerKey, whichPlayer in activePlayers do
removePlayerWeapon(whichPlayer)
end
end
function PlayerManager.resetPlayers()
for playerKey, whichPlayer in activePlayers do
respawnPlayerInLobby(whichPlayer)
end
activePlayers = {}
end
-- Événements
Players.PlayerAdded:Connect(onPlayerJoin)
return PlayerManager