Terminar partidas

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

Partidas podem terminar em algumas condições, incluindo o tempo acabando ou um único jogador sendo deixado.

Gerenciar jogadores derrotados

No momento, jogadores derrotados respawnam na arena. Em vez disso, envie-os de volta ao lobby para esperar pela próxima conferir.

  1. No PlayerManager, crie uma função local chamada respawnPlayerInLobby(). Nessa função, faça o seguindo:
  • Defina a propriedade RespawnLocation do jogador para o lobbySpawn.
  • Recarregue o personagem com Player:LoadCharacter() . Lembre-se, LoadCharacter() recria o jogador em seu Gerar, removendo quaisquer ferramentas que eles tinham.

Usar funções anônimas

Funções anônimas são comumente usadas em scripts avançados sob situações específicas.Antes de definir eles, é importante entender uma situação que seu script pode encontrar.

Considere isso: Para teletransportar jogadores derrotados para o lobby, a função de respawn terá que ser conectada ao evento Died do jogador.Há um problema, porém.Se você conectar o evento como temos no passado, não há como obter o nome do jogador do evento Died.O script precisa desse nome para remover um jogador derrotado da tabela de rastreamento de jogadores ativos.

Para obter o nome do jogador que disparou o evento Died, use uma função anônima. Funções anônimas não têm nomes e podem ser criadas diretamente dentro de Connect() em vez de separadamente.

Uma função anônima de amostra está abaixo que mostra a síntese.


myPlayer.Died:Connect(function()
print(player)
end)

Codifique o evento de morte

Para essa função, sempre que o personagem de um jogador morre, ele ativará a função que o respawna.

  1. Para obter acesso ao evento Died do jogador, no PlayerManager > preparePlayer(), adicione uma variável para o humanoide do jogador.


    local function preparePlayer(player, whichSpawn)
    player.RespawnLocation = whichSpawn
    player:LoadCharacter()
    local character = player.Character or player.CharacterAdded:Wait()
    local sword = playerWeapon:Clone()
    sword.Parent = character
    local humanoid = character:WaitForChild("Humanoid")
    end
  2. Crie uma função anônima que se conecte ao evento Died.Comece digitando humanoid.Died:Connect().Então, dentro de Connect() , digite function() , pressione Enter para preencher automaticamente end e exclua a vírgula extra.


    local humanoid = character:WaitForChild("Humanoid")
    humanoid.Died:Connect(function()
    end)
  3. Na função anônima, chame respawnPlayerInLobby(). Passe em player, uma variável que armazena o jogador se preparando para entrar em uma conferir.


    local humanoid = character:WaitForChild("Humanoid")
    humanoid.Died:Connect(function()
    respawnPlayerInLobby(player)
    end)
  4. Inicie um servidor e jogue uma conferir.Teste quando um jogador morre, ele respawna no lobby.Para derrotar os jogadores, caminhe até eles e use sua arma até confirmar que eles respawnaram no lobby.

    Atacando o Jogador2
    Jogador2 no Lobby depois de respawnar

Observe, também existem algumas maneiras diferentes de testar se desejado.

  • Para matar um jogador, na janela Servidor > Saída > Barra de Comando, copie e cole: workspace.Player1.Humanoid.Health = 0 .Pressione Enter para executar o comando.Para remover outros jogadores, use Player2, Player3, etc.
  • Definir GameSettings > para um tempo mais longo pode lhe dar mais tempo para encontrar e eliminar todos os jogadores.
  • Para ter testes mais rápidos, altere GameSettings > minimumPlayers para um número menor, como 2.

Termine o jogo

Agora que os jogadores derrotados respawnaram, comece a trabalhar para terminar o jogo.Lembra de criar o evento MatchEnd? Ele será disparado quando o tempo acabar ou um vencedor for encontrado.

Para dizer a outros scripts qual condição terminou o jogo, crie uma tabela com variáveis para TimerUp e FoundWinner.Quando o evento de fim de partida é disparado, ele passará em uma variável para que outros scripts possam responder.

  1. Em Configurações do Jogo, crie uma tabela de módulo vazia chamada endStates .


    local GameSettings = {}
    -- Variáveis do jogo
    GameSettings.intermissionDuration = 5
    GameSettings.matchDuration = 10
    GameSettings.minimumPlayers = 2
    GameSettings.transitionTime = 5
    -- Maneiras possíveis que o jogo pode terminar/parar/sair.
    GameSettings.endStates = {
    }
    return GameSettings
  2. Crie duas variáveis chamadas TimerUp e FoundWinner. Defina cada uma para uma string que corresponda ao seu nome. Essas strings serão usadas para testar o código.


