Need help with math (circles)

Since I have nowhere to go, countless of google attempts led me to basically nothing and none to really ask I came here. I’m also very bad in math if it’s related to geometry.

I spent the last 4 hours trying to figure how to make the circle change it’s size (not radius, x or y but for example from a full circle go 7/8 of the circle) based on the player health.

I’ve got this function:

function GenCircle(x,y,radius,quality)
local circle = {}
local tmp = 0
for i=1,quality do
tmp = rad(i360)/quality
= {x = x + cos(tmp)*radius,y = y + sin(tmp)*radius}
return circle

which I later use to draw few circles

circleDraw1 = GenCircle(20,20, 200, 100)

circleDraw2 = GenCircle(20,20, 170, 100)
surface.SetDrawColor( Color( 255, 60, 60))
surface.SetDrawColor( Color( 100, 100, 100))



What I want it to do is reduce the size of the circle based on players health, if the player has for example 90 HP then it’ll be 9/10 of it’s size. (note: without moving the circle itself)

I was thinking of using images instead and do a few conditionals, see what to display but I don’t think it’ll work out well.


Time to waste another 4 hours and explore that thing, thanks! (no sarcasm, even if it sounds like that)

Here’s something I whipped up that you can use or learn from.
In order to draw half a circle you simply have to make your loop smaller or bigger.
There’s absolutely no need to mess around with scissor rects, if that works at all because it seems to clip things in a square shape.


function scaleVertices(tblVertices, iScaleX, iScaleY)
for k, v in pairs(tblVertices) do
v.x = v.x * iScaleX
v.y = v.y * iScaleY

function offsetVertices(tblVertices, iOffsetX, iOffsetY)
for k, v in pairs(tblVertices) do
v.x = v.x + iOffsetX
v.y = v.y + iOffsetY

function createCircle(iStartAngle, iEndAngle, iStepSize)
assert(iStepSize > 0 and iStepSize < 360, “invalid iStepSize”)

local tblVertices = {}

-- Unless we're a full circle, add a center point.
if math.abs(iStartAngle - iEndAngle) != 0 then
	table.insert(tblVertices, {x = 0, y = 0})

for iAngle = iStartAngle, iEndAngle + iStepSize, iStepSize do -- We're adding the stepsize to the end angle here, because if we have a circle between 0-90 and the stepsize is 80, we'd otherwise miss out on the last 10.
	iAngle = math.Clamp(iAngle, iStartAngle, iEndAngle) -- So here we make sure that we still clamp our angles to the start and end.
	local iRadians = math.rad(iAngle)
	local iVertexX = math.sin(iRadians)
	local iVertexY = math.cos(iRadians)
	table.insert(tblVertices, {x = iVertexX, y = iVertexY})

return tblVertices


hook.Add(“HUDPaint”, “DrawCircleExample”, function()
local iCircleAngle = 90 / 100 * LocalPlayer():Health()
local tblVertices = createCircle(0, iCircleAngle, 90 / 16)

scaleVertices(tblVertices, ScrH() * 0.25, ScrH() * 0.25)
offsetVertices(tblVertices, 40, 40)

surface.SetDrawColor(Color(255, 0, 0, 100))


If you decide to use this code, then please for performance reasons, don’t call createCircle/scaleVertices/offsetVertices all time in your HUDPaint hook like my example does.
Call it once outside your HUDPaint hook and then store the vertices, and only recreate the shape when the health changes or the screen resolution changes.

Oh and a screenshot:

Thank you very much!

It’s easier and it works just fine if you position it correctly.

there was another thread earlier this year that was trying to accomplish the same thing, there is a code snippet at the bottom with an example: