Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion

edited July 2016 Posts: 160

Hello!
I'm trying to make a circle shatter into a bunch of peices when you tap the screen, but I'm having trouble figuring out what points I need to use when creating the slices. I'm worried I might have to use some of the math functions I don't understand like `math.acos`, `math.cosh`, `math.asin`, `math.sinh`, `math.atan`, `math.tanh`, `math.fmod`, and `math.log` (I do understand however, that cosine is adjecent / hypotenuse, sine is oposite / hypotenuse and tangent is oposite / adjecent in a triangle). Don't blame me, I'm not in high school yet. I've tried learning these math functions through the internet, but that kind of math was very confusing. I'm hoping someone can help me here on the forums. I would love someone to help me write the code, but giving me some easy-to-understand tutorials on these math functions would also be great!
Here's what I have so far:

``````-- Use this function to perform your initial setup
function setup()
borders = physics.body(CHAIN,true,vec2(0,0),vec2(WIDTH,0),vec2(WIDTH,HEIGHT),vec2(0,HEIGHT))

bodies = {}
newBody(physics.body(CIRCLE, 100), WIDTH/2, HEIGHT/2, vec2(0,0))
--newBody(physics.body(POLYGON,vec2(-100,-100),vec2(0,100),vec2(100,-100)),200,HEIGHT-100)

physics.gravity(0,-700)
end

-- This function gets called once every frame
function draw()
-- This sets a dark background color
background(40, 40, 50)

-- Do your drawing here
for k,t in pairs(bodies) do
pushMatrix()
translate(t.b.x,t.b.y)
if t.b.shapeType == POLYGON then
rotate(t.b.angle)
t.m:draw()
elseif t.b.shapeType == CIRCLE then
pushStyle()
fill(0,0,255)
noStroke()
popStyle()
end
popMatrix()
end
end

function touched(t)
if t.state == ENDED then
-- First we create new bodies in the shapes of the circle sliced (how??)

bodies[1].b:destroy()
table.remove(bodies,1) -- Then we remove the original circle
end
end

function newBody(b, x, y, vel, ang, rotSpeed)
local velocity
if vel then
velocity = vec2(vel.x,vel.y)
else
velocity = vec2(0,0)
end

b.position = vec2(x,y)
b.linearVelocity = velocity
b.angle = ang or 0
b.angularVelocity = rotSpeed or 0
b.restitution = 0.4

local m = mesh()
if b.shapeType == POLYGON then
m.vertices = triangulate(b.points)
end
m:setColors(0,0,255)

table.insert(bodies, {b=b,m=m})
end
``````

Thank-you so much in advance!

Tagged:

• Mod
Posts: 2,020

The easiest way would be to have it shatter into pie-slices (pi slices? )

Is that what you want though?

You say "shatter" which implies to me that you'd like the pieces to be more irregular and unevenly shaped.

• Posts: 160

Yes, that is what I was implying when I said shatter. But if that's too complicated, the pie slices would work too. (and thank-you for helping out! )

• edited July 2016 Posts: 160

I'm sorry to do so but, I've actually changed my mind. I think the pie slices method would be a lot better because if we use the other option we will end up with peices that are very small which is not so good for the game I'll be using this for. I think the pie slices can be made with a couple for loops, `math.cos` and `math.sin`, but I'm not sure exactly how to do it.

• Mod
Posts: 5,396

@Kolosso - we are happy to help solve problems, but we do ask people to make an effort first, because we are a small group.

Unless you are expecting us to write all the code for you, you will need to learn a bit about sin, cos, tan. They really aren't very difficult, even if you aren't in high school yet, and you need them all the time to do graphics programming.

There are stacks of tutorials on them, much better than anything we could do. Why reinvent the wheel?

Why don't you look at all the stuff out there, try to get a basic understanding of trig functions, then come back and have a go with Codea?

• Mod
Posts: 2,020

Sorry, couldn't resist. Codea's triangulate function creates nice, spiky looking segments.

``````--# Main
-- Circle Shatter

function setup()
--unique points describing circle
local noPoints = 24 --must be a multiple of 3
local points = {}
local radius = 100
local angleStep = (math.pi * 2) / noPoints
for i = 1,noPoints do
local angle = (i-1) * angleStep
points[i] = vec2(radius * math.sin(angle), radius * math.cos(angle))
end

