Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
✓ ANSWER ACCEPTED

What's a good way to keep a game looping through rounds/matches ?

I've been working on some classes for a project and I've run into the problem of not really knowing how to keep the game consistently starting a new round, picking a new map, etc, etc.

Should I use a while loop, or perhaps a bindable event (this is what seems best to me) to detect the end of a game, or what?

I think this question is pretty discussion based, so let me know what you guys prefer to do. I'm honestly pretty stumped. Creating a frame work for a game is a lot tougher than it seems on the surface.

Btw, I'm not asking for any code, or requesting anything. This falls in the lines as a 'good question' haha. I just want to know how some people prefer to do things like this, especially if you have experience doing it.

Thanks.

1 comment

0

The reason I ask is because I'm also pushing to write less procedural code and move more into OOP. Using a while loop over something like an event is just too procedural and "hacky". It doesnt seem like a good idea That being said I'm looking for more answers focused outside of that method of programming..

2 answers

✓ Accepted answer

I've made dozens of round based games before. What I usually do is make a bunch of functions each with it's own purpose (e.g the intermission or choosing specific maps).

function Intermission() --Intermission function
	for i = 30,0,-1 do --We run a loop 30 times and each time it runs it subtracts "i" by 1.
		print(i) --Print i
		wait(1) --wait a second
	end
end

function ChooseMap() --Choose map function
	local Maps = game:GetService("ReplicatedStorage"):GetChildren() --We get the children of the replicated storage (assuming its all maps, if not make a separate folder within replicated storage and get the children from there)
	local ChosenMap = Maps[math.random(1,#Maps) --We index the Maps table from a random number between 1 to the number of maps in the table.
	
	print(ChosenMap.Name.." is the chosen map!") --We print that its the chosen map.
	
	local Map = ChosenMap:Clone() --We clone it
	Map.Name = "Map" --We name it map for future reference
	Map.Parent = workspace --We parent it to the workspace.
end

function RunGame()
	local Map = workspace.Map --We grab the map and since it was named map beforehand its easier to get
	for i,v in pairs(game:GetService("Players"):GetPlayers()) do --We loop through the players
		if v.Character and v.Character.Humanoid.Health > 0 then --Run a simple conditional statement to see if the character of the specific player exists and if they're still alive
			Character.HumanoidRootPart.CFrame = Map.Spawns[i].CFrame + Vector3.new(0,3,0) --If thats the case then we modify the cframe of their humanoidrootpart to a spawn in the map and add Vector3.new() to ensure that they don't get stuck in the spawn.
		end
	end
end

while true do -- A while true do loop in which we run all three of these functions, and since when you run a function it yields the code we can easily do all three one by one.
	Intermission()
	ChooseMap()
	RunGame()
end

Considering you're attempting to check if the game is reaching its win/lose conditions, I usually make a loop for the game timer and have a loop that runs each second that checks if any of the players are alive and I use a conditional statement to check.

function RunGame()
	local IngamePlayers = {}

	local Map = workspace.Map --We grab the map and since it was named map beforehand its easier to get
	for i,v in pairs(game:GetService("Players"):GetPlayers()) do --We loop through the players
		if v.Character and v.Character.Humanoid.Health > 0 then --Run a simple conditional statement to see if the character of the specific player exists and if they're still alive
			Character.HumanoidRootPart.CFrame = Map.Spawns[i].CFrame + Vector3.new(0,3,0) --If thats the case then we modify the cframe of their humanoidrootpart to a spawn in the map and add Vector3.new() to ensure that they don't get stuck in the spawn.

			table.insert(IngamePlayers,i) --We insert them into the table
		end
	end

	for time = 100,0,-1 do
		print(i)

		for index,plr in pairs(IngamePlayers) do
			if plr then --if the player exists
				local char= plr.Character
				if char.Humanoid.Health > 100 then --If they are alive
					--We do nothing.
				else
					table.remove(IngamePlayers,index) --remove them since theyre dead.
				end
			else
				table.remove(IngamePlayers,index) --remove them from the table since they probably left the game. 		
			end
		end
		
		if #IngamePlayers == 1 then
			print(IngamePlayers[1].Name.." has won!")
		elseif #IngamePlayers == 0 then
			print("everyone died! no one wins!")
		elseif i == 0 then
			print("ran out of time! no one wins!")
		end

		wait(1) --We do this every second.
	end
end

2 comments

1

For separate win conditions (such as checking if they beat the map if its a parkour map or something) i'd just make a touched event for the win part and then award them the cash. afterwards I'd disconnect the event.

0

Thanks for the insights. Really appreciate it.

Hey for anyone wondering; I did eventually find a way to do this, and in such a manner as I think its worth sharing with other people.

I basically went with mostly OOP, I created a class called the GameController and another class for matches.

The matches class holds the information like the match time, the game mode, the current map, etc. The GameController class holds all the functions that actually start the game (Like choosing the map, teleporting the players, updating the intermission sequences, etc).

Then I required them into a server script and ran a bit of code like this:

while true do 
	gameController:StartIntermission() 
	gameController:StartGame()
	wait()
end

Its super clean and works really well, Im thinking about finishing it and open sourcing it for my buddies. If I ever do, I'll try and remember to post it here for other people to learn. Cheers.

This discussion is preserved as it was. New answers, comments, and votes are closed.