Limpieza y reinicio

*Este contenido se traduce usando la IA (Beta) y puede contener errores. Para ver esta página en inglés, haz clic en aquí.

Hora de codificar la última fase del juego: limpieza y reinicio.El código en esta fase garantiza que los bucles del juego pasen a intermedio y que los partidos futuros comiencen igual para cada jugador.

Actualizar la interfaz gráfica

Antes de hacer limpieza y reinicio, informa a los jugadores cómo terminó el juego usando el Administrador de pantalla para mostrar el estado apropiado.

Obtener el nombre del ganador

Comience por obtener el nombre del jugador ganador si hubo uno.Anteriormente, el código verificaba si el tamaño de la tabla de jugadores activos era de 1.Para obtener el nombre del jugador restante, devuelve el nombre en el primer índice de esa tabla.

  1. En PlayerManager, inicia una nueva función de módulo llamada getWinnerName().


    function PlayerManager.getWinnerName()
    end
    -- Eventos
    Players.PlayerAdded:Connect(onPlayerJoin)
  2. Añade una declaración if que se ejecuta si algo existe en activePlayers[1] .Aunque el recuento de tablas se verificó antes, el jugador podría haberse desconectado o abandonado el juego.


    function PlayerManager.getWinnerName()
    local winningPlayer = activePlayers[1]
    if winningPlayer then
    end
    end
  3. En la declaración if:

    • Devuelve el nombre del jugador.
    • Para lo demás, devuelve una cadena de errores.

    function PlayerManager.getWinnerName()
    local winningPlayer = activePlayers[1]
    if winningPlayer then
    return winningPlayer.Name
    else
    return "Error: No winning player found"
    end
    end

Obtener el estado final

Usa una función de módulo para tomar información del estado final correcto, ya sea que termine el temporizador o se deje a un jugador.Luego, envíe esa variable de estado al gestor de pantalla para actualizar la interfaz de estado con el mensaje apropiado.

  1. En MatchManager , codifica una nueva función de módulo llamada getEndStatus() con un parámetro llamado endState.Para almacenar el mensaje que se enviará, agregue una variable vacía llamada 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. Establece el valor de statusToReturn usando las declaraciones if y elseif.Compruebe las variables de estado final: FoundWinner y TimerUp.Para verificación de errores, incluya un else al final.


    function MatchManager.getEndStatus(endState)
    local statusToReturn
    if endState == gameSettings.endStates.FoundWinner then
    elseif endState == gameSettings.endStates.TimerUp then
    else
    end
    end
  3. Añade lo siguiente para cada condición:

    FoundWinner

    • Una variable para el ganador usando playerManager.getWinnerName() .
    • Actualizar statusToReturn con una cadena que anuncia al ganador.

    TimerUp

    • Actualizar statusToReturn con una cadena que anuncia que el tiempo se agotó.

    Else

    • Actualizar statusToReturn con un mensaje de error en caso de que haya problemas con la obtención del mensaje del juego final.

    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. Envíe de vuelta el mensaje escribiendo 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

Mostrar y probar

Obtenga el anuncio actualizado en GameManager y muéstralo a los jugadores usando el DisplayManager.

  1. Abre GameManager .En el bucle while verdadero, elimina la última declaración de impresión.Luego, crea una variable llamada endStatus.Establezca igual a llamar 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 mostrar el mensaje devuelto en la etiqueta GUI, llame a displayManager.updateStatus() y pase en endStatus .


    local endStatus = matchManager.getEndStatus(endState)
    displayManager.updateStatus(endStatus)
  3. Así que el juego se detiene para que los jugadores vean el mensaje, agrega una espera usando transitionTime .


    local endStatus = matchManager.getEndStatus(endState)
    displayManager.updateStatus(endStatus)
    task.wait(gameSettings.transitionTime)
  4. Inicie un servidor de prueba y verifique que los jugadores vean los siguientes mensajes para el tiempo transcurrido y las condiciones del jugador ganador .

    La condición de tiempo ha expirado
    Condición de jugador ganador

Consejos de solución de problemas

En este punto, no puedes ver los mensajes, prueba uno de los siguientes a continuación.

  • Si tu mensaje de estado final es "Error encontrado", ninguna de las condiciones tuvo éxito. Comprueba el código en MatchManager.getEndStatus().
  • Si el estado final no se muestra, compruebe que task.wait(gameSettings.transitionTime) está después de enviar el mensaje a displayManager.

Iniciar nuevas partidas

Antes de comenzar una nueva partida, habrá una breve transición.Esto da tiempo a los jugadores para ver el estado final y hace que ser teletransportados al vestíbulo se sienta menos repentino.

Al final de la transición, los jugadores restantes serán eliminados de la arena y todo el código se reiniciará.Esto garantiza que los jugadores inicien la siguiente partida con una versión limpia del juego.

Gestionar transiciones

