Limpeza e Redefinição

*Este conteúdo é traduzido por IA (Beta) e pode conter erros. Para ver a página em inglês, clique aqui.

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.

  1. No PlayerManager, inicie uma nova função de módulo chamada getWinnerName().


    function PlayerManager.getWinnerName()
    end
    -- Eventos
    Players.PlayerAdded:Connect(onPlayerJoin)
  2. 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 then
    end
    end
  3. Na 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 then
    return winningPlayer.Name
    else
    return "Error: No winning player found"
    end
    end

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.

  1. 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()
    end
    function MatchManager.getEndStatus(endState)
    local statusToReturn
    end
    matchStart.Event:Connect(startTimer)
    matchEnd.Event:Connect(stopTimer)
    return MatchManager
  2. Defina 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 statusToReturn
    if endState == gameSettings.endStates.FoundWinner then
    elseif endState == gameSettings.endStates.TimerUp then
    else
    end
    end
  3. Adicione 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 statusToReturn
    if endState == gameSettings.endStates.FoundWinner then
    local winnerName = playerManager.getWinnerName()
    statusToReturn = "Winner is : " .. winnerName
    elseif endState == gameSettings.endStates.TimerUp then
    statusToReturn = "Time ran out!"
    else
    statusToReturn = "Error found"
    end
    end
  4. Envie de volta a mensagem digitando return statusToReturn .


    function MatchManager.getEndStatus(endState)
    local statusToReturn
    if endState == gameSettings.endStates.FoundWinner then
    local winnerName = playerManager.getWinnerName()
    statusToReturn = "Winner is : " .. winnerName
    elseif endState == gameSettings.endStates.TimerUp then
    statusToReturn = "Time ran out!"
    else
    statusToReturn = "Error found"
    end
    return statusToReturn
    end

Exibindo e Testando

Obtenha o anúncio atualizado no GameManager e exiba-o aos jogadores usando o DisplayManager.

  1. 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 do
    displayManager.updateStatus("Waiting for Players")
    repeat
    task.wait(gameSettings.intermissionDuration)
    until #Players:GetPlayers() >= gameSettings.minimumPlayers
    displayManager.updateStatus("Get ready!")
    task.wait(gameSettings.transitionTime)
    matchManager.prepareGame()
    local endState = matchEnd.Event:Wait()
    local endStatus = matchManager.getEndStatus(endState)
    end
  2. Para exibir a mensagem retornada no rótulo GUI, chame displayManager.updateStatus() e passe em endStatus .


    local endStatus = matchManager.getEndStatus(endState)
    displayManager.updateStatus(endStatus)
  3. 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)
  4. 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.

    O tempo acabou
    Condição 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.

  1. 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 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
  2. Inicie uma nova função de módulo chamada removeAllWeapons() .


    function PlayerManager.removeAllWeapons()
    end
    -- Eventos
    Players.PlayerAdded:Connect(onPlayerJoin)
    return PlayerManager
  3. Nessa 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 do
    removePlayerWeapon(whichPlayer)
    end
    end

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.

  1. Abra o MatchManager. Adicione uma nova função de módulo chamada cleanupMatch(). Nessa função, chame playerManager.removeAllWeapons().


    function MatchManager.cleanupMatch()
    playerManager.removeAllWeapons()
    end
    matchStart.Event:Connect(startTimer)
    matchEnd.Event:Connect(stopTimer)
    return MatchManager
  2. Em 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 do
    displayManager.updateStatus("Waiting for Players")
    repeat
    task.wait(gameSettings.intermissionDuration)
    until #Players:GetPlayers() >= gameSettings.minimumPlayers
    displayManager.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)
    end
  3. Inicie 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.

    Durante uma partida
    Após a partida

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.

  1. 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 do
    respawnPlayerInLobby(whichPlayer)
    end
    end
    -- Eventos
    Players.PlayerAdded:Connect(onPlayerJoin)
    return PlayerManager
  2. Certifique-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 do
    respawnPlayerInLobby(whichPlayer)
    end
    activePlayers = {}
    end
  3. Abra o MatchManager. Crie uma nova função do módulo chamada resetMatch() e chame playerManager.resetPlayers().


    function MatchManager.resetMatch()
    playerManager.resetPlayers()
    end
    matchStart.Event:Connect(startTimer)
    matchEnd.Event:Connect(stopTimer)
    return MatchManager
  4. Volte para GameManager . No final do loop while true do, chame matchManager.resetMatch().


    while true do
    displayManager.updateStatus("Waiting for Players")
    repeat
    task.wait(gameSettings.intermissionDuration)
    until #Players:GetPlayers() >= gameSettings.minimumPlayers
    displayManager.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
  5. Inicie 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ços
local ServerStorage = game:GetService("ServerStorage")
local Players = game:GetService("Players")
-- Scripts de Módulo
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local matchManager = require(moduleScripts:WaitForChild("MatchManager"))
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
local displayManager = require(moduleScripts:WaitForChild("DisplayManager"))
-- Eventos
local events = ServerStorage:WaitForChild("Events")
local matchEnd = events:WaitForChild("MatchEnd")
while true do
displayManager.updateStatus("Waiting for Players")
repeat
task.wait(gameSettings.intermissionDuration)
until #Players:GetPlayers() >= gameSettings.minimumPlayers
displayManager.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