so basically i want to make a gui drawing system for my game but the on ive made currently lags after just a couple of strokes. does anyone have any suggestions?
game for reference: doodl_io - Roblox
my current code:
-- add max per layer
local userInput = game:GetService("UserInputService")
local isMouseDown = false -- Track the mouse state
local UserInputService = game:GetService("UserInputService")
local frame = script.Parent -- Replace with your target GUI object
local brushTemplate = script.Parent.Brush -- Reference to the brush template
local previousPosition = nil -- Store the previous position for interpolation
-- Detect when the mouse button is pressed
userInput.InputBegan:Connect(function(input, gameProcessed)
if gameProcessed then return end -- Ignore inputs when UI or other game features consume them
if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
isMouseDown = true
script.Parent.Held.Value = true
end
end)
-- Detect when the mouse button is released
userInput.InputEnded:Connect(function(input, gameProcessed)
if gameProcessed then return end
if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
isMouseDown = false
script.Parent.Held.Value = false
previousPosition = nil
end
end)
-- Example: Check mouse state continuously
game:GetService("RunService").RenderStepped:Connect(function()
if isMouseDown then
script.Parent.Held.Value = true
else
script.Parent.Held.Value = false
previousPosition = nil
end
end)
game:GetService("RunService").RenderStepped:Connect(function()
-- Drawing logic here
end)
UserInputService.InputChanged:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseMovement then
local mouse = game.Players.LocalPlayer:GetMouse()
local ContainerPosition = script.Parent.AbsolutePosition
script.Parent.BrushStroke.Position = UDim2.new((mouse.X - ContainerPosition.X)/script.Parent.AbsoluteSize.X, 0, (mouse.Y - ContainerPosition.Y)/script.Parent.AbsoluteSize.Y, 0)
if script.Parent.Held.Value == true then
local mousePosition = UserInputService:GetMouseLocation()
local containerPosition = frame.AbsolutePosition
local containerSize = frame.AbsoluteSize
-- Calculate the current position in UDim2
local currentPosition = UDim2.new(
(mouse.X - containerPosition.X) / containerSize.X,
0,
(mouse.Y - containerPosition.Y) / containerSize.Y,
0
)
-- If there was a previous position, interpolate between it and the current position
if previousPosition then
local start = Vector2.new(
previousPosition.X.Scale * containerSize.X,
previousPosition.Y.Scale * containerSize.Y
)
local finish = Vector2.new(
currentPosition.X.Scale * containerSize.X,
currentPosition.Y.Scale * containerSize.Y
)
local distance = (finish - start).Magnitude
local step = math.max(brushTemplate.AbsoluteSize.X / 5, distance / 100) -- Number of pixels between brush strokes
-- Create interpolated brush strokes
for i = 0, distance, step do
local t = i / distance
local interpolatedPosition = start:Lerp(finish, t)
-- Convert interpolated position back to UDim2
local interpolatedUDim2 = UDim2.new(
interpolatedPosition.X / containerSize.X,
0,
interpolatedPosition.Y / containerSize.Y,
0
)
if interpolatedUDim2.X.Scale < 1 or interpolatedUDim2.Y.Scale < 1 and interpolatedUDim2.X.Scale >= 0 or interpolatedUDim2.Y.Scale >= 0 then
-- Create and position a brush clone
local clone = brushTemplate:Clone()
clone.Position = interpolatedUDim2
clone.Parent = frame
end
end
end
if currentPosition.X.Scale < 1 and currentPosition.Y.Scale < 1 and currentPosition.X.Scale >= 0 and currentPosition.Y.Scale >= 0 then
-- Update the brush stroke and set the previous position
local clone = brushTemplate:Clone()
clone.Position = currentPosition
clone.Parent = frame
previousPosition = currentPosition
end
script.Parent.BrushStroke.Visible = true
-- Store for the next frame
else
previousPosition = nil
end
end
end)
UserInputService.TouchMoved:Connect(function(touch)
print("touch moved")
local touchPosition = Vector2.new(touch.Position.X, touch.Position.Y)
local ContainerPosition = script.Parent.AbsolutePosition
script.Parent.BrushStroke.Position = UDim2.new((touchPosition.X - ContainerPosition.X)/script.Parent.AbsoluteSize.X, 0, (touchPosition.Y - ContainerPosition.Y)/script.Parent.AbsoluteSize.Y, 0)
if script.Parent.Held.Value == true then
local containerPosition = frame.AbsolutePosition
local containerSize = frame.AbsoluteSize
-- Calculate the current position in UDim2
local currentPosition = UDim2.new(
(touchPosition.X - containerPosition.X) / containerSize.X,
0,
(touchPosition.Y - containerPosition.Y) / containerSize.Y,
0
)
-- If there was a previous position, interpolate between it and the current position
if previousPosition then
local start = Vector2.new(
previousPosition.X.Scale * containerSize.X,
previousPosition.Y.Scale * containerSize.Y
)
local finish = Vector2.new(
currentPosition.X.Scale * containerSize.X,
currentPosition.Y.Scale * containerSize.Y
)
local distance = (finish - start).Magnitude
local step = math.max(brushTemplate.AbsoluteSize.X / 5, distance / 100) -- Number of pixels between brush strokes
-- Create interpolated brush strokes
for i = 0, distance, step do
local t = i / distance
local interpolatedPosition = start:Lerp(finish, t)
-- Convert interpolated position back to UDim2
local interpolatedUDim2 = UDim2.new(
interpolatedPosition.X / containerSize.X,
0,
interpolatedPosition.Y / containerSize.Y,
0
)
if interpolatedUDim2.X.Scale < 1 or interpolatedUDim2.Y.Scale < 1 and interpolatedUDim2.X.Scale >= 0 or interpolatedUDim2.Y.Scale >= 0 then
-- Create and position a brush clone
local clone = brushTemplate:Clone()
clone.Position = interpolatedUDim2
clone.Parent = frame
end
end
end
if currentPosition.X.Scale < 1 and currentPosition.Y.Scale < 1 and currentPosition.X.Scale >= 0 and currentPosition.Y.Scale >= 0 then
-- Update the brush stroke and set the previous position
local clone = brushTemplate:Clone()
clone.Position = currentPosition
clone.Parent = frame
previousPosition = currentPosition
end
script.Parent.BrushStroke.Visible = true
else
previousPosition = nil
end
end)
--[[UserInputService.InputChanged:Connect(function(input)
print("Input Type:", input.UserInputType, "Position:", input.Position)
end)]]
--[[
local mouse = game.Players.LocalPlayer:GetMouse()
local ContainerPosition = script.Parent.AbsolutePosition
script.Parent.BrushStroke.Position = UDim2.new((mouse.X - ContainerPosition.X)/script.Parent.AbsoluteSize.X, 0, (mouse.Y - ContainerPosition.Y)/script.Parent.AbsoluteSize.Y, 0)
if script.Parent.Held.Value == true then
local mousePosition = UserInputService:GetMouseLocation()
local containerPosition = frame.AbsolutePosition
local containerSize = frame.AbsoluteSize
-- Calculate the current position in UDim2
local currentPosition = UDim2.new(
(mouse.X - containerPosition.X) / containerSize.X,
0,
(mouse.Y - containerPosition.Y) / containerSize.Y,
0
)
-- If there was a previous position, interpolate between it and the current position
if previousPosition then
local start = Vector2.new(
previousPosition.X.Scale * containerSize.X,
previousPosition.Y.Scale * containerSize.Y
)
local finish = Vector2.new(
currentPosition.X.Scale * containerSize.X,
currentPosition.Y.Scale * containerSize.Y
)
local distance = (finish - start).Magnitude
local step = math.max(brushTemplate.AbsoluteSize.X / 5, distance / 100) -- Number of pixels between brush strokes
-- Create interpolated brush strokes
for i = 0, distance, step do
local t = i / distance
local interpolatedPosition = start:Lerp(finish, t)
-- Convert interpolated position back to UDim2
local interpolatedUDim2 = UDim2.new(
interpolatedPosition.X / containerSize.X,
0,
interpolatedPosition.Y / containerSize.Y,
0
)
if interpolatedUDim2.X.Scale < 1 or interpolatedUDim2.Y.Scale < 1 and interpolatedUDim2.X.Scale >= 0 or interpolatedUDim2.Y.Scale >= 0 then
-- Create and position a brush clone
local clone = brushTemplate:Clone()
clone.Position = interpolatedUDim2
clone.Parent = frame
end
end
end
if currentPosition.X.Scale < 1 and currentPosition.Y.Scale < 1 and currentPosition.X.Scale >= 0 and currentPosition.Y.Scale >= 0 then
-- Update the brush stroke and set the previous position
local clone = brushTemplate:Clone()
clone.Position = currentPosition
clone.Parent = frame
previousPosition = currentPosition
end
script.Parent.BrushStroke.Visible = true
-- Store for the next frame
else
previousPosition = nil
end]]
--[[-- Function to calculate the mouse's UDim2 position
local function getMouseUDim2()
-- Get the mouse's absolute position
local mousePos = UserInputService:GetMouseLocation()
-- Get the frame's position and size
local framePos = frame.AbsolutePosition
local frameSize = frame.AbsoluteSize
-- Calculate the relative offset position
local relativeX = mousePos.X - framePos.X
local relativeY = mousePos.Y - framePos.Y
-- Ensure the position is within the frame
if relativeX < 0 or relativeY < 0 or relativeX > frameSize.X or relativeY > frameSize.Y then
return nil -- Mouse is outside the frame
end
-- Calculate scale (percentage)
local scaleX = relativeX / frameSize.X
local scaleY = relativeY / frameSize.Y
-- Construct a UDim2
return UDim2.new(scaleX, 0, scaleY, 0)
end
UserInputService.InputChanged:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseMovement then
-- Set the clone's position
local mouseUDim2 = getMouseUDim2()
if not mouseUDim2 then
script.Parent.Held.Value = false
previousPosition = nil
end
end
end)]]