Cuando los jugadores se mueven al estado de transición, elimina sus armas.

  1. En PlayerManager, encuentra las funciones locales.Copia y pega el código resaltado para removePlayerWeapon() abajo.El código eliminará el arma de un jugador individual si está equipado activamente o en la mochila del jugador.


    local function removePlayerWeapon(whichPlayer)
    -- Compruebe si existe un jugador en caso de que se desconectara o se fuera.
    if whichPlayer then
    local character = whichPlayer.Character
    -- Si el jugador lo tiene actualmente en su personaje
    local weapon = character:FindFirstChild("Weapon")
    if weapon then
    weapon:Destroy()
    end
    -- Si el jugador tiene la arma en su mochila
    local backpackWeapon = whichPlayer.Backpack:FindFirstChild("Weapon")
    if backpackWeapon then
    backpackWeapon:Destroy()
    end
    else
    print("No player to remove weapon")
    end
    end
  2. Inicia una nueva función de módulo llamada removeAllWeapons().


    function PlayerManager.removeAllWeapons()
    end
    -- Eventos
    Players.PlayerAdded:Connect(onPlayerJoin)
    return PlayerManager
  3. En esa función, utilice un bucle for para recorrer la tabla de jugadores activos. En el bucle, llame a removePlayerWeapon() y pase el jugador encontrado.


    function PlayerManager.removeAllWeapons()
    for playerKey, whichPlayer in activePlayers do
    removePlayerWeapon(whichPlayer)
    end
    end

Limpiar entre partidos

La limpieza será su propia función en MatchManager.Por ahora, la limpieza solo usará esa función previamente creada para eliminar las armas de los jugadores.A medida que expandes el juego, se pueden agregar más, como funciones para restablecer un mapa que cambió durante una partida.

  1. Abre el administrador de partidos. Añade una nueva función de módulo llamada cleanupMatch() . En esa función, llama playerManager.removeAllWeapons() .


    function MatchManager.cleanupMatch()
    playerManager.removeAllWeapons()
    end
    matchStart.Event:Connect(startTimer)
    matchEnd.Event:Connect(stopTimer)
    return MatchManager
  2. A continuación, llame a la función de limpieza.Abre GameManager y encuentra el bucle while verdadero.Así que los jugadores tienen armas eliminadas durante el intermedio del final, llama a matchManager.cleanupMatch() antes del ú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. Inicia un servidor de prueba y ejecuta una partida. Espera a que el temporizador se agote y confirma que la arma del jugador se elimina durante la interrupción del juego final.

    Durante una partida
    Después del partido

Reiniciar coincidencias

Es posible que haya notado algunas otras cosas en el juego, como que los jugadores sigan en la arena después de que termine un partido.Con la coincidencia limpia, reinicie el juego siguiente.Esto incluye enviar a los jugadores en la arena de vuelta al vestíbulo y despejar la tabla de jugadores activos.Con un reinicio en lugar, un bucle de juego puede ejecutarse indefinidamente.

Primero, inicia una función para devolver a los jugadores al vestíbulo.

  1. En PlayerManager:

    • Crea una función de módulo llamada resetPlayers().
    • Añade un bucle for para iterar a través de jugadores activos.
    • En el bucle, llama a respawnPlayerInLobby() y pasa al jugador como parámetro.

    function PlayerManager.resetPlayers()
    for playerKey, whichPlayer in activePlayers do
    respawnPlayerInLobby(whichPlayer)
    end
    end
    -- Eventos
    Players.PlayerAdded:Connect(onPlayerJoin)
    return PlayerManager
  2. Asegúrese de que la tabla activePlayers vacía para la próxima partida al establecerla igual a {}, que es una manera rápida de restablecer a una tabla vacía.


    function PlayerManager.resetPlayers()
    for playerKey, whichPlayer in activePlayers do
    respawnPlayerInLobby(whichPlayer)
    end
    activePlayers = {}
    end
  3. Abre el administrador de partidos. Codifica una nueva función de módulo llamada resetMatch() y llama playerManager.resetPlayers() .


    function MatchManager.resetMatch()
    playerManager.resetPlayers()
    end
    matchStart.Event:Connect(startTimer)
    matchEnd.Event:Connect(stopTimer)
    return MatchManager
  4. Vuelve a GameManager . Al final del bucle while verdadero, llama 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. Inicia un servidor de prueba y ejecuta una partida. Confirma que puedes pasar por lo menos por dos bucles de juego sin errores.

Guiones completados

A continuación, se completan los scripts para verificar doblemente tu trabajo.

Script del administrador del juego


-- Servicios
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

Guión de MatchManager


local MatchManager = {}
-- Servicios
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")
-- Crea un nuevo objeto de temporizador para usar para rastrear el tiempo de la partida.
local myTimer = timer.new()
-- Funciones locales
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
-- Añadir +1 asegura que la pantalla del temporizador termine en 1 en lugar de 0.
timeLeft.Value = (myTimer:getTimeLeft() + 1) // 1
-- Al no establecer el tiempo para esperar, ofrece un ciclo más preciso
task.wait()
end
end
-- Funciones 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 de PlayerManager


local PlayerManager = {}
-- Servicios
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")
-- Variables 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")
-- Variables del jugador
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()
-- Darle al jugador una herramienta
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)
-- Compruebe si existe un jugador en caso de que se desconectara o se fuera.
if whichPlayer then
local character = whichPlayer.Character
-- Si el jugador lo tiene actualmente en su personaje
local weapon = character:FindFirstChild("Weapon")
if weapon then
weapon:Destroy()
end
-- Si el jugador tiene la arma en su 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)
-- Obtiene una ubicación de generación y luego la elimina de la tabla para que el próximo jugador obtenga el siguiente punto de generación
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