È ora di codificare l'ultima fase del Gioco: la pulizia e il Ripristina. Il codice in questa fase garantisce che i giochi si svolgono ininterrotti e che le future partite iniziano lo stesso per ogni Giocatore.
Aggiornamento della GUI or Intefaccia grafica utente
Prima di fare pulizia e Ripristina, informa i giocatori come il gioco è finito usando il DisplayManager per mostrare lo Statoappropriato.
Ottenere il nome del vincitore
Inizia ottenendo il nome del Giocatorevincitore se c'era uno. In precedenza, il codice controllava se la dimensione della tabella dei giocatori attivi era inferiore a 1. Per ottenere il nome del Giocatorerimanente, restituisci il nome all'indice di primo della tabella.
In PlayerManager, inizia una nuova funzione del modulo chiamata getWinnerName() .
function PlayerManager.getWinnerName()end-- EventiPlayers.PlayerAdded:Connect(onPlayerJoin)Aggiungi una dichiarazione if che viene eseguita se esiste qualcosa in activePlayers[1] . Anche se il numero di tabelle è stato controllato prima, il giocatore potrebbe essere disconnesso o uscito dal Gioco.
function PlayerManager.getWinnerName()local winningPlayer = activePlayers[1]if winningPlayer thenendendNella dichiarazione if:
- Restituisci il nome del Giocatore.
- Per gli altri, restituisci una Stringadi errore.
function PlayerManager.getWinnerName()local winningPlayer = activePlayers[1]if winningPlayer thenreturn winningPlayer.Nameelsereturn "Error: No winning player found"endend
Ottenere lo stato finale
Usa una funzione del modulo per ottenere informazioni dallo stato corretto, che il timer finisca o che un giocatore venga lasciato. Quindi, invia quella variabile di stato a DisplayManager per aggiornare la GUI di stato con il Messaggioappropriato.
In MatchManager , codice una nuova funzione del modulo chiamata getEndStatus() con un parametro chiamato endState . Per memorizzare il messaggio che verrà inviato, aggiungi una variabile vuota chiamata 1> statusToReturn1> .
function MatchManager.prepareGame()playerManager.sendPlayersToMatch()matchStart:Fire()endfunction MatchManager.getEndStatus(endState)local statusToReturnendmatchStart.Event:Connect(startTimer)matchEnd.Event:Connect(stopTimer)return MatchManagerImposta il valore di statusToReturn utilizzando if e elif statement. Controlla le variabili di stato alla fine: FoundWinner e TimerUp . Per il controllo degli errori, includi un altro alla Terminare.
function MatchManager.getEndStatus(endState)local statusToReturnif endState == gameSettings.endStates.FoundWinner thenelseif endState == gameSettings.endStates.TimerUp thenelseendendAggiungi quanto segue per ciascuna condizione:
FoundWinner
- Una variabile per il vincitore usando playerManager.getWinnerName() .
- Aggiorna statusToReturn con una stringa che annuncia il vincitore.
TimerUp
- Aggiorna statusToReturn con una stringa che annuncia il tempo scaduto.
Else
- Aggiorna statusToReturn con un messaggio di errore in caso di problemi con l'ottenimento del Messaggiodi fine partita.
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"endendInvia il messaggio facendo clic su 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
Visualizzazione e Test
Ottieni l'annuncio aggiornato in GameManager e mostralo ai giocatori usando il DisplayManager.
Apri GameManager . In while true do loop, delete l'ultima dichiarazione di stampa. Quindi, crea una variabile chiamata endStatus. Impostarla uguale a chiamare 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)endPer visualizzare il messaggio restituito nell'EtichettaGUI, chiama displayManager.updateStatus() e passa in endStatus .
local endStatus = matchManager.getEndStatus(endState)displayManager.updateStatus(endStatus)Quindi il gioco si ferma per consentire ai giocatori di vedere il Messaggio, aggiungi un'attesa usando transitionTime .
local endStatus = matchManager.getEndStatus(endState)displayManager.updateStatus(endStatus)task.wait(gameSettings.transitionTime)Avvia un test server e controlla che i giocatori visualizzino i seguenti messaggi per il tempo up e le condizioni di vincitore.
Risolvere i problemi
Al momento, non sei in grado di visualizzare i messaggi, prova uno dei seguenti sotto.
- Se il tuo messaggio di stato finale è "Errore trovato", nessuna delle condizioni è riuscita. Controlla il codice in MatchManager.getEndStatus() contro gli esempi di codice.
- Se lo stato di fine non viene visualizzato, controlla che task.wait(gameSettings.transitionTime) sia dopo l'invio del messaggio a displayManager.
Inizio Nuove Partite
Prima di iniziare una nuova Corrisponde, ci sarà una breve transizione. Ciò dà ai giocatori il tempo di vedere lo stato di fine e rendere il teletrasporto alla lobby meno improvviso.
Alla fine della transizione, i giocatori rimanenti dall'arena saranno rimossi e tutto il codice verrà Ripristina. Ciò garantisce che i giocatori inizieranno la prossima partita con una versione pulita del Gioco.
Trattamento delle transizioni
Quando i giocatori entrano in stato di transizione, rimuovono le loro armi.
In PlayerManager, trova le funzioni locali. Copia e pasta il codice evidenziato per removePlayerWeapon() sotto. Il codice rimuoverà l'arma di un Giocatoreindividuale se è attivamente equipaggiato o nello zaino del Giocatore.
local function removePlayerWeapon(whichPlayer)-- Controlla se un giocatore esiste in caso di loro disconnessione o uscita.if whichPlayer thenlocal character = whichPlayer.Character-- Se il giocatore lo ha attualmente nel suo personaggiolocal weapon = character:FindFirstChild("Weapon")if weapon thenweapon:Destroy()end-- Se il giocatore ha l'arma nel suo zainolocal backpackWeapon = whichPlayer.Backpack:FindFirstChild("Weapon")if backpackWeapon thenbackpackWeapon:Destroy()endelseprint("No player to remove weapon")endendInizia una nuova funzione del modulo chiamata removeAllWeapons() .
function PlayerManager.removeAllWeapons()end-- EventiPlayers.PlayerAdded:Connect(onPlayerJoin)return PlayerManagerIn quella funzione, usa un for loop per passare attraverso la tabella dei giocatori attivi. In loop, chiama removePlayerWeapon() e passa nel giocatore trovato.
function PlayerManager.removeAllWeapons()for playerKey, whichPlayer in activePlayers doremovePlayerWeapon(whichPlayer)endend
Pulizia tra le partite
Il pulire sarà la sua funzione in MatchManager. Per ora, il pulire utilizzera solo la funzione precedentemente creata per rimuovere le armi del giocatore. Man mano che espandi il Gioco, puoi aggiungere ulteriori funzioni, come funzioni per ripristinare una mappa che è cambiata durante una Corrisponde.
Apri MatchManager. Aggiungi una nuova funzione del modulo chiamata cleanupMatch() . In quella funzione, chiami playerManager.removeAllWeapons() .
function MatchManager.cleanupMatch()playerManager.removeAllWeapons()endmatchStart.Event:Connect(startTimer)matchEnd.Event:Connect(stopTimer)return MatchManagerSuccessivamente, chiama la funzione di pulizia. Apri GameManager e trova il while true do loop. Quindi i giocatori hanno le armi rimosse durante l'intervallo di finzione, chiama matchManager.cleanupMatch() prima dell'ultimo 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)endAvvia un server di prova e esegui una Corrisponde. Attendi che il timer finisca e conferma che l'arma del Giocatoresia rimossa durante l'interruzione della partita di fine gioco.
Ripristinare le Partite
Potresti aver notato alcune altre cose nel Gioco, come i giocatori che vengono ancora nell'arena dopo la fine di una partita. Con la partita pulita, quindi ripristina il Gioco. Ciò include l'invio dei giocatori nell'arena nel lobby e la pulizia della tabella dei giocatori attivi. Con un reset in Posto, un ciclo di gioco può essere eseguito indefinitamente.
Per prima cosa, inizia una funzione per inviare i giocatori alla lobby.
In PlayerManager:
- Crea una funzione del modulo chiamata resetPlayers() .
- Aggiungi un for loop per itere attraverso i giocatori attivi.
- In loop, call respawnPlayerInLobby() and pass in the player as the parameter.
function PlayerManager.resetPlayers()for playerKey, whichPlayer in activePlayers dorespawnPlayerInLobby(whichPlayer)endend-- EventiPlayers.PlayerAdded:Connect(onPlayerJoin)return PlayerManagerAssicurati che la tabella activePlayers sia vuota per il prossimo match impostandola uguale a {} , che è un modo rapido per resettare a una tabella vuota.
function PlayerManager.resetPlayers()for playerKey, whichPlayer in activePlayers dorespawnPlayerInLobby(whichPlayer)endactivePlayers = {}endApri MatchManager. Codice una nuova funzione del modulo chiamata resetMatch() e chiama playerManager.resetPlayers() .
function MatchManager.resetMatch()playerManager.resetPlayers()endmatchStart.Event:Connect(startTimer)matchEnd.Event:Connect(stopTimer)return MatchManagerTorna a GameManager . Alla fine del while true do loop, chiama 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()endInizia un server di prova e esegui una Corrisponde. Conferma che puoi almeno passare attraverso due loop di gioco senza errori.
Script completati
Di seguito sono gli script completati per il doppio controllo del tuo lavoro.
Script del GameManager
-- Servizilocal ServerStorage = game:GetService("ServerStorage")local Players = game:GetService("Players")-- Script del modulolocal moduleScripts = ServerStorage:WaitForChild("ModuleScripts")local matchManager = require(moduleScripts:WaitForChild("MatchManager"))local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))local displayManager = require(moduleScripts:WaitForChild("DisplayManager"))-- Eventilocal 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 del MatchManager
local MatchManager = {}
-- Servizi
local ServerStorage = game:GetService("ServerStorage")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Script del modulo
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"))
-- Eventi
local events = ServerStorage:WaitForChild("Events")
local matchStart = events:WaitForChild("MatchStart")
local matchEnd = events:WaitForChild("MatchEnd")
-- Valori
local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")
local timeLeft = displayValues:WaitForChild("TimeLeft")
-- Crea un nuovo oggetto timer per essere utilizzato per tracciare il tempo della partita.
local myTimer = timer.new()
-- Funzioni locali
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
-- L'aggiunta di +1 assicura che il timer finisca a 1 invece di 0.
timeLeft.Value = (math.floor(myTimer:getTimeLeft() + 1))
-- Impostando il tempo di attesa, offre un looping più preciso
task.wait()
end
end
-- Funzioni del modulo
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 del lettore
local PlayerManager = {}
-- Servizi
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Moduli
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
-- Eventi
local events = ServerStorage:WaitForChild("Events")
local matchEnd = events:WaitForChild("MatchEnd")
-- Variabili di mappa
local lobbySpawn = workspace.Lobby.StartSpawn
local arenaMap = workspace.Arena
local spawnLocations = arenaMap.SpawnLocations
-- Valori
local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")
local playersLeft = displayValues:WaitForChild("PlayersLeft")
-- Variabili del giocatore
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()
-- Dai al giocatore uno strumento
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)
-- Controlla se un giocatore esiste in caso di loro disconnessione o uscita.
if whichPlayer then
local character = whichPlayer.Character
-- Se il giocatore lo ha attualmente nel suo personaggio
local weapon = character:FindFirstChild("Weapon")
if weapon then
weapon:Destroy()
end
-- Se il giocatore ha l'arma nel suo zaino
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)
-- Ottiene una posizione di spawn e poi la rimuove dalla tabella in modo che il prossimo giocatore ottenga la prossima Rigenerare
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
-- Eventi
Players.PlayerAdded:Connect(onPlayerJoin)
return PlayerManager