OOP Pendulum Simulation Module

ok so I have made a Pendulum Module in the past year for my loading and soft shutdown screens and I wanted to share it in the devforum

demo video:

Insert this into the module: (the pendulum bob)
template.rbxm (2.2 KB)
Module:

local Pendulum = {}
local Static = {}

local function drawLine(parent: Instance, color: Color3): Frame
	local line = Instance.new("Frame", parent)
	line.AnchorPoint = Vector2.new(.5, .5)
	
	line.BackgroundColor3 = color
	line.BorderSizePixel = 0
	
	line.Parent = parent
	
	return line
end

local function updateLine(line: Frame, x1: number, y1: number, x2: number, y2: number, thickness: number)
	local centerX = (x1 + x2) / 2
	local centerY = (y1 + y2) / 2
	
	local deltaX = math.abs(x1 - x2) ^ 2
	local deltaY = math.abs(y1 - y2) ^ 2
	
	local distance = math.sqrt(deltaX + deltaY)
	local rotation = math.deg(math.atan2(y1 - y2, x1 - x2))
	
	line.Position = UDim2.fromOffset(centerX, centerY)
	line.Size = UDim2.fromOffset(distance, thickness or 1)
	
	line.Rotation = rotation
end

function Pendulum.new(origin: Vector2, len: number, parent: Instance)
	local self = setmetatable({
		pos = Vector2.zero;
		origin = origin;
		len = len;
		
		angle = math.pi / 4;
		angleV = 0;
		angleA = .01;
		gravity = .5;
		size = 12;
						
		object = script.template:Clone();
		line = drawLine(parent, Color3.new(1, 1, 1))
	}, {__index = Static});
	
	self.object.Size = UDim2.fromOffset(self.size, self.size)
	self.object.Parent = parent
	
	return self
end

function Static:render()
	if not self.object or not self.line then return end
	
	self.object.Position = UDim2.fromOffset(self.pos.X, self.pos.Y)
	
	updateLine(self.line, self.origin.X, self.origin.Y, self.pos.X, self.pos.Y, 1)
end

function Static:update()
	local force = self.gravity * math.sin(self.angle);
	self.angleA = (-1 * force) / self.len;
	
	self.angleV += self.angleA;
	self.angle += self.angleV;
	
	self.pos = Vector2.new(self.len * math.sin(self.angle) + self.origin.X, self.len * math.cos(self.angle) + self.origin.Y); 
end

function Static:Destroy()
	self.object:Destroy()
	self.line:Destroy()
end

return Pendulum

Usage:

	local pendulums = {}
        -- the length of the rope i found online (#length must be equal to count)
	local length = {301.05, 289.58, 278.75, 268.53, 258.85, 249.69, 241, 232.76, 224.94, 217.51, 210.43, 203.7, 197.28, 191.17, 185.33}

	local count = 15

	for i = 1, count do
		table.insert(pendulums, Pendulum.new(Vector2.new(Canvas.AbsoluteSize.X/2, Canvas.AbsoluteSize.Y/2), length[i], Canvas)) -- the main pendulum pivot point is in the center of Canvas as a Vector2
	end

	RunService:BindToRenderStep('pendulumAnimation', 1, function() -- do the cycle
		for _, pendulum in pendulums do
			pendulum:render()
			pendulum:update()
		end
	end)

so… yeah that’s it, if there’s any inaccuracy or anything I’ve overlooked, please let me know.
you can use this in your loading screens, other guis, or If you’re feeling fancy make it work in a 3d environment

unlocked place:

6 Likes

I’ve got it to work, and I have to say that it is really satisfying. Not sure what practical applications this has besides maybe a loading screen like you said. If you want this to be more developer friendly, consider making a public model or an example place. I wasn’t sure what “template” was at first and there were no instructions, but a frame seemed to work well.

1 Like

I forgot to add the template bob frame oopsie :neutral_face:, I have added the template place for anyone to use

1 Like

A video of your resource would be awesome. :+1:

2 Likes