Las partidas pueden terminar en algunas condiciones, incluyendo temporizadores que se acaban o un solo jugador que se queda.
Gestionar Jugadores Derrotados
Ahora mismo, los jugadores derrotados reaparecen en la arena. En cambio, envíalos de vuelta al lobby para esperar la próxima coincidir.
- En PlayerManager, crea una función local nombrada respawnPlayerInLobby() . En esa función, haz lo siguiendo:
- Establece la propiedad de RespawnLocation del jugador en el lobbySpawn.
- Recarga el personaje con Player:LoadCharacter() . Recuerda, LoadCharacter() recrea al jugador en su regeneración, eliminando cualquier herramienta que tuvieran.
Usando Funciones Anónimas
Las funciones anónimas se utilizan comúnmente en los scripts avanzados en situaciones específicas. Antes de definirlas, es importante comprender una situación que tu script puede encontrar.
Considere esto: Para teletransportar a los jugadores derrotados al lobby, la función de respawn tendrá que estar conectada al evento Died del jugador. Hay un problema sin embargo. Si conecta el evento como lo hacemos en el pasado, no hay manera de obtener el nombre del jugador del evento Died. El script necesita ese nombre para eliminar un jugador derrotado de la tabla de rastreo de jugadores activos.
Para obtener el nombre del jugador que activó el evento Died, usa una función anónima. Las funciones anónimas no tienen nombres, y se pueden crear directamente dentro de Connect() en lugar de separadamente.
Una función anónima de ejemplo está debajo que muestra la sintaxis.
myPlayer.Died:Connect(function()
print(player)
end)
Código del evento muerto
Para esta función, siempre que muera un personaje del jugador, se activará la función que los reaparecerá.
Para obtener acceso al evento Died del jugador, en PlayerManager > preparePlayer(), agregue una variable para el humanoide del jugador.
local function preparePlayer(player, whichSpawn)player.RespawnLocation = whichSpawnplayer:LoadCharacter()local character = player.Character or player.CharacterAdded:Wait()local sword = playerWeapon:Clone()sword.Parent = characterlocal humanoid = character:WaitForChild("Humanoid")endCrea una función anónima que se conecta al evento Died. Empieza por escribir humanoid.Died:Connect() . Luego, dentro Connect() , escribe 1> function()1> , y presiona 4> Enter4> para autocompletar 7> finalizar7> , y elimina la parentesis extra.
local humanoid = character:WaitForChild("Humanoid")humanoid.Died:Connect(function()end)En la función anónima, llame a respawnPlayerInLobby() . Pasar en player, una variable que almacena el jugador listo para entrar a un coincidir.
local humanoid = character:WaitForChild("Humanoid")humanoid.Died:Connect(function()respawnPlayerInLobby(player)end)Inicia un servidor y juega una coincidir. Prueba que cuando un jugador muere, reaparece en el lobby. Para derrotar a los jugadores, acércate a ellos y usa tu arma hasta que puedas confirmar que han reaparecido en el lobby.
Nota, también hay algunas diferentes formas de probar si se desea.
- Para matar a un jugador, en la ventana de salida del servidor > barra de comandos > barra de comandos, copia y pega: workspace.Player1.Humanoid.Health = 0 . Presione Ingrese para ejecutar el comando. Para eliminar a otros jugadores, use Player2, Player3, etc.
- Establecer GameSettings > matchDuration a un tiempo más largo puede darte más tiempo para encontrar y eliminar a todos los jugadores.
- Para tener pruebas más rápidas, cambia GameSettings > minimumPlayers a un número más pequeño, como 2.
Finalizando el juego
Ahora que los jugadores derrotados reaparecen, comience a trabajar en la terminación del juego. ¿Recuerda crear el evento MatchEnd? Se eliminará cuando el temporizador se acabe o se encuentre un ganador.
Para decir a otros scripts que condición terminó el juego, crea una tabla con variables para TimerUp y FoundWinner . Cuando el evento de finalización de la partida se activa, pasará en una variable para que otros scripts puedan responder.
En GameSettings, crea una tabla de módulo vacía llamada endStates .
local GameSettings = {}-- Variables del juegoGameSettings.intermissionDuration = 5GameSettings.matchDuration = 10GameSettings.minimumPlayers = 2GameSettings.transitionTime = 5-- Posibles formas en que el juego puede finalizar.GameSettings.endStates = {}return GameSettingsCree dos variables nombradas TimerUp y FoundWinner . Establece cada una de ellas con una cadena que coincida con su nombre. Estas cadenas se usarán para probar el código.
GameSettings.endStates = {TimerUp = "TimerUp",FoundWinner = "FoundWinner"}
Terminando con un Temporizador
Cuando el temporizador termine, fire el evento de final de la coincidencia y envíe la variable de estado de final de la coincidencia. De ese modo, otros scripts que escuchan para ese evento pueden responder de manera correspondiente. Recuerda que mientras los eventos disparan señales, también puede enviar datos que se reciben al escuchar los scripts, como TimerUp o FoundWinner .
En GameManager , en el mientras cierto ciclo, encuentra la línea matchEnd.Event:Wait() . En el comienzo de la línea, agrega local 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()endPara confirmar que se recibió el estado correcto, agregue una declaración de impresión que incluya 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()print("Game ended with: " .. endState)endEn MatchManager, encuentra timeUp() y eliminar la declaración de impresión. Luego, para disparar el evento de fin de la partida, escribe matchEnd:Fire() y pasa en 1> gameSettings.endSettings.TimerUp1> .
-- Valoreslocal displayValues = ReplicatedStorage:WaitForChild("DisplayValues")local timeLeft = displayValues:WaitForChild("TimeLeft")-- Crea un nuevo objeto de tiempo para usarlo para rastrear el tiempo de la partida.local myTimer = timer.new()-- Funciones localeslocal function timeUp()matchEnd:Fire(gameSettings.endStates.TimerUp)endPrueba un coincidir. Una vez que el temporizador se acabe, asegúrate de que la declaración de impresión incluya la cadena almacenada en la variable TimerUp .
Consejos de solución de problemas
En este momento, el mensaje no se mostró, intenta uno de los siguientes abajo.
- Asegúrese de que, dondequiera que se llamen las variables de estado del final, que estén escritas exactamente, como aquí: gameSettings.endStates.TimerUp .
- Asegúrese de usar : (operador de colon) con el Fire() вместо del operador de punto, como en matchEnd:Fire() .
Cómo codificar un partido ganador
A continuación, el script necesita identificar a los jugadores ganadores, eliminar a los jugadores perdedores y ejecutar limpiezas como detener el temporizador. Las partidas también terminarán si se deja a un jugador. Para ver si se cumple la condición FoundWinner, necesitarás una función que verifique el número restante en la tabla rastreando jugadores en una coincidir.
Checando el número de jugadores
Las partidas terminarán si solo queda un jugador. Para verificar esto, el script necesita rastrear a los jugadores en una ronda. Una vez que un jugador se haya ido, un ganador puede ser asignado.
En PlayerManager, define las siguientes variables:
- Car carpeta
- Módulo GameSettings - Se utiliza para acceder a las variables de estado final
- Evento Folder y el evento MatchEnd - Evento de fuego
local PlayerManager = {}-- Servicioslocal Players = game:GetService("Players")local ServerStorage = game:GetService("ServerStorage")local ReplicatedStorage = game:GetService("ReplicatedStorage")-- Móduloslocal moduleScripts = ServerStorage:WaitForChild("ModuleScripts")local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))-- Eventoslocal events = ServerStorage:WaitForChild("Events")local matchEnd = events:WaitForChild("MatchEnd")Arriba de respawnPlayerInLobby() , añade una nueva función local nombrada checkPlayerCount() .
-- Variables del jugadorlocal activePlayers = {}local playerWeapon = ServerStorage.Weaponlocal function checkPlayerCount()endlocal function respawnPlayerInLobby(player)En dentro de esa función, usa una declaración if para chequear por un ganador. En esa declaración:
- Compruebe si el tamaño de la tabla activePlayers es 1.
- Si es así, <a href=\"#fire matchEnd\">fire</a> y <a href=\"#gameSettings.endSettings.foundWinner\">gameSettings.endSettings.foundWinner</a>.
local function checkPlayerCount()if #activePlayers == 1 thenmatchEnd:Fire(gameSettings.endStates.FoundWinner)endend
Eliminando a un Jugador
No se puede mantener un recuento preciso a menos que los jugadores se eliminen. Cuando un jugador es derrotado, mantenga un recuento de jugadores preciso eliminándolos de la tabla de jugadores. Luego, verifique el tamaño de la mesa de jugadores activa para ver si hay un ganador.
Bajo checkPlayerCount(), crea una nueva función local llamada removeActivePlayer() con un parámetro llamado player .
local function checkPlayerCount()if #activePlayers == 1 thenmatchEnd:Fire(gameSettings.endStates.FoundWinner)endendlocal function removeActivePlayer(player)endPara encontrar al jugador en la tabla activePlayers, haz clic a través de ella usando un bucle for . Luego, agrega una declaración de if que se ejecuta si un jugador que coincide con el nombre ingresa a la función.
local function removeActivePlayer(player)for playerKey, whichPlayer in activePlayers doif whichPlayer == player thenendendendPara eliminar al jugador, en la declaración if:
- Llamar table.remove() . En los paréntesis, pasa en activePlayers , la tabla para mirar y playerKey - el jugador para eliminar de la tabla.
- Establece el valor del objeto playersLeft a #activePlayers .
- Verifique un jugador ganador al ejecutar checkPlayerCount() .
local function removeActivePlayer(player)for playerKey, whichPlayer in activePlayers doif whichPlayer == player thentable.remove(activePlayers, playerKey)playersLeft.Value = #activePlayerscheckPlayerCount()endendend
Conectando Eventos y Pruebas
Para usar la función recién creada, llámanos desde el evento anónimo conectado al jugador.
Encuentra preparePlayer() . En la función anónima con la conexión del evento Died, llama removeActivePlayer() . Luego, pasa el jugador como parámetro.
humanoid.Died:Connect(function()respawnPlayerInLobby(player)removeActivePlayer(player)end)Para ver si se encuentra un jugador ganador, inicia un servidor de prueba . Cuando solo queda un jugador, deberías ver a Ganador en la ventana de salida.
Continúe probando y deje que finalizarel partido. Observe como comienza un nuevo partido, un error aparece en la ventana de salida:
Este error se debe a que el temporizador no se detuvo, lo cual se arreglará en la siguiente sección.
Detener el temporizador
Cada vez que termina un partido con un jugador ganador, el temporizador debería detenerse también. Para detener el temporizador antes de que se acabe el tiempo, haz que el temporizador se detenga cuando se activa el evento de finalización del partido. Este es uno de los beneficios de crear eventos. Se pueden reutilizar en múltiples situaciones para iniciar relaciones de causa y efecto.
En MatchManager, crea una nueva función local nombrada stopTimer() . Dentro, escribe myTimer:stop() para detener el temporizador.
-- Crea un nuevo objeto de tiempo para usarlo para rastrear el tiempo de la partida.local myTimer = timer.new()-- Funciones localeslocal function stopTimer()myTimer:stop()endlocal function timeUp()matchEnd:Fire(gameSettings.endStates.TimerUp)endPara detener el temporizador cuando termine el partido, conecta el evento de finalización del partido a stopTimer() .
-- Funciones de módulofunction MatchManager.prepareGame()playerManager.sendPlayersToMatch()matchStart:Fire()endmatchStart.Event:Connect(startTimer)matchEnd.Event:Connect(stopTimer)return MatchManagerPrueba que el error anterior ya no aparece al iniciar un servidor . Elimina todo menos un jugador y luego espera unos segundos una vez que termine la partida.
Siguiente pasos
Mientras que las dos condiciones de victoria están terminadas, todavía hay algunas tareas restantes para terminar el ciclo de juego. Por instancia, el jugador ganador nunca se teletransporta al lobby. En la siguiente lección, mostrarás cómo terminó el partido para los jugadores y restablecerás el juego, finalmente completando todo el ciclo.
Scripts Completados
A continuación, están los scripts completados para revisar tu trabajo.
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
-- Funciones locales
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
-- Funciones 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
Script de GameSettings
local GameSettings = {}-- Variables del juegoGameSettings.intermissionDuration = 5GameSettings.matchDuration = 10GameSettings.minimumPlayers = 2GameSettings.transitionTime = 5-- Posibles formas en que el juego puede finalizar.GameSettings.endStates = {TimerUp = "TimerUp",FoundWinner = "FoundWinner"}return GameSettings
Script de GameManager
-- Servicioslocal 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()print("Game ended with: " .. endState)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 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 tiempo para usarlo 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()
print("Timer started")
myTimer:start(gameSettings.matchDuration)
myTimer.finished:Connect(timeUp)
while myTimer:isRunning() do
-- Añadiendo +1 asegura que la pantalla de tiempo muestre 1 en lugar de 0.
timeLeft.Value = (math.floor(myTimer:getTimeLeft() + 1))
-- Al no configurar el tiempo para esperar, ofrece más preciso flujo
task.wait()
end
end
-- Funciones de módulo
function MatchManager.prepareGame()
playerManager.sendPlayersToMatch()
matchStart:Fire()
end
matchStart.Event:Connect(startTimer)
matchEnd.Event:Connect(stopTimer)
return MatchManager