GameSettings.endStates = {
TimerUp = "TimerUp",
FoundWinner = "FoundWinner"
}

Termine com um temporizador

Quando o cronômetro termina, dispare o evento Fim de Partida e envie a variável de estado de fim correspondente.Dessa forma, outros scripts que estão ouvindo esse evento podem responder de acordo.Lembre-se que, enquanto eventos disparam sinais de fogo, também podem enviar dados que são recebidos por scripts de escuta, como TimerUp ou FoundWinner.

  1. Em Gerenciador de Jogo , no while verdadeiro do loop, encontre a linha matchEnd.Event:Wait(). No início da linha, adicione local 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()
    end
  2. Para confirmar que o estado correto foi recebido, adicione uma declaração de impressão incluindo 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()
    print("Game ended with: " .. endState)
    end
  3. No MatchManager, encontre timeUp() e remova a declaração de impressão.Então, para disparar o evento de fim da partida, digite matchEnd:Fire() e passe em gameSettings.endStates.TimerUp.


    -- 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 timeUp()
    matchEnd:Fire(gameSettings.endStates.TimerUp)
    end
  4. Teste uma conferir. Uma vez que o tempo acaba, verifique se a declaração de impressão inclui a string armazenada na variável TimerUp.

Dicas de solução de problemas

Neste ponto, a mensagem não foi exibida, tente uma das seguintes abaixo.

  • Verifique que, onde quer que as variáveis de estado final sejam chamadas, elas sejam escritas exatamente, como aqui: gameSettings.endStates.TimerUp .
  • Certifique-se de usar : (operador de coluna) com o em vez do operador de ponto, como em .

Codifique uma conferirvencedora

Em seguida, o script precisa identificar jogadores vencedores, remover jogadores perdedores e executar limpeza, como parar o cronômetro.Partidas também terminarão se um jogador for deixado.Para ver se a condição FoundWinner é atendida, você precisará de uma função que verifique o número deixado na tabela rastreando jogadores em uma conferir.

Verifique o número de jogadores

As partidas terminarão se restar apenas um jogador.Para verificar isso, o script precisa rastrear os jogadores em uma rodada.Uma vez que um jogador é deixado, um vencedor pode ser designado.

  1. No PlayerManager, defina as seguintes variáveis:

    • Pasta ModuleScripts
    • Módulo GameSettings - Usado para acessar variáveis de estado final
    • Pasta de eventos e o evento MatchEnd - Evento de incêndio

    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")
  2. Acima de respawnPlayerInLobby(), adicione uma nova função local chamada checkPlayerCount().


    -- Variáveis do Jogador
    local activePlayers = {}
    local playerWeapon = ServerStorage.Weapon
    local function checkPlayerCount()
    end
    local function respawnPlayerInLobby(player)
  3. Dentro dessa função, use uma declaração if então para verificar um vencedor. Nessa declaração:

    • Verifique se o tamanho da tabela activePlayers é 1.
    • Se assim for, dispare matchEnd e passe em gameSettings.endStates.FoundWinner.

    local function checkPlayerCount()
    if #activePlayers == 1 then
    matchEnd:Fire(gameSettings.endStates.FoundWinner)
    end
    end

Remova um jogador

Uma contagem precisa não pode ser mantida a menos que os jogadores sejam removidos.Quando um jogador é derrotado, mantenha um contagem precisa de jogadores removendo-os da tabela de jogadores.Então, verifique o tamanho da tabela de jogadores ativos para ver se há um vencedor.

  1. Abaixo de checkPlayerCount(), crie uma nova função local chamada removeActivePlayer() com um parâmetro chamado player .


    local function checkPlayerCount()
    if #activePlayers == 1 then
    matchEnd:Fire(gameSettings.endStates.FoundWinner)
    end
    end
    local function removeActivePlayer(player)
    end
  2. Para encontrar o jogador na tabela activePlayers, itere através dela usando um for loop.Então, adicione uma declaração if que será executada se um jogador que corresponde ao nome for encontrado na função.


    local function removeActivePlayer(player)
    for playerKey, whichPlayer in activePlayers do
    if whichPlayer == player then
    end
    end
    end
  3. Para remover o jogador, na declaração if:

    • Chame table.remove() . Dentro das vírgulas, passe em activePlayers , a tabela para olhar, e playerKey - o jogador para remover da tabela.
    • Defina o valor do objeto playersLeft para #activePlayers.
    • Verifique um jogador vencedor executando checkPlayerCount() .

    local function removeActivePlayer(player)
    for playerKey, whichPlayer in activePlayers do
    if whichPlayer == player then
    table.remove(activePlayers, playerKey)
    playersLeft.Value = #activePlayers
    checkPlayerCount()
    end
    end
    end

