Las partidas pueden terminar en unas pocas condiciones, incluidos los temporizadores que se agotan o un jugador único que se queda.
Administrar jugadores derrotados
En este momento, los jugadores derrotados reaparecen en la arena. En cambio, envíelos de vuelta al vestíbulo para esperar la siguiente coincidir.
- En PlayerManager, crea una función local llamada respawnPlayerInLobby(). En esa función, haz lo siguiendo:
- Establece la propiedad RespawnLocation del jugador en el lobbySpawn.
- Recarga el personaje con Player:LoadCharacter() . Recuerda, LoadCharacter() recrea al jugador en su punto de aparición, eliminando cualquier herramienta que tuvieran.
Usar funciones anónimas
Las funciones anónimas se utilizan comúnmente en scripts avanzados bajo situaciones específicas.Antes de definirlos, es importante comprender una situación que tu guión pueda encontrar.
Considera esto: para teletransportar a los jugadores derrotados al vestíbulo, la función de reaparición tendrá que estar conectada al evento de muerte del jugador.Hay un problema, sin embargo.Si conectas el evento como tenemos en el pasado, no hay forma de obtener el nombre del jugador del evento Fallecido.El script necesita ese nombre para eliminar a un jugador derrotado de la tabla que rastrea a jugadores activos.
Para obtener el nombre del jugador que activó el evento Fallecido, utilice 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 muestra está debajo que muestra la sintaxis.
myPlayer.Died:Connect(function()
print(player)
end)
Codifica el evento de muerte
Para esta función, cada vez que el personaje de un jugador muera, activará la función que lo respawna.
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.Comience escribiendo humanoid.Died:Connect() .Luego, dentro de Connect() , escriba function() , presione Enter para completar automáticamente end , y elimine la coma extra.
local humanoid = character:WaitForChild("Humanoid")humanoid.Died:Connect(function()end)En la función anónima, llama a respawnPlayerInLobby(). Pasa en player , una variable que almacena al jugador que se prepara para entrar en una 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 vestíbulo.Para derrotar a los jugadores, camina hacia ellos y usa tu arma hasta que puedas confirmar que han reaparecido en el vestíbulo.
Atacando a Player2 Jugador2 en el vestíbulo después de reaparecer
Tenga en cuenta, también hay algunas formas diferentes de probar si lo desea.
- Para matar a un jugador, en la ventana Servidor > Salida > Barra de comandos, copia y pega: workspace.Player1.Humanoid.Health = 0 .Presione Enter para ejecutar el comando.Para eliminar a otros jugadores, usa Player2, Player3, etc.
- Establecer GameSettings > matchDuration a un tiempo más largo puede darte más tiempo para encontrar y sacar a todos los jugadores.
- Para tener pruebas más rápidas, cambia GameSettings > minimumPlayers a un número más pequeño, como 2.
Termina el juego
Ahora que los jugadores derrotados reaparecieron, comienza a trabajar en terminar el juego.¿Recuerdas crear el evento MatchEnd? Se disparará cuando el temporizador se agote o se encuentre un ganador.
Para decirle a otros scripts qué condición terminó el juego, crea una tabla con variables para TimerUp y FoundWinner .Cuando se activa el evento de fin del partido, pasará una variable para que otros scripts puedan responder.
En GameSettings, crea una tabla de módulo vacía llamada endStates.
local GameSettings = {}-- Variables de juegoGameSettings.intermissionDuration = 5GameSettings.matchDuration = 10GameSettings.minimumPlayers = 2GameSettings.transitionTime = 5-- Posibles maneras en que el juego puede finalizar.GameSettings.endStates = {}return GameSettingsCrea dos variables llamadas TimerUp y FoundWinner . Establece cada una en una cadena que coincida con su nombre. Estas cadenas se usarán para probar el código.
GameSettings.endStates = {TimerUp = "TimerUp",FoundWinner = "FoundWinner"}
Termina con un temporizador
Cuando termina el temporizador, dispara el evento de fin de partido y envía la variable de estado de final coincidente.De esa manera, otros scripts que escuchan ese evento pueden responder de acuerdo.Recuerde que mientras los eventos disparan señales de fuego, también pueden enviar datos que son recibidos por los scripts de escucha, como TimerUp o FoundWinner.
En GameManager , en el bucle while verdadero, encuentra la línea matchEnd.Event:Wait(). Al 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 elimina la declaración de impresión.Luego, para disparar el evento de fin de partido, escriba matchEnd:Fire() y pase en gameSettings.endStates.TimerUp.
-- Valoreslocal 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 localeslocal function timeUp()matchEnd:Fire(gameSettings.endStates.TimerUp)endPrueba una coincidir. Una vez que el temporizador se agota, comprueba que la declaración de impresión incluya la cadena almacenada en la variable TimerUp.
Consejos de solución de problemas
En este punto, el mensaje no se mostró, prueba uno de los siguientes a continuación.
- Asegúrate de que dondequiera que se llamen las variables de estado final, estén escritas exactamente, como aquí: gameSettings.endStates.TimerUp .
- Asegúrate de usar : (operador de colon) con el Fire() en lugar de del operador de punto, como en matchEnd:Fire() .
Codifica una coincidirganadora
A continuación, el script debe identificar a los jugadores ganadores, eliminar a los jugadores perdedores y ejecutar una limpieza como detener el temporizador.Las partidas también terminarán si un jugador se queda sin opciones.Para ver si se cumple la condición FoundWinner, necesitarás una función que verifique el número que queda en la tabla que rastrea a los jugadores en una coincidir.
Compruebe el número de jugadores
Las coincidencias terminarán si solo queda un jugador.Para verificar esto, el script debe rastrear a los jugadores en una ronda.Una vez que se quede un jugador, se puede asignar un ganador.
En PlayerManager, define las siguientes variables:
- Carpeta ModuleScripts
- Módulo GameSettings - Se utiliza para acceder a las variables de estado final
- Carpeta de eventos 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")Por encima de respawnPlayerInLobby(), agregue una nueva función local llamada checkPlayerCount().
-- Variables del jugadorlocal activePlayers = {}local playerWeapon = ServerStorage.Weaponlocal function checkPlayerCount()endlocal function respawnPlayerInLobby(player)Dentro de esa función, utilice una declaración if then para verificar un ganador. En esa declaración:
- Compruebe si el tamaño de la tabla activePlayers es 1.
- Si es así, dispara matchEnd y pasa gameSettings.endStates.FoundWinner.
local function checkPlayerCount()if #activePlayers == 1 thenmatchEnd:Fire(gameSettings.endStates.FoundWinner)endend
Eliminar a un jugador
No se puede mantener un conteo preciso a menos que se eliminen a los jugadores.Cuando un jugador es derrotado, mantén un conteo preciso de jugadores eliminándolos de la tabla del jugador.Luego, compruebe el tamaño de la tabla de jugadores activos 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, iterar a través de ella usando un bucle for.Luego, agregue una declaración if que se ejecuta si se encuentra un jugador que coincida con el nombre en la función.
local function removeActivePlayer(player)for playerKey, whichPlayer in activePlayers doif whichPlayer == player thenendendendPara eliminar al jugador, en la declaración if:
- Llama a table.remove() . Dentro de los paréntesis, pasa activePlayers , la tabla para mirar, y playerKey - el jugador para eliminar de la tabla.
- Establece el valor del objeto playersLeft a #activePlayers.
- Compruebe si hay 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
Conectar eventos y probar
Para usar la función que acaba de crear, llámela desde dentro de la función anónima conectada al evento Died del jugador.
Encuentra preparePlayer() . En la función anónima con la conexión del evento Died, llama removeActivePlayer() . Luego, pasa al jugador como parámetro.
humanoid.Died:Connect(function()respawnPlayerInLobby(player)removeActivePlayer(player)end)Para ver si se encuentra un jugador ganador, inicie un servidor de prueba **** .Cuando solo quede un jugador, deberías ver a FoundWinner en la ventana de salida.
Continúa probando y deja que la partida finalizar. Nota como empieza una nueva partida, aparece un error en la ventana de salida:
Este error se debe a que el temporizador no se detuvo, lo que se corregirá en la siguiente sección.
Detener el temporizador
Cada vez que una partida termina con un jugador ganador, el temporizador debe detenerse también.Para detener el temporizador antes de que se acabe el tiempo, haz que el temporizador se detenga cada vez que se active el evento de fin de partido.Este es uno de los beneficios de crear eventos.Se pueden reutilizar en múltiples situaciones para escribir relaciones de causa y efecto.
En MatchManager, crea una nueva función local llamada stopTimer() . Dentro, escribe myTimer:stop() para detener el temporizador.
-- Crea un nuevo objeto de temporizador para usar 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 matchEnd 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 a todos menos a un jugador y luego espera unos segundos una vez que termine el partido.
Siguientes pasos
Aunque las dos condiciones de victoria estén terminadas, aún hay algunas tareas pendientes para terminar el ciclo de juego.Por instancia, el jugador ganador nunca se teletransporta al vestíbulo.En la siguiente lección, mostrarás cómo terminó el partido para los jugadores y reiniciarás el juego, completando finalmente todo el bucle.
Guiones completados
A continuación, se completan los scripts para verificar doblemente tu trabajo.
scriptde 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
scriptde configuración del juego
local GameSettings = {}-- Variables de juegoGameSettings.intermissionDuration = 5GameSettings.matchDuration = 10GameSettings.minimumPlayers = 2GameSettings.transitionTime = 5-- Posibles maneras en que el juego puede finalizar.GameSettings.endStates = {TimerUp = "TimerUp",FoundWinner = "FoundWinner"}return GameSettings
scriptdel administrador del juego
-- 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 scriptMatchManager
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 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()
print("Timer started")
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
matchStart.Event:Connect(startTimer)
matchEnd.Event:Connect(stopTimer)
return MatchManager