I’m currently creating a 2D Battle system for a single-player game.
I am not sure what the most effective way of doing this type of system would be since this is my first time creating something like this. By “2D Battle System” I mean a GUI object which can move in four directions and that can detect if other GUI objects hit it. (I do this atm but I am using actual objects and rendering them on the client as images).
I use the player object for now as the heart and the bones are parts. I’m not sure if it is a good way of doing this like that? If it is an alright way of doing it then how could I improve the code below?
(The code below is only the client since the server creates attack objects, moves them and handles damage and some normal security.)
Code:
local Battle = {}
-- VARIABLES
local RunService = game:GetService("RunService")
local Player = game.Players.LocalPlayer
local Client = Player.PlayerGui.Client
local Root = Player.Character:WaitForChild("HumanoidRootPart")
local Humanoid = Player.Character:WaitForChild("Humanoid")
local RenderPlayer
local RenderAttack
local RenderCamera
-- OBJECT VARIABLES
local AttackStorage = game.Workspace.Battle.Attack
local Spawn = game.Workspace.Battle.Spawn
-- FUNCTIONS
function Battle:CalculatePos(obj) -- calculates objects for the area inside the GUI.
local x,z = obj.Position.X, obj.Position.Z
local xz = UDim2.fromScale(x/100+0.5, z/50+0.5)
return xz
end
function Battle:CreateAttack(physicalObj) -- creates attack obj in GUI.
if AttackStorage[physicalObj.Name] then
local guiObject = script[physicalObj.Name]:Clone()
guiObject.Parent = Client.BattleFrame.Area
guiObject.Name = physicalObj:WaitForChild("GUID").Value
guiObject.Position = self:CalculatePos(physicalObj)
Battle:VisualAttack(guiObject.Name)
end
end
function Battle:VisualAttack(GUID) -- unique object identification and movement for object.
for _,v in pairs(Client.BattleFrame.Area:GetChildren()) do
if v.Name == GUID then
RenderAttack = RunService.RenderStepped:Connect(function()
for _,b in pairs(AttackStorage:GetChildren()) do
for _,d in pairs(b:GetChildren()) do
if d:IsA("StringValue") and d.Value == GUID then
Client.BattleFrame.Area[GUID].Position = self:CalculatePos(b)
end
end
end
end)
end
end
end
local RemoveBattleAttack = function(GUID) -- removes gui object.
for _,b in pairs(AttackStorage:GetChildren()) do
for _,d in pairs(b:GetChildren()) do
if d:IsA("StringValue") and d.Value == GUID then
Client.BattleFrame.Area[d.Value]:Destroy()
end
end
end
end
local BattleCamera = function(state) -- forces player's camera to have matching orientation with the gui (-90, 0, 0)
if state then
RenderCamera = RunService.RenderStepped:Connect(function()
game.Workspace.CurrentCamera.CFrame = game.Workspace.Battle.Camera.CFrame
end)
else
if RenderCamera then
RenderCamera:Disconnect()
game.Workspace.CurrentCamera.CFrame = game.Workspace
else
return print("[CLIENT] - Camera has not been rendered!")
end
end
end
function Battle:Render() -- renders the player in gui (heart)
RenderPlayer = RunService.RenderStepped:Connect(function()
Client.BattleFrame.Area.Player.Position = Battle:CalculatePos(player)
end)
end
function Battle:TeleportPlayer() -- teleports player to area for now.
Root.CFrame = CFrame.new(Spawn.Position)
end
AttackStorage.ChildAdded:Connect(function(typ) -- creates attack when server creates attack.
Battle:CreateAttack(typ)
end)
-- CONNECTIONS
Battle:TeleportPlayer()
Battle:Render()
local CameraEvent = game.ReplicatedStorage.Assets.Events:WaitForChild("Camera")
local CleanBattleEvent = game.ReplicatedStorage.Assets.Events:WaitForChild("Clean")
CleanBattleEvent.OnClientEvent:Connect(RemoveBattleAttack)
CameraEvent.OnClientEvent:Connect(BattleCamera)
return Battle