Collision and Physics Bodies

Hey everyone, I am a new programmer into a high school intro to programming class and I’m trying to program a basic game that has a little guy who jumps and tries to hit stars; when he hits the stars, he scores. My major issue is that the falling stars are physics bodies and when they reach the bottom they’re supposed to go back to the top, but the velocity keeps increasing so after a bit they are too fast to even see, is there a way to reset velocity? Another issue I’m having is making the stars “disappear” by going back to the top after they have collided with the character. Right now, when the character hits a star, they both go back to the top and I don’t know how to avoid that. Any help?? Here’s my code:


-- Final

-- Use this function to perform your initial setup
function setup()
    c1=physics.body(CIRCLE, 50)
    c1.position=vec2(WIDTH/2,HEIGHT/2)
    c2=physics.body(CIRCLE,50)
    c2.x=WIDTH-math.random(WIDTH/8,WIDTH/2+140)
    c2.y=HEIGHT
    c2.speed=3
    c3=physics.body(CIRCLE,50)
    c3.x=0+math.random(0,WIDTH)
    c3.y=HEIGHT+350
    float3=physics.body(CIRCLE,50)
    float3.x=WIDTH
    float3.y=HEIGHT+700
    float4=physics.body(CIRCLE,50)
    float4.x=0
    float4.y=HEIGHT+1400
    space1=math.random(WIDTH/8,WIDTH/2+140)
    space2=math.random(WIDTH/8,WIDTH/2+140)
    space3=math.random(WIDTH/8,WIDTH/2+140)
    space4=math.random(WIDTH/8,WIDTH/2+140)
    timer=0
    gravity=8
    score=0
    
end

function draw()
    background(140, 223, 220, 93) 
    sprite("Platformer Art:Water",WIDTH/2,50,WIDTH+100,150)
    sprite("Planet Cute:Character Horn Girl",c1.x,c1.y,100,200)
    timer=timer+DeltaTime
    if timer > 0 then sprite("SpaceCute:Star", c2.x, c2.y,100) end

    if timer>1 then sprite("SpaceCute:Star",c3.x,c3.y,200) end
    
    if timer>2 then sprite("Tyrian Remastered:Evil Head",float3.x, float3.y,50) end
    
    if timer>3 then sprite("Tyrian Remastered:Evil Head",float4.x, float4.y,50) end
    
    if c2.y<2 then c2.y=HEIGHT c2.x=WIDTH-math.random(0,WIDTH+50) end
    if c3.y<2 then c3.y=HEIGHT c3.x=math.random(0,WIDTH) end
    if float3.y<2 then float3Y=HEIGHT float3.x=math.random(0,WIDTH) end
    if float4.y<2 then float4Y=HEIGHT float4.x=math.random(0,WIDTH) end
   
font("Copperplate-Bold") fontSize(100) fill(180, 0, 255, 255)
    
    text(score,WIDTH/2,HEIGHT-100)
end

function collide(c)
    if c.state==BEGAN then score=score+1 print(score) c2.y=HEIGHT end
    if c.state==BEGAN then score=score+1 print(score) c3.y=HEIGHT end
end

function touched(touch)
    if CurrentTouch.x>WIDTH/2 and CurrentTouch.y < HEIGHT then 
        c1.linearVelocity=vec2(150,75)
        else c1.linearVelocity=vec2(-150,75)
    end
end

@emcloyd When you post code, put 3 ~'s on a line before and after your code to format it correctly. I added them for you. As for the stars velocity, when you move them back to the top, you can change their speed by using linearVelocity. You’re already using it in the touched() function. Another suggestion is to not use CurrentTouch. Learn how to use the touched function properly.

@emcloyd Another suggestion is that when a star is collided, you can destroy it and recreate a new one at the top with a new location and velocity.

@dave1707 would that have to involve using a table? This is just a high school intro to programming class so we haven’t really gotten that far.

@emcloyd You could use a table if you want a lot of stars, but if you just have a few, then you can skip a table. Move your star creations into seperate functions. When a collision happens then destroy that (star) physics object and call the function to recreate it.

@dave1707, when you say separate functions, do you mean separate collision functions?

@emcloyd You just need 1 collide function, but you need to determine what collided. When a collision happens, then you need to check c.bodyA or c.bodyB and determine if c2 or c3 was in the collision with c1. If c2 or c3 was in the collision, then you could destroy c2 or c3 and then recreate it.

@dave1707 how do would I check to see which body it is? In other words, where in my collide function would I put that?