local verts = triangulate(points) --triangulate points
bodies = {}
local col = color(0, 235, 255, 255)
local pos = vec2(WIDTH/2, HEIGHT/2) --position of circle
print("triangles:", #verts / 3)
for i = 1, #verts, 3 do
local a = verts[i] * 1 -- *1 to make a new copy of the vec
local b = verts[i+1] * 1
local c = verts[i+2] * 1
local centre = (a+b+c)/3
a = a - centre
b = b - centre
c = c - centre
table.insert(bodies, Triangle(centre, pos, col, a, b, c))
end
end

function draw()
background(40, 40, 50)
for i = 1, #bodies do
bodies[i]:draw()
end

end

function touched(t)
for i = 1, #bodies do
bodies[i]:touched()
end
end

--# Triangle
Triangle = class()

local function randomRange(n)
return (math.random() - 0.5) * n * 2
end

function Triangle:init(segmentPos, circlePos, col, a,b,c)
self.body = physics.body(POLYGON, a, b, c)
self.body.position = segmentPos + circlePos
self.body.gravityScale = 0 --not affected by gravity. yet...
self.body.interpolate = true
self.mesh = mesh()
local mag = 1.01 --make mesh slightly bigger to cover cracks. Or, smaller, 0.99 if you want cracks
self.mesh.vertices = {a * mag,b * mag,c * mag}
self.mesh:setColors(col)
--the vector that the segment will explode along is its normalized segment position, plus anti-gravity, plus noise
self.escapeVelocity = (segmentPos:normalize() + vec2(randomRange(0.5),1 + math.random() * 0.4)) * 3
end

function Triangle:draw()
pushMatrix()
translate(self.body.x, self.body.y)
rotate(self.body.angle)
self.mesh:draw()
popMatrix()
end

function Triangle:touched()
self.body.gravityScale = 1
self.body:applyLinearImpulse(self.escapeVelocity)
self.body:applyAngularImpulse(randomRange(10))
end
``````
• Posts: 160

@yojimbo2000, Thank-you so much! Like I said, I have changed my mind so I may not use the code you provided in my game (and I'm sorry about it) but I will still try to learn from it. I bet there are many techniques in your code.

@Ignatz, Sorry for causing any problems. I have looked up cosine, sine and tangent tutorials on the internet and I'm currently trying my best to split the circle into even pie slices with them.

• Mod
Posts: 2,020

Well, look at the first for loop in my setup function for your pi slices.

• Posts: 160

I looked at this code in your setup function, and after quite a few experiments, I think I finally understand how it works!!:

``````    local noPoints = 24 --must be a multiple of 3
local points = {}
local radius = 100
local angleStep = (math.pi * 2) / noPoints
for i = 1,noPoints do
local angle = (i-1) * angleStep
points[i] = vec2(radius * math.sin(angle), radius * math.cos(angle))
end
``````

Thanks, @yojimbo2000!

• Mod
edited July 2016 Posts: 9,480

@Kolosso Thought I'd give a try at the exploding circle. Tap the screen to explode it. Do a restart to see it again.

``````displayMode(FULLSCREEN)

function setup()
e1=physics.body(EDGE,vec2(0,0),vec2(0,HEIGHT))
e2=physics.body(EDGE,vec2(WIDTH,0),vec2(WIDTH,HEIGHT))
e3=physics.body(EDGE,vec2(0,0),vec2(WIDTH,0))
e4=physics.body(EDGE,vec2(0,HEIGHT),vec2(WIDTH,HEIGHT))
ba={}
for x=1,16 do
table.insert(ba,ball(WIDTH/2,HEIGHT/2))
end
physics.continuous=true
end

function draw()
background(40, 40, 50)
stroke(255)
strokeWidth(2)
noFill()
if not hide then
ellipse(WIDTH/2,HEIGHT/2,40)
else
for a,b in pairs(ba) do
b:draw()
end
end
end

function touched(t)
if t.state==BEGAN and not hide then
hide=true
for z=1,#ba do
ba[z].a.type=DYNAMIC
ba[z].a.linearVelocity=vec2(math.random(-300,300),math.random(-300,300))
end
end
end

ball=class()

function ball:init(x,y)
self.a=physics.body(POLYGON,
vec2(math.random(-10,0),math.random(10)),
vec2(math.random(-10,0),math.random(-10,0)),
vec2(math.random(10),math.random(-10,0)),
vec2(math.random(10),math.random(10)))
self.a.gravityScale=0
self.a.x=x
self.a.y=y
self.a.restitution=.8
self.a.type=STATIC
end

function ball:draw()
stroke(255)
strokeWidth(2)
pushMatrix()
translate(self.a.x,self.a.y)
rotate(self.a.angle)
p=self.a.points
for z=2,#p do
line(p[z-1].x,p[z-1].y,p[z].x,p[z].y)
end
line(p[1].x,p[1].y,p[#p].x,p[#p].y)
popMatrix()
end
``````
• Posts: 160

I did it!
It took a lot of time and effort and it probably isn't the most efficient way, but I finally figured out how to make a circle split into a bunch of peices!:

``````-- Use this function to perform your initial setup
displayMode(FULLSCREEN)
function setup()
borders = physics.body(CHAIN,true,vec2(0,0),vec2(WIDTH,0),vec2(WIDTH,HEIGHT),vec2(0,HEIGHT))

bodies = {}
newBody(physics.body(CIRCLE, 100), WIDTH/2, HEIGHT/6*5, vec2(0,0))
--newBody(physics.body(POLYGON,vec2(-100,-100),vec2(0,100),vec2(100,-100)),200,HEIGHT-100)

physics.gravity(0,-700)
end

-- This function gets called once every frame
function draw()
-- This sets a dark background color
background(40, 40, 50)

-- Do your drawing here
for k,t in pairs(bodies) do
pushMatrix()
translate(t.b.x,t.b.y)
if t.b.shapeType == POLYGON then
rotate(t.b.angle)
t.m:draw()
elseif t.b.shapeType == CIRCLE then
pushStyle()
fill(0,0,255)
noStroke()
popStyle()
end
popMatrix()
end
end

function touched(t)
if t.state == ENDED then
-- First we create new bodies in the shapes of a sliced circle
slicedCircle(bodies[1].b.radius, bodies[1].b.x, bodies[1].b.y, bodies[1].b.linearVelocity * 1, 500)

bodies[1].b:destroy()
bodies[1] = nil -- Then we remove the original circle
end
end

function newBody(b, x, y, vel, ang, rotSpeed)
local velocity
if vel then
velocity = vec2(vel.x,vel.y)
else
velocity = vec2(0,0)
end

b.position = vec2(x,y)
b.linearVelocity = velocity
b.angle = ang or 0
b.angularVelocity = rotSpeed or 0
b.restitution = 0.4

local m = mesh()
if b.shapeType == POLYGON then
m.vertices = triangulate(b.points)
end
m:setColors(0,0,255)

table.insert(bodies, {b=b,m=m})
end

function slicedCircle(radius, x, y, velocity, explo, p, groups)
local p = p or 24
local groups = groups or 2
local circle = circlePoints(radius, p)

local next = 0
for i=1, math.ceil(#circle / groups) do
local points = {vec2(0,0)}
for g=1, groups+1 do
next = next + 1
if circle[next+(i-1)] then
table.insert(points,circle[next+(i-1)]*1)
elseif points[#points] ~= circle[1] then
table.insert(points,circle[1]*1)
end
end
next = next - 2
local b = physics.body(POLYGON, table.unpack(points))
local vel = vec2(math.sin(i) * explo + velocity.x, math.cos(i) * explo + velocity.y)
newBody(b, x, y, vel)
end
end

local points = {}
local fullCircle = math.pi * 2
local angleStep = fullCircle / numPoints
for i=1, numPoints do
local angle = (i-1) * angleStep
points[i] = vec2(math.sin(angle) * radius, math.cos(angle) * radius)
end
return points
end
``````

I made a function called `slicedCircle(radius, x, y, velocity, explo, p, groups)` that makes a bunch of polygon physics bodies in shapes of a sliced circle. The parameter `radius` determines the radius of the circle, `x` and `y` is for location of the sliced circle, `velocity` and `explo` are used to determine the velocity of the peices, `p` is for the amount of points you want the circle to have and `groups` is used to determine how many points (the more points, the more round) each slice has. If `groups` is not a multiple of `p`, the slice just left of the top of the circle will be a different fraction of the whole circle and this is fine in my opinion. I'm just pointing it out incase someone might want to use these functions.

Thank-you so much @dave and @yojimbo2000 for writing examples. They really helped.
And thank-you, @ignatz for the advice.