Hora de codificar a última fase do jogo: limpeza e redefinir. O código nesta fase garante que os loops do jogo sejam interrompidos e que as partidas futuras comecem da mesma maneira para cada jogador.
Atualizando a Interface gráfica do usuário
Antes de fazer a limpeza e redefinir, informe os jogadores como o jogo terminou usando o DisplayManager para mostrar o status apropriado.
Obtendo o Nome do Vencedor
Comece obtendo o nome do jogador vencedor, se houver um. Anteriormente, o código verificou se o tamanho da mesa de jogadores ativos era inferior a 1. Para obter o nome do jogador restante, devolva o nome no primeiro índice dessa 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 funciona se algo existir em activePlayers[1] . Embora a contagem de mesas tenha sido verificada antes, o jogador pode ter se desconectado ou saído do jogo.
function PlayerManager.getWinnerName()local winningPlayer = activePlayers[1]if winningPlayer thenendendNa declaração if:
- Retorna o nome do jogador.
- Para o outro, devolva uma string / cadeia / textode erro.
function PlayerManager.getWinnerName()local winningPlayer = activePlayers[1]if winningPlayer thenreturn winningPlayer.Nameelsereturn "Error: No winning player found"endend
Conseguindo o Status Final
Use uma função de módulo para obter informações do estado final correto, seja o timer terminando ou um jogador restante. Em seguida, envie essa variável de estado ao DisplayManager para atualizar o status da GUI com a mensagem apropriada.
Em MatchManager , codifique 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 declarações if e elseif. Verifique se há variáveis de estado final: FoundWinner e TimerUp. Para verificação de erro, inclua outra no terminar/parar/sair.
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 anunciando o vencedor.
TimerUp
- Atualize statusToReturn com uma string anunciando que o tempo acabou.
Else
- Atualize statusToReturn com uma mensagem de erro no caso de haver problemas com a obtenção da mensagem de fim do jogo.
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
Exibindo e Testando
Obtenha o anúncio atualizado no GameManager e exiba-o aos jogadores usando o DisplayManager.
Abra GameManager . No loop while true do, apague a última instrução de impressão. Em seguida, crie uma variável chamada endStatus. Defina isso como 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 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 vêem as seguintes mensagens para o tempo restante e as condições do jogador vencedor.
Dicas de solução de problemas
Neste ponto, você não pode ver as mensagens, tente uma das seguintes opções 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() contra as amostras de código.
- Se o status final não for exibido, verifique se task.wait(gameSettings.transitionTime) está após enviar a mensagem ao displayManager.
Começando Novas Partidas
Antes de iniciar uma nova conferir, haverá uma breve transição. Isso dá aos jogadores tempo para ver o status final e faz com que ser teletransportado para o lobby se sinta menos repentino.
No final da transição, os jogadores restantes serão removidos da arena e todo o código será redefinir. Isso garante que os jogadores comecem a próxima partida com uma versão limpa do jogo.
Transições de manipulação
Quando os jogadores entrarem no estado de transição, remova suas armas.
No PlayerManager, encontre as funções locais. Copie e cole o código destacado para removePlayerWeapon() abaixo. O código removerá a arma de um jogador individual se estiver ativamente equipada 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 tem atualmente em seu personagemlocal weapon = character:FindFirstChild("Weapon")if weapon thenweapon:Destroy()end-- Se o jogador tiver a arma na 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 loop para passar pela mesa de jogadores ativos. No loop, chame removePlayerWeapon() e passe no jogador encontrado.
function PlayerManager.removeAllWeapons()for playerKey, whichPlayer in activePlayers doremovePlayerWeapon(whichPlayer)endend
Limpeza entre Partidas
A limpeza será sua própria função no MatchManager. Por enquanto, a limpeza usará apenas a função criada anteriormente para remover as armas dos jogadores. À medida que você expande o jogo, mais podem ser adicionados, como funções para redefinir um mapa que mudou durante uma conferir.
Abra o MatchManager. 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 GameManager e encontre o loop while true do. Então os jogadores têm as armas removidas durante o intervalo final, chame matchManager.cleanupMatch() antes do último 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 corra uma conferir. Espere o tempo acabar e confirme que a arma do jogador é removida durante o intervalo de fim de jogo.
Reiniciando Partidas
Você pode ter notado algumas outras coisas no jogo, como jogadores ainda estando na arena após o final de uma partida. Com a partida limpa, a próxima reinicialização do jogo. Isso inclui enviar jogadores na arena de volta para o lobby e limpar a mesa de jogadores ativos. Com uma reinicialização no local, um loop de jogo pode correr indefinidamente.
Primeiro, inicie uma função para enviar jogadores de volta para o lobby.
No Gerenciador de Jogadores:
- Crie uma função de módulo chamada resetPlayers()
- Adicione um loop para iterar através dos jogadores ativos.
- No loop, chame respawnPlayerInLobby() e passe no 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 mesa activePlayers esteja vazia para a próxima partida configurando-a como {} , que é uma maneira rápida de redefinir para uma mesa vazia.
function PlayerManager.resetPlayers()for playerKey, whichPlayer in activePlayers dorespawnPlayerInLobby(whichPlayer)endactivePlayers = {}endAbra o MatchManager. Crie uma nova função do módulo chamada resetMatch() e chame playerManager.resetPlayers().
function MatchManager.resetMatch()playerManager.resetPlayers()endmatchStart.Event:Connect(startTimer)matchEnd.Event:Connect(stopTimer)return MatchManagerVolte para GameManager . No final do loop while true do, 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 corra uma conferir. Confirme que você pode pelo menos passar por dois loops de jogo sem erros.
Scripts Concluídos
Abaixo estão scripts completos para verificar novamente seu trabalho.
Script do Gerenciador de Jogos
-- 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 Gerente de Partidas
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 temporizador 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 cronômetro termine em 1 em vez de 0.
timeLeft.Value = (math.floor(myTimer:getTimeLeft() + 1))
-- Ao não definir o tempo de espera, oferece um loop mais preciso
task.wait()
end
end
-- Funções do 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
Scripts do Gerente de Jogadores
local PlayerManager = {}
-- Serviços
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Módulos
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
-- Eventos
local events = ServerStorage:WaitForChild("Events")
local matchEnd = events:WaitForChild("MatchEnd")
-- Variáveis do 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ê ao jogador uma ferramenta
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 tem atualmente em seu personagem
local weapon = character:FindFirstChild("Weapon")
if weapon then
weapon:Destroy()
end
-- Se o jogador tiver a arma na 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 o remove da mesa para que o próximo jogador receba o próximo Gerar
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