function collide(c)
if c.state==c.bodyA then score=score+1 print(score) c3.y=HEIGHT+150 end
if c.state==c.bodyB then score=score+1 print(score) c2.y=HEIGHT+150 end
end

I am fairly clueless.

@emcloyd Here’s an example of a simple collision. When the collision happens, I print some information that’s available. I print the values of c1 and c2 and you can see which one is bodyA or bodyB. There is a lot of other information you can see when a collision happens.


function setup() 
    c1 = physics.body(CIRCLE,100)    -- create body for 1st circle
    c1.type=STATIC
    c1.x=WIDTH/2
    c1.y=300
    
    c2 = physics.body(CIRCLE,50)    -- create body for 2nd circle
    c2.x=WIDTH/2
    c2.y=800
    c2.restitution=1
end

function draw()
    background(40,40,50)
    fill(255)
    ellipse(c1.x,c1.y,200,200)    -- draw the 1st circle
    ellipse(c2.x,c2.y,100,100)    -- draw the 2nd circle   
end

function collide(c)
    if c.state==BEGAN then
        print("c1",c1)
        print("c2",c2)
        print("bodyA",c.bodyA)
        print("bodyB",c.bodyB)
        print("radius of body A ",c.bodyA.radius)
        print("radius of body B ",c.bodyB.radius)
        print("x position of body A ",c.bodyA.x)
        print("y position of body A ",c.bodyA.y)
        -- see physics.contact and physics.body in the reference manual
        --    for other info that's available during a collision
        physics.pause()
    end    
end

Tables would make this a lot easier. While I do not do a programming class, at my school I am in a programming club and know what it is like to be clueless. My only coding mentors were the nice folks at the Codea forums, and I know how hard that is(even though you guys are AMAZING :smiley: ). Tables were the hardest thing for me to learn…just think of them as storing multiple values. For example, you could declare a table like this:

--create a table with 4 values in it:
table={1, 200, 300, 40}

Although tables have no use until you can call values from it. To call the 4th element from the above table, you could use:

table[4]

But if you want to iterate through an entire table, you should use for loops.

--The # operator returns the length of a string or table.
for i=0, #table do
print(table[i])
end

Then you can simplify(or complex-ify if you’re just starting out) this even further:

for i, v in pairs(table) do
print(v)
end

I know this is hard to understand now, but learning this will make your life a whole lot easier.

@TheSolderKing I really don’t have the time to figure out how to do the tables. I tried with them for a month and had no luck. Is there any way that I could make one go to the top and the other keep going? @dave1707 's advice didn’t really relate to what I was trying to accomplish

@emcloyd Here’s the fixed collide function.


function collide(c)
    if c.state==BEGAN then 
        if c.bodyA==c1 and c.bodyB==c2 or c.bodyA==c2 and c.bodyB==c1 then
            score=score+1 
            c2.y=HEIGHT 
        end
        if c.bodyA==c1 and c.bodyB==c3 or c.bodyA==c3 and c.bodyB==c1 then
            score=score+1 
            c3.y=HEIGHT 
        end
    end
end

@emcloyd tables really aren’t that complicated, but in lua they can be of you don’t stick to the basics. Here is the simplest use of an array. Also, if you are taking/have taken Algebra 2, think of an array(table) as a matrix.

function setup()
array = {}
-- declare the empty array, really simple in lua
array[1] = "hello"
array[2] = "world"
-- you can use an array just like a variable, just put what slot in the array you are saving to
print(array[1])
-- note what is saved in the first slot
print(array[2])
-- note what is saved in the second slot
print(array[1].." "..array[2])
-- and then you can use them to do as you please. In lua arrays don't have to be declared as a certain size or anything, so just think of them as a variable.
end
function draw()
background(255,255,255,255)
strokeWidth(5)
end

So if you wanted three stars, you can think of each slot in the array as a star, like this, and then reset or destroy and create new ones as they hit the ground

star = {}
-- an empty array
star[1] = vec2(math.random(100,WIDTH-100),HEIGHT)
star[2] = vec2(math.random(100,WIDTH-100),HEIGHT)
star[3] = vec2(math.random(100,WIDTH-100),HEIGHT)
-- so make coordinates for each star

Or you can declare the coordinates like this

star = {vec2(math.random(100,WIDTH-100),HEIGHT),vec2(math.random(100,WIDTH-100),HEIGHT),vec2(math.random(100,WIDTH-100),HEIGHT)}