I made this place around 2 years ago, I think this might have the effect you are looking for:
Screen Saver Simulator - Roblox
I read through it quite quickly now, and I’m gonna be honest, it is a bit of a headache.
local TS = game:GetService("TweenService")
-- Services ^
math.randomseed(os.time())
--- Appearance
local radius = 250 -- Particle target radis
local ratio = 5 -- How far the shortest distance is (radius/ratio)
local icon = script.Parent
local bg = script:FindFirstAncestorWhichIsA("ScreenGui")
local pos = icon.AbsolutePosition - bg.AbsolutePosition
local size = icon.AbsoluteSize
local bgSize = bg.AbsoluteSize
local angle = 45
local speed = icon.Speed.Value -- Unit is pixels / 0.025 seconds
local lastSize = bgSize
--icon.Position = UDim2.fromOffset((bgSize.X + size.X)/2, (bgSize.Y + size.Y)/2)
local missed = Vector2.new(0, 0)
function bounce(pos)
lastSize = bgSize
if pos == "top" then
pos = UDim2.fromOffset(icon.Position.X.Offset + size.X/2, 0)
elseif pos == "bot" then
pos = UDim2.fromOffset(icon.Position.X.Offset + size.X/2, bgSize.Y)
elseif pos == "left" then
pos = UDim2.fromOffset(0, icon.Position.Y.Offset + size.Y/2)
elseif pos == "right" then
pos = UDim2.fromOffset(bgSize.X, icon.Position.Y.Offset + size.Y/2)
else
return
end
--[[ -- Doesn't work.
local p = Instance.new("Frame")
local a = Instance.new("UIAspectRatioConstraint", p)
p.Size = UDim2.new(0, 10, 0, 10)
p.Rotation = 0
p.Position = pos
p.BorderSizePixel = 0
p.Parent = bg
TS:Create(p, TweenInfo.new(.5), { Size = UDim2.fromOffset(math.random(10, 50), math.random(10, 50)), Rotation = 45 }):Play()
local t = TS:Create(p, TweenInfo.new(1), { BackgroundTransparency = 1 })
t:Play()
t.Completed:Connect(function()
p:Destroy()
end)
]]
local maxX = pos.X.Offset + radius
local minX = pos.X.Offset + radius/ratio
local maxY = pos.Y.Offset + radius
local minY = pos.Y.Offset + radius/ratio
if maxX > bgSize.X then
minX = maxX - 2*radius
maxX = pos.X.Offset - radius/ratio
end
if maxY > bgSize.Y then
minY = maxY - 2*radius
maxY = pos.Y.Offset - radius/ratio
end
for i=1, 5, 1 do
local p = Instance.new("Frame")
local a = Instance.new("UIAspectRatioConstraint", p)
p.Size = UDim2.new(0, math.random(5,25), 0, math.random(5,25))
p.Rotation = math.random(0, 90)
p.Position = pos
p.BorderSizePixel = 0
p.Parent = bg
TS:Create(p, TweenInfo.new(5), { Position = UDim2.fromOffset(math.random(minX, maxX), math.random(minY, maxY)), Rotation = math.random(0, 1080)} ):Play()
local t = TS:Create(p, TweenInfo.new(3), { BackgroundTransparency = 1 })
t:Play()
t.Completed:Connect(function()
p:Destroy()
end)
end
end
wait(1.5)
function corner()
if lastSize ~= bgSize then return end
bg.Highlight.Visible = true
local prevColor = bg.Background.BackgroundColor3
local t = TS:Create(bg.Background, TweenInfo.new(.1), { BackgroundColor3 = Color3.fromRGB(100, 100, 100)})
t:Play()
t.Completed:Connect(function()
TS:Create(bg.Background, TweenInfo.new(1), { BackgroundColor3 = prevColor}):Play()
for _, bar in pairs(bg.Highlight:GetChildren()) do
TS:Create(bar, TweenInfo.new(2), { BackgroundTransparency = 1}):Play()
end
wait(2)
bg.Highlight.Visible = false
for _, bar in pairs(bg.Highlight:GetChildren()) do
bar.BackgroundTransparency = 0
end
end)
bg.Background.cornerhits.Text = game.ReplicatedStorage.MasterFunc:InvokeServer("Cornerhit")
end
spawn(function()
while wait(0.025) do
-- Update variables
pos = icon.AbsolutePosition - script:FindFirstAncestorWhichIsA("ScreenGui").AbsolutePosition
size = icon.AbsoluteSize
bgSize = bg.AbsoluteSize
speed = icon.Speed.Value
angle = angle%360
-----------------------------
-- Movement
local newPos = Vector2.new((speed * math.cos(math.rad(angle)) + (missed.X%1)), (speed * math.sin(math.rad(angle)) + (missed.Y%1)))
icon.Position = icon.Position + UDim2.fromOffset(newPos.X, newPos.Y)
missed = missed - Vector2.new(missed.X%1, missed.Y%1)
missed = missed + Vector2.new(newPos.X%1, newPos.Y%1)
----------------------------
-- Corner
if pos.Y <= 0 or pos.Y + size.Y >= bgSize.Y then
if pos.X <= 0 or pos.X + size.X >= bgSize.X then
corner()
end
end
----------------------------
-- Bounce
if pos.Y + size.Y >= bgSize.Y then -- Bottom
angle = 360 - angle
icon.Position = UDim2.fromOffset(icon.Position.X.Offset, bgSize.Y - size.Y - 1)
bounce("bot")
elseif pos.Y <= 0 then -- Top
angle = 360 - angle
icon.Position = UDim2.fromOffset(icon.Position.X.Offset, 1)
bounce("top")
elseif pos.X + size.X >= bgSize.X then
angle = 180 - angle
icon.Position = UDim2.fromOffset(bgSize.X - size.X - 1, icon.Position.Y.Offset)
bounce("right")
elseif pos.X <= 0 then
bounce("left")
angle = 180 - angle
icon.Position = UDim2.fromOffset(1, icon.Position.Y.Offset)
end
end
end)
I (of course) didn’t leave any comments for my future self, but from reading through the code it looks like I changed the angle by using Axis - angle
or something.
But the principles of the bounce is that the outgoing angle should be the same as the incoming one, except flipped on whichever axis you are at.