Menu
CoddyTech

Waves

Lesson 4 of 18 in Coddy's Roblox Game: Tower Defense course.

One zombie is not a game. Settings.Waves lists the waves, each a list of enemy names:

Waves = {
	{ "Zombie", "Zombie", "Zombie" },
	{ "Zombie", "Runner" },
}

runWave(list) spawns its enemies one by one, Settings.SpawnGap seconds apart, and then waits until workspace.Enemies is empty, so the next wave starts only when this one is over. Before each wave the players get Settings.WaveBreak seconds to prepare.

The main loop goes through the waves in order: for i, list in Settings.Waves do.

challenge icon

Challenge

Easy
  1. Write runWave(list): spawn each enemy in the list, waiting Settings.SpawnGap after each, then wait until enemies has no children.
  2. Replace the single spawn with a loop over Settings.Waves: wait Settings.WaveBreak, then run the wave.

This lesson's world has two short waves. Press Play, then Check.

Try it yourself

local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local Settings = require(game.ReplicatedStorage.Settings)

local enemies = workspace.Enemies

print("The base can take " .. Settings.BaseHealth .. " hits")

-- The waypoints, in order (they are named 1, 2, 3...)
local waypoints = workspace.Path.Waypoints:GetChildren()
table.sort(waypoints, function(a, b)
	return tonumber(a.Name) < tonumber(b.Name)
end)

-- The base's health, as an attribute of the workspace: every client can read it
workspace:SetAttribute("BaseHealth", Settings.BaseHealth)

-- Every player gets Money on the leaderboard
Players.PlayerAdded:Connect(function(player)
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player

	local money = Instance.new("IntValue")
	money.Name = "Money"
	money.Value = Settings.StartMoney
	money.Parent = leaderstats
end)

-- An enemy reached the base
local function damageBase(amount)
	local health = math.max(0, workspace:GetAttribute("BaseHealth") - amount)
	workspace:SetAttribute("BaseHealth", health)
end

-- Walk an enemy along the path. MoveTo gives up after 8 seconds and says so
-- (MoveToFinished with false), so a slow enemy is sent again until it arrives.
local function walkPath(enemy)
	local humanoid = enemy.Humanoid
	for i = 2, #waypoints do
		repeat
			humanoid:MoveTo(waypoints[i].Position)
		until humanoid.MoveToFinished:Wait() or not enemy.Parent
		if not enemy.Parent then
			return
		end
	end
	-- it reached the base
	damageBase(1)
	enemy:Destroy()
end

-- A new enemy at the gate, walking the path
local function spawnEnemy(kind)
	local enemy = ServerStorage.Enemies[kind]:Clone()
	-- dropped in just above the first waypoint
	enemy:PivotTo(waypoints[1].CFrame + Vector3.new(0, 5, 0))
	enemy.Parent = enemies
	task.spawn(walkPath, enemy)
	return enemy
end

-- One enemy, for now
spawnEnemy("Zombie")
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Roblox Game: Tower Defense