Hora de codificar a última fase do jogo: limpar e reiniciar.Código nesta fase garante que os loops do jogo para intermissão e que as partidas futuras comecem igualmente para cada jogador.
Atualize a GUI
Antes de fazer limpeza e redefinir, informe os jogadores como o jogo terminou usando o Gerenciador de Exibição para mostrar o status apropriado.
Obtenha o nome do vencedor
Comece por obter o nome do jogador vencedor se houve um.Anteriormente, o código verificava se o tamanho da tabela de jogadores ativos era reduzido para 1.Para obter o nome do jogador restante, retorne o nome no primeiro índice daquela tabela.
No PlayerManager, inicie uma nova função de módulo chamada getWinnerName().
function PlayerManager.getWinnerName()end-- EventosPlayers.PlayerAdded:Connect(onPlayerJoin)Adicione uma declaração if que execute se algo existir em activePlayers[1] .Embora a contagem de mesas tenha sido verificada antes, o jogador pode ter se desconectado ou deixado o jogo.
function PlayerManager.getWinnerName()local winningPlayer = activePlayers[1]if winningPlayer thenendendNa declaração if:
- Retorne o nome do jogador.
- Para o resto, retorne uma string de erro.
function PlayerManager.getWinnerName()local winningPlayer = activePlayers[1]if winningPlayer thenreturn winningPlayer.Nameelsereturn "Error: No winning player found"endend
Obtenha o status final
Use uma função de módulo para obter informações do estado final correto, se o cronômetro termina ou um jogador é deixado.Então, envie essa variável de estado para o Gerenciador de Exibição para atualizar o status GUI com a mensagem apropriada.
Em Gerenciador de Partida , códigue uma nova função de módulo chamada getEndStatus() com um parâmetro chamado endState .Para armazenar a mensagem que será enviada, adicione uma variável vazia chamada statusToReturn.
function MatchManager.prepareGame()playerManager.sendPlayersToMatch()matchStart:Fire()endfunction MatchManager.getEndStatus(endState)local statusToReturnendmatchStart.Event:Connect(startTimer)matchEnd.Event:Connect(stopTimer)return MatchManagerDefina o valor de statusToReturn usando as declarações if e elseif.Verifique as variáveis de estado final: FoundWinner e TimerUp.Para verificação de erros, inclua um else no final.
function MatchManager.getEndStatus(endState)local statusToReturnif endState == gameSettings.endStates.FoundWinner thenelseif endState == gameSettings.endStates.TimerUp thenelseendendAdicione o seguinte para cada condição:
FoundWinner
- Uma variável para o vencedor usando playerManager.getWinnerName() .
- Atualize statusToReturn com uma string que anuncia o vencedor.
TimerUp
- Atualize statusToReturn com uma string que anuncia o tempo acabou.
Else
- Atualize statusToReturn com uma mensagem de erro caso haja problemas com a obtenção da mensagem do jogo final.
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"endendEnvie de volta a mensagem digitando 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
Exibição e teste
Obtenha o anúncio atualizado no Gerenciador de Jogo e exibi-lo para os jogadores usando o Gerenciador de Exibição.
Abra Gerenciador de Jogo .No loop while verdadeiro, exclua a última declaração de impressão.Então, crie uma variável chamada endStatus.Defina-o igual ao chamando 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)endPara exibir a mensagem retornada no rótulo da GUI, chame displayManager.updateStatus() e passe em endStatus.
local endStatus = matchManager.getEndStatus(endState)displayManager.updateStatus(endStatus)Então o jogo pára para que os jogadores vejam a mensagem, adicione uma espera usando transitionTime .
local endStatus = matchManager.getEndStatus(endState)displayManager.updateStatus(endStatus)task.wait(gameSettings.transitionTime)Inicie um servidor de teste e verifique se os jogadores veem as seguintes mensagens para o tempo até e as condições do jogador vencedor .
A condição acabou o tempo Condição de jogador vencedor
Dicas de solução de problemas
Neste ponto, você não consegue ver as mensagens, tente uma das seguintes abaixo.
- Se a sua mensagem de status final for "Erro encontrado", nenhuma das condições foi bem-sucedida. Verifique o código em MatchManager.getEndStatus().
- Se o status final não for exibido, verifique se task.wait(gameSettings.transitionTime) está após enviar a mensagem para o displayManager.
Começar novas partidas
Antes de iniciar uma nova partida, haverá uma breve transição.Isso dá aos jogadores tempo para ver o status final e torna ser teletransportado para o lobby menos repentino.
No final da transição, os jogadores restantes serão removidos da arena e todo o código será redefinido.Isso garante que os jogadores iniciem a próxima partida com uma versão limpa do jogo.
Lidar com transições
Quando os jogadores se movem para o estado de transição, removam suas armas.
No PlayerManager, encontre as funções locais.Copie e cole o código destacado para removePlayerWeapon().O código removerá a arma de um jogador individual se estiver equipada ativamente ou na mochila do jogador.
local function removePlayerWeapon(whichPlayer)-- Verifique se um jogador existe caso ele se desconecte ou saia.if whichPlayer thenlocal character = whichPlayer.Character-- Se o jogador tiver atualmente em seu personagemlocal weapon = character:FindFirstChild("Weapon")if weapon thenweapon:Destroy()end-- Se o jogador tem a arma em sua mochilalocal backpackWeapon = whichPlayer.Backpack:FindFirstChild("Weapon")if backpackWeapon thenbackpackWeapon:Destroy()endelseprint("No player to remove weapon")endendInicie uma nova função de módulo chamada removeAllWeapons().
function PlayerManager.removeAllWeapons()end-- EventosPlayers.PlayerAdded:Connect(onPlayerJoin)return PlayerManagerNessa função, use um ciclo for para percorrer a tabela de jogadores ativos. No ciclo, chame removePlayerWeapon() e passe o jogador encontrado.
function PlayerManager.removeAllWeapons()for playerKey, whichPlayer in activePlayers doremovePlayerWeapon(whichPlayer)endend
Limpe entre as partidas
Limpeza será sua própria função no MatchManager.Por enquanto, a limpeza usará apenas a função criada anteriormente para remover as armas do jogador.À medida que você expande o jogo, mais pode ser adicionado, como funções para redefinir um mapa que mudou durante uma partida.
Abra o Gerenciador de Partidas. Adicione uma nova função de módulo chamada cleanupMatch(). Nessa função, chame playerManager.removeAllWeapons().
function MatchManager.cleanupMatch()playerManager.removeAllWeapons()endmatchStart.Event:Connect(startTimer)matchEnd.Event:Connect(stopTimer)return MatchManagerEm seguida, chame a função de limpeza.Abra Gerenciador de Jogo e encontre o ciclo while verdadeiro.Então, os jogadores têm armas removidas durante a intermissão final, chame matchManager.cleanupMatch() antes da última 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)endInicie um servidor de teste e execute uma partida. Espere que o tempo acabe e confirme que a arma do jogador é removida durante a intermissão do jogo final.
Durante uma partida Após a partida
Redefinir partidas
Você pode ter notado algumas outras coisas no jogo, como os jogadores ainda estarem na arena depois que uma partida termina.Com a partida limpa, próximo reinicie o jogo.Isso inclui enviar jogadores na arena de volta ao lobby e limpar a mesa de jogadores ativos.Com um reset em vigor, um ciclo de jogo pode executar indefinidamente.
Primeiro, inicie uma função para enviar os jogadores de volta ao lobby.
No Gerenciador de Jogadores:
- Crie uma função de módulo chamada resetPlayers().
- Adicione um loop for para iterar através de jogadores ativos.
- No loop, chame respawnPlayerInLobby() e passe o jogador como parâmetro.
function PlayerManager.resetPlayers()for playerKey, whichPlayer in activePlayers dorespawnPlayerInLobby(whichPlayer)endend-- EventosPlayers.PlayerAdded:Connect(onPlayerJoin)return PlayerManagerCertifique-se de que a tabela activePlayers vazia para a próxima partida, definindo-a igual a {}, que é uma maneira rápida de redefinir para uma tabela vazia.
function PlayerManager.resetPlayers()for playerKey, whichPlayer in activePlayers dorespawnPlayerInLobby(whichPlayer)endactivePlayers = {}endAbra o Gerenciador de Partidas. Codifique uma nova função de módulo chamada resetMatch() e chame playerManager.resetPlayers().
function MatchManager.resetMatch()playerManager.resetPlayers()endmatchStart.Event:Connect(startTimer)matchEnd.Event:Connect(stopTimer)return MatchManagerVolte para Gerenciador de Jogo . No final do loop while verdadeiro, chame 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()endInicie um servidor de teste e execute uma partida. Confirme que você pode pelo menos passar por dois ciclos de jogo sem erros.
Scripts concluídos
Abaixo estão scripts concluídos para verificar duas vezes o seu trabalho.
Script do Gerenciador de Jogo
-- Serviçoslocal ServerStorage = game:GetService("ServerStorage")local Players = game:GetService("Players")-- Scripts de Módulolocal moduleScripts = ServerStorage:WaitForChild("ModuleScripts")local matchManager = require(moduleScripts:WaitForChild("MatchManager"))local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))local displayManager = require(moduleScripts:WaitForChild("DisplayManager"))-- Eventoslocal 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 do Gerenciador de Partida
local MatchManager = {}
-- Serviços
local ServerStorage = game:GetService("ServerStorage")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Scripts de Módulo
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"))
-- Eventos
local events = ServerStorage:WaitForChild("Events")
local matchStart = events:WaitForChild("MatchStart")
local matchEnd = events:WaitForChild("MatchEnd")
-- Valores
local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")
local timeLeft = displayValues:WaitForChild("TimeLeft")
-- Cria um novo objeto de cronômetro para ser usado para acompanhar o tempo da partida.
local myTimer = timer.new()
-- Funções Locais
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
-- Adicionar +1 garante que a exibição do tempo termine em 1 ao invés de 0.
timeLeft.Value = (myTimer:getTimeLeft() + 1) // 1
-- Ao não definir o tempo para espera, oferece um looping mais preciso
task.wait()
end
end
-- Funções de Módulo
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 do Gerenciador de Jogadores
local PlayerManager = {}
-- Serviços
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Móveis
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
-- Eventos
local events = ServerStorage:WaitForChild("Events")
local matchEnd = events:WaitForChild("MatchEnd")
-- Variáveis de Mapa
local lobbySpawn = workspace.Lobby.StartSpawn
local arenaMap = workspace.Arena
local spawnLocations = arenaMap.SpawnLocations
-- Valores
local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")
local playersLeft = displayValues:WaitForChild("PlayersLeft")
-- Variáveis do Jogador
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()
-- Dê uma ferramenta ao jogador
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)
-- Verifique se um jogador existe caso ele se desconecte ou saia.
if whichPlayer then
local character = whichPlayer.Character
-- Se o jogador tiver atualmente em seu personagem
local weapon = character:FindFirstChild("Weapon")
if weapon then
weapon:Destroy()
end
-- Se o jogador tem a arma em sua mochila
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)
-- Obtém um local de spawn e depois remove-o da tabela para que o próximo jogador obtenha o próximo spawn
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
-- Eventos
Players.PlayerAdded:Connect(onPlayerJoin)
return PlayerManager