Skip to content

Instantly share code, notes, and snippets.

@cozywitchcraft
Created May 24, 2026 13:53
Show Gist options
  • Select an option

  • Save cozywitchcraft/382e489547356678898d516876fcc3c2 to your computer and use it in GitHub Desktop.

Select an option

Save cozywitchcraft/382e489547356678898d516876fcc3c2 to your computer and use it in GitHub Desktop.
Google Balls 2008 Roblox
-- StarterPack.GoogleBalls
local Players = game:service("Players")
local RunService = game:service("RunService")
local XY = Vector3.new(1, 1)
local Z = Vector3.new(0, 0, 1)
-- Util
local function fromHex(hex)
local dec = tonumber(string.sub(hex, 2), 16)
local r = math.floor(dec / 65536)
local g = math.floor(dec / 256) % 256
local b = dec % 256
return Color3.new(r / 255, g / 255, b / 255)
end
local function toPoint(v)
return Vector3.new(10 * v.x, 10 * v.z)
end
local function toWorld(v, y)
return Vector3.new(v.x / 10, y, v.y / 10)
end
-- Point
local function updatePoint(self, deltaTime)
local offset = (self.currentPosition - self.originalPosition) * XY
self.targetPosition = XY * self.targetPosition + Z * (offset.magnitude / 100 + 1)
local delta = self.targetPosition - self.currentPosition
self.velocity = self.friction * (self.velocity + delta * self.springStrength)
self.currentPosition = self.currentPosition + self.velocity * (deltaTime * 30)
self.radius = math.max(self.size * self.currentPosition.z, 1.0)
end
local function drawPoint(self)
local radius = self.radius / 10
self.part.Size = Vector3.new(radius, radius, radius)
self.part.CFrame = CFrame.new(toWorld(self.currentPosition, 5))
end
function Point(x, y, z, size, color)
local position = Vector3.new(x, y, z)
local part = Instance.new("Part")
part.Anchored = true
part.BrickColor = BrickColor.new(fromHex(color))
part.CanCollide = false
part.Shape = Enum.PartType.Ball
part.TopSurface = Enum.SurfaceType.Smooth
part.BottomSurface = Enum.SurfaceType.Smooth
part.Parent = workspace
return {
part = part,
color = fromHex(color),
currentPosition = position,
originalPosition = position,
friction = 0.8,
radius = size,
size = size,
springStrength = 0.1,
targetPosition = position,
velocity = Vector3.new(),
update = updatePoint,
draw = drawPoint,
}
end
-- PointCollection
local function updatePointCollection(self, deltaTime)
for _, point in pairs(self.points) do
local delta = self.mousePosition - point.currentPosition
if delta.magnitude < 150 then
point.targetPosition = point.currentPosition - delta
else
point.targetPosition = point.originalPosition
end
point:update(deltaTime)
end
end
local function drawPointCollection(self)
for _, point in pairs(self.points) do
point:draw()
end
end
function PointCollection(points)
return {
mousePosition = Vector3.new(),
points = points,
update = updatePointCollection,
draw = drawPointCollection,
}
end
-- Main
local function init()
local localPlayer = Players.LocalPlayer
local pointCollection = PointCollection({ Point(202, 78, 0.0, 9, "#ed9d33"), Point(348, 83, 0.0, 9, "#d44d61"), Point(256, 69, 0.0, 9, "#4f7af2"), Point(214, 59, 0.0, 9, "#ef9a1e"), Point(265, 36, 0.0, 9, "#4976f3"), Point(300, 78, 0.0, 9, "#269230"), Point(294, 59, 0.0, 9, "#1f9e2c"), Point(45, 88, 0.0, 9, "#1c48dd"), Point(268, 52, 0.0, 9, "#2a56ea"), Point(73, 83, 0.0, 9, "#3355d8"), Point(294, 6, 0.0, 9, "#36b641"), Point(235, 62, 0.0, 9, "#2e5def"), Point(353, 42, 0.0, 8, "#d53747"), Point(336, 52, 0.0, 8, "#eb676f"), Point(208, 41, 0.0, 8, "#f9b125"), Point(321, 70, 0.0, 8, "#de3646"), Point(8, 60, 0.0, 8, "#2a59f0"), Point(180, 81, 0.0, 8, "#eb9c31"), Point(146, 65, 0.0, 8, "#c41731"), Point(145, 49, 0.0, 8, "#d82038"), Point(246, 34, 0.0, 8, "#5f8af8"), Point(169, 69, 0.0, 8, "#efa11e"), Point(273, 99, 0.0, 8, "#2e55e2"), Point(248, 120, 0.0, 8, "#4167e4"), Point(294, 41, 0.0, 8, "#0b991a"), Point(267, 114, 0.0, 8, "#4869e3"), Point(78, 67, 0.0, 8, "#3059e3"), Point(294, 23, 0.0, 8, "#10a11d"), Point(117, 83, 0.0, 8, "#cf4055"), Point(137, 80, 0.0, 8, "#cd4359"), Point(14, 71, 0.0, 8, "#2855ea"), Point(331, 80, 0.0, 8, "#ca273c"), Point(25, 82, 0.0, 8, "#2650e1"), Point(233, 46, 0.0, 8, "#4a7bf9"), Point(73, 13, 0.0, 8, "#3d65e7"), Point(327, 35, 0.0, 6, "#f47875"), Point(319, 46, 0.0, 6, "#f36764"), Point(256, 81, 0.0, 6, "#1d4eeb"), Point(244, 88, 0.0, 6, "#698bf1"), Point(194, 32, 0.0, 6, "#fac652"), Point(97, 56, 0.0, 6, "#ee5257"), Point(105, 75, 0.0, 6, "#cf2a3f"), Point(42, 4, 0.0, 6, "#5681f5"), Point(10, 27, 0.0, 6, "#4577f6"), Point(166, 55, 0.0, 6, "#f7b326"), Point(266, 88, 0.0, 6, "#2b58e8"), Point(178, 34, 0.0, 6, "#facb5e"), Point(100, 65, 0.0, 6, "#e02e3d"), Point(343, 32, 0.0, 6, "#f16d6f"), Point(59, 5, 0.0, 6, "#507bf2"), Point(27, 9, 0.0, 6, "#5683f7"), Point(233, 116, 0.0, 6, "#3158e2"), Point(123, 32, 0.0, 6, "#f0696c"), Point(6, 38, 0.0, 6, "#3769f6"), Point(63, 62, 0.0, 6, "#6084ef"), Point(6, 49, 0.0, 6, "#2a5cf4"), Point(108, 36, 0.0, 6, "#f4716e"), Point(169, 43, 0.0, 6, "#f8c247"), Point(137, 37, 0.0, 6, "#e74653"), Point(318, 58, 0.0, 6, "#ec4147"), Point(226, 100, 0.0, 5, "#4876f1"), Point(101, 46, 0.0, 5, "#ef5c5c"), Point(226, 108, 0.0, 5, "#2552ea"), Point(17, 17, 0.0, 5, "#4779f7"), Point(232, 93, 0.0, 5, "#4b78f1") })
RunService.Heartbeat:connect(function(deltaTime)
local character = localPlayer.Character
local head = character and character:FindFirstChild("Head")
if not head then
return
end
pointCollection.mousePosition = toPoint(head.Position)
pointCollection:update(deltaTime)
pointCollection:draw()
end)
end
init()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment