Image Drawing not working

I am currently working on Paint a Game game but I have some issues on the client code with coloring, for example, when I am walking and painting, it pains different direction or position, but I want 5 studs from player’s feet, how can I fix it, here’s the code:

ServerScript

`
local HttpService = game:GetService(“HttpService”)
local Workspace = game:GetService(“Workspace”)
local ReplicatedStorage = game:GetService(“ReplicatedStorage”)

local PlaceIds = {
126884695634066,
79546208627805,
109983668079237
}

local GAS_URL = “https://script.google.com/macros/s/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/exec
local TARGET_IMAGE_ID = “rbxassetid://78673074540642” – fallback
local TOTAL_CANVAS_SIZE = 72
local GRID_RESOLUTION = 360

– Pravimo RemoteEvent
local canvasEvent = ReplicatedStorage:FindFirstChild(“CanvasSetupEvent”) or Instance.new(“RemoteEvent”)
canvasEvent.Name = “CanvasSetupEvent”
canvasEvent.Parent = ReplicatedStorage

local function InitializePixelCanvas()
local randomPlaceId = PlaceIds[math.random(1, #PlaceIds)]
print("[SERVER] Prevlačim UniverseId za PlaceId: " .. randomPlaceId)

local successHttp, response = pcall(function()
	return HttpService:GetAsync(GAS_URL .. "?placeId=" .. tostring(randomPlaceId))
end)Preformatted text

local imageToLoad = TARGET_IMAGE_ID

if successHttp then
	local successDecode, decodedData = pcall(function() return HttpService:JSONDecode(response) end)
	if successDecode and decodedData.success and decodedData.universeId then
		imageToLoad = "rbxthumb://type=GameIcon&id=" .. decodedData.universeId .. "&w=150&h=150"
		print("[SERVER] Uspešno dobijen rbxthumb link: " .. imageToLoad)
	end
end

-- Kreiramo Part na serveru da ga svi vide
local canvasPart = Workspace:FindFirstChild("PixelArtCanvasPart")
if not canvasPart then
	canvasPart = Instance.new("Part")
	canvasPart.Name = "PixelArtCanvasPart"
	canvasPart.Size = Vector3.new(TOTAL_CANVAS_SIZE, 0.2, TOTAL_CANVAS_SIZE)
	canvasPart.CFrame = CFrame.new(0, 0.1, 0)
	canvasPart.Anchored = true
	canvasPart.Material = Enum.Material.SmoothPlastic
	canvasPart.Color = Color3.fromRGB(255, 255, 255)
	canvasPart.Parent = Workspace
end

canvasPart:SetAttribute("ImageToLoad", imageToLoad)
canvasEvent:FireAllClients(canvasPart, imageToLoad)

end

InitializePixelCanvas()

game:GetService(“Players”).PlayerAdded:Connect(function(player)
local canvasPart = Workspace:WaitForChild(“PixelArtCanvasPart”, 10)
if canvasPart then
local img = canvasPart:GetAttribute(“ImageToLoad”)
if img then
canvasEvent:FireClient(player, canvasPart, img)
end
end
end)
`

LocalScript

`
–!native
local ReplicatedStorage = game:GetService(“ReplicatedStorage”)
local AssetService = game:GetService(“AssetService”)
local Players = game:GetService(“Players”)

local player = Players.LocalPlayer
local canvasEvent = ReplicatedStorage:WaitForChild(“CanvasSetupEvent”)

local GRID_RESOLUTION = 360
local COLOR_RADIUS = 4

canvasEvent.OnClientEvent:Connect(function(canvasPart, imageToLoad)
if not canvasPart or not canvasPart:IsA(“BasePart”) then return end

local surfaceGui = canvasPart:FindFirstChildOfClass("SurfaceGui")
if not surfaceGui then
	surfaceGui = Instance.new("SurfaceGui")
	surfaceGui.Face = Enum.NormalId.Top
	surfaceGui.SizingMode = Enum.SurfaceGuiSizingMode.FixedSize
	surfaceGui.CanvasSize = Vector2.new(GRID_RESOLUTION, GRID_RESOLUTION)
	surfaceGui.Parent = canvasPart
end

local imageLabel = surfaceGui:FindFirstChildOfClass("ImageLabel")
if not imageLabel then
	imageLabel = Instance.new("ImageLabel")
	imageLabel.Size = UDim2.new(1, 0, 1, 0)
	imageLabel.BackgroundTransparency = 1
	imageLabel.ResampleMode = Enum.ResamplerMode.Pixelated
	imageLabel.Parent = surfaceGui
end

local success, sourceEditableImage = pcall(function()
	return AssetService:CreateEditableImageAsync(imageToLoad)
end)

if not success or not sourceEditableImage then
	warn("[KLIJENT] Neuspešno učitavanje izvorne slike.")
	return
end

local targetEditableImage = AssetService:CreateEditableImage({
	Size = Vector2.new(GRID_RESOLUTION, GRID_RESOLUTION)
})
imageLabel.ImageContent = Content.fromObject(targetEditableImage)

targetEditableImage:DrawRectangle(Vector2.zero, targetEditableImage.Size, Color3.fromRGB(200, 200, 200), 0, Enum.ImageCombineType.Overwrite)

local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Include
raycastParams.FilterDescendantsInstances = {canvasPart}

task.spawn(function()
	while canvasPart and canvasPart.Parent do
		task.wait(0.03)

		local character = player.Character
		local hrp = character and character:FindFirstChild("HumanoidRootPart")

		if hrp then
			local rayResult = workspace:Raycast(hrp.Position, Vector3.new(0, -15, 0), raycastParams)

			if rayResult and rayResult.Instance == canvasPart then
				local localPos = canvasPart.CFrame:PointToObjectSpace(rayResult.Position)

				local u = math.clamp((localPos.X / canvasPart.Size.X) + 0.5, 0, 1)
				local v = math.clamp((localPos.Z / canvasPart.Size.Z) + 0.5, 0, 1)

				local pixelX = math.floor(u * GRID_RESOLUTION)
				local pixelY = math.floor(v * GRID_RESOLUTION)
				local clickPosition = Vector2.new(pixelX, pixelY)

				local sourceSize = sourceEditableImage.Size
				local sampleX = math.clamp(math.floor(u * sourceSize.X), 0, sourceSize.X - 1)
				local sampleY = math.clamp(math.floor(v * sourceSize.Y), 0, sourceSize.Y - 1)

				local colorBuffer = sourceEditableImage:ReadPixelsBuffer(Vector2.new(sampleX, sampleY), Vector2.new(1, 1))
				local r = buffer.readu8(colorBuffer, 0) / 255
				local g = buffer.readu8(colorBuffer, 1) / 255
				local b = buffer.readu8(colorBuffer, 2) / 255
				local targetColor = Color3.new(r, g, b)

				targetEditableImage:DrawCircle(
					clickPosition,
					COLOR_RADIUS,
					targetColor,
					0,
					Enum.ImageCombineType.Overwrite,
					Enum.AntiAliasing.Disabled
				)
			end
		end
	end
end)

end)
`

I think issue is on the client side in while loop. Any idea?