Run it
Copy the script and paste it into your executor.
().BallTracerCleanup (().BallTracerCleanup)
RunService = :()
UIS = :()
cam = .CurrentCamera
CFG = {
Enabled = ,
Color = .(, , ),
Thickness = ,
SimStep = / ,
MaxTime = ,
MaxBounces = ,
Gravity = ,
FloorBounce = ,
WallBounce = ,
CornerRadius = ,
GoalHalfWidth = ,
GoalHeight = ,
GoalDepth = ,
MinSpeed = ,
Window = ,
GroundY = ,
HitThreshold = ,
}
MAX_PTS = .(CFG.MaxTime / CFG.SimStep) +
gui = .()
gui.Name =
gui.IgnoreGuiInset =
gui.ResetOnSpawn =
gui.DisplayOrder =
gui.Parent = (gethui ()) :()
lines = {}
i = , MAX_PTS
f = .()
f.AnchorPoint = .(, )
f.BorderSizePixel =
f.Visible =
f.Parent = gui
lines[i] = f
conns = {}
().BallTracerCleanup = ()
_, c (conns) c:()
gui:()
().BallTracerCleanup =
(n)
i = n, MAX_PTS lines[i].Visible =
(f, a, b)
d = b - a
len = d.Magnitude
f.Position = .((a.X + b.X) / , (a.Y + b.Y) / )
f.Size = .(len + , CFG.Thickness)
f.Rotation = .(.(d.Y, d.X))
f.BackgroundColor3 = CFG.Color
f.Visible =
BOX = { min = .(-, , -), max = .(, , ) }
hist = {}
vel = .zero
base =
(ball, now)
p = ball.Position
grounded = p.Y < CFG.GroundY
G = .(, grounded -CFG.Gravity, )
fresh =
last = hist[#hist]
last
dt = now - last.t
dt <=
pred = last.p + vel * dt + G * ( * dt * dt)
(p - pred).Magnitude > CFG.HitThreshold (p - last.p).Magnitude >
hist = {}
fresh =
hist[#hist + ] = { t = now, p = p }
#hist > now - hist[].t > CFG.Window .(hist, )
base = p
n = #hist
n < now - hist[].t <
sumT, sumP = , .zero
pcs = .(n)
taus = .(n)
i, h (hist)
tau = h.t - now
pc = h.p - G * ( * tau * tau)
taus[i], pcs[i] = tau, pc
sumT += tau
sumP += pc
tm, pm = sumT / n, sumP / n
sxx, sxy = , .zero
i = , n
dtau = taus[i] - tm
sxx += dtau * dtau
sxy += (pcs[i] - pm) * dtau
sxx <
newVel = sxy / sxx
vel = (fresh n <= ) newVel vel:(newVel, )
base = pm - newVel * tm
(p)
v = cam:(p)
.(v.X, v.Y), v.Z
pts = .(MAX_PTS)
(now)
bodies = :()
ball = bodies bodies:()
CFG.Enabled ball
()
hist = {}
cam = .CurrentCamera
(ball, now)
radius = .(ball.Size.X, ball.Size.Y, ball.Size.Z) /
p, v = base ball.Position, vel
v.Magnitude < CFG.MinSpeed ()
g = .(, -CFG.Gravity, )
R = CFG.CornerRadius
bounces, count, t = , ,
pts[] = p
t < CFG.MaxTime count < MAX_PTS
nv = v + g * CFG.SimStep
np = p + (v + nv) * * CFG.SimStep
bmin, bmax = BOX.min, BOX.max
.(np.X) < CFG.GoalHalfWidth np.Y < CFG.GoalHeight
bmin = .(bmin.X, bmin.Y, -CFG.GoalDepth)
bmax = .(bmax.X, bmax.Y, CFG.GoalDepth)
lo = bmin + .one * (radius + R)
hi = bmax - .one * (radius + R)
q = .(.(np.X, lo.X, hi.X), .(np.Y, lo.Y, hi.Y), .(np.Z, lo.Z, hi.Z))
d = np - q
dist = d.Magnitude
dist > R dist >
n = d / dist
vn = nv:(n)
vn >
np = q + n * R
e = CFG.WallBounce + (CFG.FloorBounce - CFG.WallBounce) * .(n.Y)
nv = nv - n * vn * ( + e)
vn > bounces +=
count +=
pts[count] = np
p, v = np, nv
t += CFG.SimStep
bounces > CFG.MaxBounces
v.Magnitude < CFG.MinSpeed bounces >
scr, depth = .(count), .(count)
i = , count scr[i], depth[i] = (pts[i])
used =
i = , count -
a2, b2, ad, bd = scr[i], scr[i + ], depth[i], depth[i + ]
ad > bd >
ad <=
a2 = (pts[i]:(pts[i + ], ( - ad) / (bd - ad)))
bd <=
b2 = (pts[i]:(pts[i + ], ( - ad) / (bd - ad)))
used +=
(lines[used], a2, b2)
(used + )
.(conns, RunService.RenderStepped:(()
(.())
))
.(conns, UIS.InputBegan:((input, gpe)
gpe
k = input.KeyCode
k == .KeyCode.KeypadPlus k == .KeyCode.Equals
CFG.Enabled = CFG.Enabled
( .. (CFG.Enabled ))
))
().BallTracerCFG = CFG
()Small little ball trajectory for Blox League.