I would like to create a gravity simulation using a method that provides good efficiency (Barnes-Hut algorithm)
I found this link GitHub - liuchia/barnes-hut: love2d nbody simulation which has everything i need, it’s just in 2D
but since I don’t have much experience with programming I can’t make it work
I’ve already tried asking friends for help, using ChatGPT and searching the internet for something similar, but this code doesn’t seem to be very popular
Algorithm definition
Barnes-Hut is a fast algorithm for approximating the forces between particles in a large-scale gravitational system, such as stars or galaxies.
algorithm works by recursively dividing the system into smaller regions with Quadtree/Octree method, so the calculation goes from being between each particle, to a calculation concentrated in the center of mass of a region, improving the efficiency of the simulation
This is my code without octree:
local RunService = game:GetService("RunService")
local SimulationTimeStep = 1
local G = 1
local Body = {}
Body.__index = Body
function Body.new(mass, pos, vel, body)
return setmetatable({
mass = mass,
pos = pos,
vel = vel,
body = body
}, Body)
end
local simulatedObjects = {}
for i, body in ipairs(workspace.Folder:GetChildren()) do
local mass = body:GetAttribute("mass")
local pos = body.Position
local vel = body:GetAttribute("velocity")
simulatedObjects[i] = Body.new(mass, pos, vel, body)
end
RunService.Heartbeat:Connect(function(TimeStep)
TimeStep *= SimulationTimeStep
for i = 1, #simulatedObjects - 1 do
for j = i + 1, #simulatedObjects do
local BodyA, BodyB = simulatedObjects[i], simulatedObjects[j]
local DirectionVector = BodyA.pos - BodyB.pos
local DirectionNorml = DirectionVector.Unit
local dist = DirectionVector.Magnitude
local F = G * BodyA.mass * BodyB.mass / dist
local acelerationA = F / BodyA.mass / dist
local acelerationB = F / BodyB.mass / dist
BodyA.vel -= DirectionNorml * (acelerationA * TimeStep)
BodyB.vel += DirectionNorml * (acelerationB * TimeStep)
end
end
for _, v in ipairs(simulatedObjects) do
v.pos += v.vel * TimeStep
v.body.Position = v.pos
end
end)
That would be the desired result