타워 만들기
Coddy의 Roblox 게임: 타워 디펜스 코스 레슨. 18개 중 6번째.
이제 플레이어 쪽을 살펴보겠습니다. DefenseClient는 HUD 안에 있는 LocalScript입니다. HUD는 Roblox가 각 플레이어의 화면에 복사하는 ScreenGui입니다. HUD의 Shop 프레임에는 타워마다 하나씩 TextButton이 있으며, 각 버튼의 이름은 타워 이름을 따릅니다. 버튼의 Activated 이벤트는 버튼을 클릭하거나 탭하면 발생합니다:
button.Activated:Connect(function()
selected = button.Name
end)그런 다음 회색 패드 중 하나를 클릭하면 선택한 타워가 해당 위치에 건설됩니다. 클라이언트는 마우스에서 클릭 정보를 읽습니다(me:GetMouse(), 마우스의 Button1Down 이벤트와 포인터 아래에 있는 파트인 Target). 하지만 타워는 서버에 있으므로 클라이언트에서 직접 타워를 건설할 수는 없습니다. 클라이언트는 RemoteEvent Remotes.Place를 통해 요청합니다:
-- 클라이언트
remotes.Place:FireServer(pad, "Archer")
-- 서버: Roblox가 player를 먼저 추가합니다
remotes.Place.OnServerEvent:Connect(function(player, pad, kind)
end)타워 모델은 ServerStorage.Towers에 대기하고 있으며, 서버가 모델 하나를 복제해 패드에 배치합니다.
챌린지
중급DefenseClient에서:
Players,Settings(WaitForChild사용),local remotes = game.ReplicatedStorage:WaitForChild("Remotes"),local me = Players.LocalPlayer,local hud = script.Parent를 가져옵니다.hud.Shop의 각 TextButton에 타워 이름과 가격(Archer $60)을 텍스트로 설정하고,Activated이벤트에서 해당 버튼을selected에 저장합니다.- 마우스의
Button1Down이벤트에서 대상이workspace.Pads에 있고 타워가 선택되어 있으면, 패드와 타워 이름을 인수로remotes.Place를 호출합니다.
DefenseServer에서: local remotes와 local towers = workspace.Towers를 추가하고, placeTower(pad, kind)를 작성합니다(복제하고, 패드의 CFrame을 패드 높이의 절반에 1을 더한 만큼 올려 PivotTo한 다음, towers를 부모로 지정). 그리고 remotes.Place.OnServerEvent를 여기에 연결합니다.
Play를 누르고 타워를 선택한 다음 패드를 클릭합니다. 그런 다음 Check를 누릅니다.
직접 해보기
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")
-- 순서대로 나열된 경유지(이름은 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)
-- 모든 플레이어는 리더보드에서 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)
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
task.spawn(walkPath, enemy)
return enemy
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
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.