Menu
CoddyTech

보상

Coddy의 Roblox 게임: 타워 디펜스 코스 레슨. 22개 중 11번째.

타워에는 돈이 들고, 돈은 적을 처치하면 얻습니다. 각 종류의 적은 설정에 Reward가 있습니다. 좀비는 6, 브루트는 15입니다.

타워 디펜스 게임에서는 서버 전체가 함께 플레이하므로, 적이 죽으면 모든 플레이어가 보상을 받습니다. Players:GetPlayers()는 게임에 있는 모든 플레이어를 나열합니다:

for _, player in Players:GetPlayers() do
	player.leaderstats.Money.Value += info.Reward
end

보상 지급은 Died 처리기에 넣으므로, 기지에 도달한 적은 아무것도 주지 않습니다.

challenge icon

챌린지

중급

타워가 처치한 적마다 플레이어에게 보상을 지급하세요.

  1. spawnEnemy의 Died 처리기에서 적을 제거하기 전에 Players:GetPlayers()를 반복하세요.
  2. 각 플레이어의 leaderstats.Money.Value에 info.Reward를 더하세요.

‘플레이’를 누르고 Archer를 건설하세요. 처치한 Zombie마다 Money가 6씩 증가합니다. 그런 다음 ‘확인’을 누르세요.

직접 해보기

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

local remotes = game.ReplicatedStorage.Remotes
local enemies = workspace.Enemies
local towers = workspace.Towers

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

-- 순서대로 나열된 경유 지점들(이름은 1, 2, 3...)
local waypoints = workspace.Path.Waypoints:GetChildren()
table.sort(waypoints, function(a, b)
	return tonumber(a.Name) < tonumber(b.Name)
end)

-- workspace의 속성으로 저장된 기지의 체력: 모든 클라이언트가 읽을 수 있음
workspace:SetAttribute("BaseHealth", Settings.BaseHealth)

-- 모든 플레이어는 leaderboard에 Money를 받음
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)

-- 적이 기지에 도달함
local function damageBase(amount)
	local health = math.max(0, workspace:GetAttribute("BaseHealth") - amount)
	workspace:SetAttribute("BaseHealth", health)
	print("Base: " .. health)
end

-- 적을 경로를 따라 이동시킴. MoveTo는 8초가 지나면 이동을 포기하고 이를 알림
-- (MoveToFinished가 false를 반환함). 따라서 느린 적은 도착할 때까지 다시 이동 명령을 받음.
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
	-- 적이 기지에 도달함
	damageBase(Settings.Enemies[enemy.Name].Damage)
	enemy:Destroy()
end

-- 입구에 나타나 경로를 따라 이동하는 새로운 적
local function spawnEnemy(kind)
	local enemy = ServerStorage.Enemies[kind]:Clone()
	-- 첫 번째 경유 지점 바로 위에 배치됨
	enemy:PivotTo(waypoints[1].CFrame + Vector3.new(0, 5, 0))
	local info = Settings.Enemies[kind]
	enemy.Humanoid.MaxHealth = info.Health
	enemy.Humanoid.Health = info.Health
	enemy.Humanoid.WalkSpeed = info.Speed
	enemy.Parent = enemies
	enemy.Humanoid.Died:Connect(function()
		-- Lesson 11: 여기에 Rewards 처리 코드를 넣음
		enemy:Destroy()
	end)
	task.spawn(walkPath, enemy)
	return enemy
end

-- 한 지점에서 일정 범위 내에 있는 가장 가까운 살아 있는 적, 없으면 nil
local function nearestEnemy(position, range)
	local best, bestDistance = nil, range
	for _, enemy in enemies:GetChildren() do
		local root = enemy:FindFirstChild("HumanoidRootPart")
		if root and enemy.Humanoid.Health > 0 then
			local distance = (root.Position - position).Magnitude
			if distance <= bestDistance then
				best, bestDistance = enemy, distance
			end
		end
	end
	return best
end

-- 타워에서 목표물까지 뻗는 섬광
local function beam(from, to)
	local ray = Instance.new("Part")
	ray.Anchored = true
	ray.CanCollide = false
	ray.CanTouch = false
	ray.Material = Enum.Material.Neon
	ray.Color = Color3.fromRGB(255, 240, 150)
	ray.Size = Vector3.new(0.2, 0.2, (to - from).Magnitude)
	ray.CFrame = CFrame.lookAt((from + to) / 2, to)
	ray.Parent = workspace
	Debris:AddItem(ray, 0.1)
end

-- 발사: 대상에게 피해를 준다
local function shoot(tower, target, info)
	local damage = info.Damage
	local at = target.HumanoidRootPart.Position
	target.Humanoid:TakeDamage(damage)
	beam(tower.Head.Position, at)
end

-- 타워의 동작: 사거리 내 가장 가까운 적을 조준하고 발사한 뒤 재사용 대기시간이 끝날 때까지 기다린다
local function runTower(tower)
	local info = Settings.Towers[tower.Name]
	while tower.Parent do
		local target = nearestEnemy(tower.Head.Position, info.Range)
		if target then
			tower.Head.CFrame = CFrame.lookAt(tower.Head.Position, target.HumanoidRootPart.Position)
			shoot(tower, target, info)
			task.wait(info.Cooldown)
		else
			task.wait(0.1)
		end
	end
end

-- 패드 위에 타워를 건설한다
local function placeTower(pad, kind)
	local tower = ServerStorage.Towers[kind]:Clone()
	tower:PivotTo(pad.CFrame + Vector3.new(0, pad.Size.Y / 2 + 1, 0))
	tower.Parent = towers
	task.spawn(runTower, tower)
end

-- 클라이언트가 패드 위에 타워를 건설하도록 요청한다
remotes.Place.OnServerEvent:Connect(function(player, pad, kind)
	placeTower(pad, kind)
end)

-- 한 웨이브: 적을 하나씩 생성한 뒤 모두 사라질 때까지 기다린다
local function runWave(list)
	for _, kind in list do
		spawnEnemy(kind)
		task.wait(Settings.SpawnGap)
	end
	while #enemies:GetChildren() > 0 do
		task.wait(0.2)
	end
end

-- 웨이브마다 휴식 시간을 둔다
for i, list in Settings.Waves do
	task.wait(Settings.WaveBreak)
	runWave(list)
end

Roblox 게임: 타워 디펜스의 모든 레슨

직접 연습해 보세요: Roblox 플레이그라운드