Creating this "moving dot" effect

I played a game and noticed this really interesting UI effect on the background. The dots move around and randomly connect to each other.

I’d like to clarify that I’m absolutely not looking for code or someone to do this for me. I’m simply looking for a guide on where to start. Since right now I’m really not sure. It would be great if someone could guide me along the lines of creating something like this.

Here is the video:

Thank you.

4 Likes

Math. Use Frames to form both lines and dots, basically the most challenging part would be getting the rotation of the line. Not gonna lie, I would like to make the same effect. I would be glad if you also sent the link to the game.

Me if I get my hands on this script:

2 Likes

Really neat effect I gotta admit. Looking at it, it doesn’t seem too hard to implement (every start of a programmer’s hell :sparkles:). Ight, let’s get real now, to spawn the dots, you can just use 1x1 frames or 2x2, basically see what fits you, spawn them randomly and for each one pick a random position every say, 3 seconds, and move it there, now that part is done, draw some lines, I looked closely in some points of the vid and doesn’t seem like it connects the closest dots but it does connect to some close ones, getting distances shouldn’t be too hard, just something like:

(p1.AbsolutePosition - p2.AbsolutePosition).Magnitude

Where p1 and p2 are 2 different frames, you can then sort it using table.sort() and either choose the closest one or pick a random one from the, say, closest 5


That will be very expensive to compute, use things like a grid and only take distances from the closest, say 9 boxes, obviously the number will differ according to the grid size
Drawing lines between the circles won't be too hard so I don't think I need to go over it, it's just some trigonometry - math - so ya, although If you need help with it feel free to ask me.
Now for the mouse interactivity part, remember the grid we had earlier? Well, it'll be very handy now! Check for dots in the same grid (or closer ones if your using a more compact one) then check for the mouse delta, using your own function as `UserInputService:GetMouseDelta()` won't work in this case, then by checking directions and clamping the values to a reasonable range, move the circles.
It would be helpful to make a class circle which has a velocity value, it moves by that velocity value every frame so no `TweenService` is needed! It will also help, greatly, with the mouse part. Good luck!
2 Likes

You could try to figure out the physics and lines of the particles all in 2D, but I think it would be far easier to just use the 3D physics and tools that Roblox already provides. I would make the particles 3D and work in the background with your GUI shown over it.

Here’s a demonstration of how I did it:

The black background and white dots are parts. The particle you see moving uses LinearVelocity, and the lines are made using beams. A script loops through all existing particles and checks whether a particle is closer to other particles. There is also another loop that checks whether the mouse is near the moving particle and makes calculations to LinearVelocity if so. The script uses the mouse’s Hit property to detect when the mouse is close to particles, and the background part ensures the Hit position doesn’t move too far from the particles.

I know you didn’t ask for code, but I’ll still provide it. It’s not complete yet anyway and only gives you a basic idea of what to do.

Code
local StarterGui = game:GetService("StarterGui")
local RunService = game:GetService("RunService")

local Mouse = game.Players.LocalPlayer:GetMouse()

-- Part inside script
local Particle = script.Particle:Clone()
local Clone = Particle:Clone()

-- Attach/Detach beams to other particles depending on magnitude.
function CheckMagnitude(part)
	while true do
		task.wait()
		for _, v in pairs(workspace:GetChildren()) do -- Searches for other "Particle" parts under Workspace.
			if v.Name == "Particle" and not rawequal(part, v) then
				local Beam1 = part:FindFirstChild("Beam1")
				local Beam2 = part:FindFirstChild("Beam2")
				
				-- Disconnect particles if they move too far from each other.
				if (Beam1.Attachment1 ~= nil and (Beam1.Attachment0.WorldCFrame.Position - Beam1.Attachment1.WorldCFrame.Position).Magnitude > 5) then
					Beam1.Attachment1 = nil
				end
				if (Beam2.Attachment1 ~= nil and (Beam2.Attachment0.WorldCFrame.Position - Beam2.Attachment1.WorldCFrame.Position).Magnitude > 5) then
					Beam2.Attachment1 = nil
				end

				if (v.Position - part.Position).Magnitude < 5 then -- Connect particles if they come close.
					if Beam1.Attachment1 == nil then
						Beam1.Attachment1 = v.Attachment
					elseif Beam2.Attachment1 == nil and not rawequal(Beam1.Attachment1, v.Attachment) then
						Beam2.Attachment1 = v.Attachment
					end
				end
			end
		end
	end
end

task.wait(1)

-- Set camera to black screen.
workspace.CurrentCamera.CameraType = Enum.CameraType.Scriptable
workspace.CurrentCamera.CFrame = workspace.CameraPart.CFrame

StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.All, false)

task.wait(3)

Clone.Parent = workspace

-- Keep particle away from mouse.
RunService.RenderStepped:Connect(function()
	if (Mouse.Hit.Position - Clone.Position).Magnitude < 3 then
		-- Lerp VectorVelocity so the particle would decelerate near the mouse instead of "bouncing".
		Clone.LinearVelocity.VectorVelocity = Clone.LinearVelocity.VectorVelocity:Lerp((Clone.Position - Mouse.Hit.Position).Unit * 5, 0.05)
		-- X is set to 0 so the particle won't be floating torwards or away from the camera. Y and Z are also clamped so it doesn't just zoom away.
		Clone.LinearVelocity.VectorVelocity = Vector3.new(0, math.clamp(Clone.LinearVelocity.VectorVelocity.Y, -5, 5), math.clamp(Clone.LinearVelocity.VectorVelocity.Z, -5, 5))
	end
end)

CheckMagnitude(Clone)

Hopefully this helps. If you have any questions, feel free to ask.

4 Likes

The game is called british railways, my friend. Very cool game.

1 Like