How to make smooth drawing canvas?

I found how to make smooth but idk how it work can someone help?

We can’t help if you don’t include any code

1 Like

So i need to show my code to you??

yeah?? thats the entire point of this forum. Maybe if you read the category rules before posting you would know this.

Oh ok sorry about that i didnt read anything before i post

What exactly are you using here?

You should next time, it would save us both a lot of time and we wouldn’t be having this conversation.

Can you please format this properly? It is difficult to read unformatted. Add “```” at the beginning and end of the reply

local UserInputService = game:GetService("UserInputService")
local player = game.Players.LocalPlayer
local mouse = player:GetMouse()

local isDrawing = false

local function startDrawing()
    isDrawing = true
end

local function stopDrawing()
    isDrawing = false
end


local function MakePoint(x,y)
    
    local dot = Instance.new("Frame",script.Parent.Frame)
    local round = Instance.new("UICorner",dot)
    
    round.CornerRadius = UDim.new(.5, 0)
    
    dot.BackgroundColor3 = Color3.new()
    
    dot.Size = UDim2.fromOffset(10,10)
    
    dot.Position = UDim2.fromOffset(x,y)
    
    dot.AnchorPoint = Vector2.new(0.5,0.5)
        
end


UserInputService.InputBegan:Connect(function(input, gameProcessedEvent)
    if not gameProcessedEvent then
        if input.UserInputType == Enum.UserInputType.MouseButton1 then
            startDrawing()
        end
    end
end)


game:GetService("RunService").Heartbeat:Connect(function()
    if isDrawing == true then
        MakePoint(mouse.X - script.Parent.Frame.AbsolutePosition.X, mouse.Y - script.Parent.Frame.AbsolutePosition.Y)
    end
end)

UserInputService.InputEnded:Connect(function(input)
    if input.UserInputType == Enum.UserInputType.MouseButton1 then
        stopDrawing()
    end
end)  

You are only placing a dot when the player clicks their mouse, this is why it is not the “smooth” effect you are trying to achieve. You will need to detect if the player is holding down the mouse button which can be achieved via a variable, e.g

local held = false
UserInputService.InputBegan:Connect(function(input))
[...stuff here...]
held = true
end

UserInputService.InputEnded:Connect(function(input))
[...stuff here...]
held = false
end

And then use while held == true do to continuously draw lines at wait(0.05) intervals.

Where can i put while held == ture do ?

I would put it in a coroutine at the bottom.

coroutine.wrap(function())
while held == true do
[...draw lines here...]
end
end) ()

So i dont need to use RunService:RenderStepped ?

Well we are essentially doing the same thing by using render stepped and while held == true do. To explain it simply, both are loops. You can use render stepped if really want to, but I think a while true do is more beneficial in this given situation.

@bomgzy Have you found a solution yet?

Grab the players mouse with local mouse = game.Players.LocalPlayer:GetMouse()
Then you can check when their mouse button is down with mouse.Button1Down and when it is up with mouse.Button1Up. Inside of the functions those would be linked too, set a variable named whatever and whenever that variable is true, you draw to the pixel. Don’t use UserInputService for this.

@bomgzy dont get confused, this is the same as what I described.

Also a better alternative is to use EditableImage though it’s currently a beta feature. You might actually have a smooth drawing canvas, but I just realized you are creating a new frame every time you are holding the mouse button down, which could be causing some lag. If you really need this working within the next week in a released game, you should use parts for the canvas and paint the part, instead of making a new frame everytime. EditableImage is the best way to go overall though for experimenting.

4 Likes

here my new script but didnt work

local UserInputService = game:GetService("UserInputService")
local player = game.Players.LocalPlayer
local mouse = player:GetMouse()

local held = false


local function MakePoint(x,y)

	local dot = Instance.new("Frame")
	local round = Instance.new("UICorner",dot)

    dot.Parent = script.Parent.Frame

	round.CornerRadius = UDim.new(.5, 0)

	dot.BackgroundColor3 = Color3.new(0, 0, 0)

	dot.Size = UDim2.fromOffset(10,10)

	dot.Position = UDim2.fromOffset(x,y)

	dot.AnchorPoint = Vector2.new(0.5,0.5)

end


UserInputService.InputBegan:Connect(function(input, gameProcessedEvent)
  if not gameProcessedEvent then
   if input.UserInputType == Enum.UserInputType.MouseButton1 then
	held = true
	    end
	end
end)

UserInputService.InputChanged:Connect(function(input, gameProcessedEvent)
	if input.UserInputType == Enum.UserInputType.MouseMovement then
		held = true
	end
end)

UserInputService.InputEnded:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1 then
	held = false
	end
end)


coroutine.wrap(function()
	while held == true do
		
		task.wait(0.05)
		
		local X = math.abs(mouse.X - script.Parent.Frame.AbsolutePosition.X)
		local Y = math.abs(mouse.Y - script.Parent.Frame.AbsolutePosition.Y)

		MakePoint(X,Y)

	end
end)
  1. Use UserInputService:GetMouseLocation(), note it uses viewport position, you’ll have to use ScreenInset.

  2. Try this:

UserInputService.InputBegan:Connect(function(input, gameProcessedEvent)
  if not gameProcessedEvent then
    if input.UserInputType == Enum.UserInputType.MouseButton1 then
      held = true
      while held do task.wait()
        local mouse=UserInputService:GetMouseLocation()
        local X = math.abs(mouse.X - script.Parent.Frame.AbsolutePosition.X)
        local Y = math.abs(mouse.Y - script.Parent.Frame.AbsolutePosition.Y)
        MakePoint(X,Y) --[[ Then, you have to create a line between this point
        and last point, if there's a last point. try using .Rotation for the line.
      ebd
    end
  end
end)