Conectar eventos e testar

Para usar a função acabada de criar, chame-a a partir da função anônima conectada ao evento Died do jogador.

  1. Encontre preparePlayer() . Na função anônima com a conexão do evento Died, chame removeActivePlayer() . Então, passe o jogador como parâmetro.


    humanoid.Died:Connect(function()
    respawnPlayerInLobby(player)
    removeActivePlayer(player)
    end)
  2. Para ver se um jogador vencedor é encontrado, inicie um servidor de teste .Quando há apenas um jogador restante, você deve ver FoundWinner na janela de Saída.

  3. Continue testando e deixe a partida terminar/parar/sair. Observe como uma nova partida começa, um erro aparece na janela de Saída:

Este erro ocorre porque o cronômetro não foi interrompido, o que será corrigido na próxima seção.

Pare o relógio

Sempre que uma partida termina com um jogador vencedor, o cronômetro deve parar também.Para interromper o cronômetro antes que o tempo acabe, faça com que o cronômetro pare sempre que o evento de fim de partida for disparado.Este é um dos benefícios de criar eventos.Eles podem ser reutilizados em várias situações para script causar e efeito relações.

  1. No MatchManager, crie uma nova função local chamada stopTimer() . Dentro, digite myTimer:stop() para interromper o cronômetro.


    -- 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
  2. Para interromper o cronômetro quando a partida terminar, conecte o evento matchEnd ao stopTimer().


    -- Funções de Módulo
    function MatchManager.prepareGame()
    playerManager.sendPlayersToMatch()
    matchStart:Fire()
    end
    matchStart.Event:Connect(startTimer)
    matchEnd.Event:Connect(stopTimer)
    return MatchManager
  3. Teste que o erro anterior não aparece mais ao iniciar um servidor .Elimine todos, exceto um jogador e então espere alguns segundos após o fim da partida.

Próximos passos

Enquanto as duas condições de vitória estão terminadas, ainda há algumas tarefas para terminar o ciclo do jogo.Por instância, o jogador vencedor nunca é teletransportado para o lobby.Na próxima lição, você mostrará como a partida terminou para os jogadores e redefinirá o jogo, finalizando, finalmente, todo o ciclo.

Scripts concluídos

Abaixo estão scripts concluídos para verificar duas vezes o seu trabalho.

scriptdo 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
-- Funções Locais
local function checkPlayerCount()
if #activePlayers == 1 then
matchEnd:Fire(gameSettings.endStates.FoundWinner)
end
end
local function removeActivePlayer(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 onPlayerJoin(player)
player.RespawnLocation = lobbySpawn
end
local function preparePlayer(player, whichSpawn)
player.RespawnLocation = whichSpawn
player:LoadCharacter()
local character = player.Character or player.CharacterAdded:Wait()
local sword = playerWeapon:Clone()
sword.Parent = character
local humanoid = character:WaitForChild("Humanoid")
humanoid.Died:Connect(function()
respawnPlayerInLobby(player)
removeActivePlayer(player)
end)
end
-- Funções de Módulo
function PlayerManager.sendPlayersToMatch()
local arenaSpawns = spawnLocations:GetChildren()
for playerKey, whichPlayer in Players:GetPlayers() do
table.insert(activePlayers, whichPlayer)
local spawnLocation = table.remove(arenaSpawns, 1)
preparePlayer(whichPlayer, spawnLocation)
end
playersLeft.Value = #activePlayers
end
-- Eventos
Players.PlayerAdded:Connect(onPlayerJoin)
return PlayerManager

scriptde Configurações do Jogo


local GameSettings = {}
-- Variáveis do jogo
GameSettings.intermissionDuration = 5
GameSettings.matchDuration = 10
GameSettings.minimumPlayers = 2
GameSettings.transitionTime = 5
-- Maneiras possíveis que o jogo pode terminar/parar/sair.
GameSettings.endStates = {
TimerUp = "TimerUp",
FoundWinner = "FoundWinner"
}
return GameSettings

scriptdo Gerenciador de Jogo


-- 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()
print("Game ended with: " .. endState)
end

scriptdo 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 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()
print("Timer started")
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
matchStart.Event:Connect(startTimer)
matchEnd.Event:Connect(stopTimer)
return MatchManager