Howdy, Stranger!

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

Collision not being detected properly (physics.body and POLYGON)

edited November 2015 in Questions Posts: 8

I'm starting a game where balls bounce across the screen, and you have to dodge them. Right now, I am unable to detect a collision against the user-controlled square and the circle. I believe it has to do with my physics.body syntax, specifically with the square (POLYGON). Any pointers?

--dodgeball

displayMode(FULLSCREEN)
supportedOrientations(LANDSCAPE_ANY)

function setup()
    w1=physics.body(EDGE,vec2(0,HEIGHT/4),vec2(WIDTH,HEIGHT/4))
    w2=physics.body(EDGE,vec2(WIDTH,0),vec2(WIDTH,HEIGHT))
    b=physics.body(CIRCLE,40)
    b.x=WIDTH
    b.y=HEIGHT/2
    b.restitution=1
    b.friction=0
    b.linearVelocity=vec2(-(math.random(100,400)),30)
    p=40
    circnum=0
    tx=20
    ty=HEIGHT/4
    player=physics.body(POLYGON,
                        vec2(tx, ty),
                        vec2(tx, ty+30),
                        vec2(tx+30, ty),
                        vec2(tx+30, ty+30)
                        )
    player.info="c1"
    b.info="c2"
end

function draw()
    circnum = circnum +.1
    if math.floor(circnum) == 10 then
        --[[
        b.x=WIDTH
        b.y=HEIGHT/2
        circnum = 0
        ellipse(b.x,b.y,math.random(10,150))
        p=math.random(30,60)
        --]]
    end
    stroke(255, 255, 255, 255)
    strokeWidth(3)
    background(40, 40, 50)
    line( 0, HEIGHT/4, WIDTH, HEIGHT/4)
    fill(255)
    ellipse(b.x,b.y,p)
    rect(tx,ty,30)
    if o==true then
    text("collision",WIDTH/2,HEIGHT/1.5)
    end
    fontSize(25)
    fill(255, 255, 255, 255)
end

function touched(t)
    if t.state == BEGAN or t.state == MOVING then
        tx=CurrentTouch.x
    end
end

function collide(c)
    if c.state==BEGAN then
        if c.bodyA.info=="c1" and c.bodyB.info=="c2" or c.bodyA.info=="c2" and c.bodyB.info=="c1" then
        o=true
        print("collision")
        end
    end
    if c.state==ENDED then
        if c.bodyA.info=="c1" and c.bodyB.info=="c2" or c.bodyA.info=="c2" and c.bodyB.info=="c1" then
            o=false
            print("collision ended")
        end
    end
end

Comments

  • Posts: 2,020

    I'm away from my iPad so I can't run your code, but I think I can see the issues.

    Firstly, you haven't assigned a position to the player, like you have with the object b, with b.x =, b.y = etc. It looks as if you want tx, ty to be the player's position. Instead of defining the points of the shape in absolute space, define them around 0,0, eg vec2(-15,-15), vec2(-15,15), vec2(15,15), vec2(15,-15), and then set player.x, player.y = tx, ty

    Secondly, you're not drawing the player. You would need to have some kind of drawing operation that is reading player.x, .y or .position. I see that you're drawing a rect at tx, ty, which are the variables you used to define the player's points, but they won't automatically update to reflect the new position set by the physics engine unless you tell them to. So you could draw the rect at player.x, player.y, or update tx,ty to equal player coords.

  • IgnatzIgnatz Mod
    Posts: 5,396

    From the Box2D docs (Codea uses Box2D)

    Game simulation usually generates a sequence of images that are played at some frame rate. This is called discrete simulation. In discrete simulation, rigid bodies can move by a large amount in one time step. If a physics engine doesn't account for the large motion, you may see some objects incorrectly pass through each other. This effect is called tunneling.

    By default, Box2D uses continuous collision detection (CCD) to prevent dynamic bodies from tunneling through static bodies. This is done by sweeping shapes from their old position to their new positions. The engine looks for new collisions during the sweep and computes the time of impact (TOI) for these collisions. Bodies are moved to their first TOI and then halted for the remainder of the time step.

    Normally CCD is not used between dynamic bodies. This is done to keep performance reasonable. In some game scenarios you need dynamic bodies to use CCD. For example, you may want to shoot a high speed bullet at a stack of dynamic bricks. Without CCD, the bullet might tunnel through the bricks.

    Fast moving objects in Box2D can be labeled as bullets. Bullets will perform CCD with both static and dynamic bodies. You should decide what bodies should be bullets based on your game design. If you decide a body should be treated as a bullet, use the following setting.

    YourBodyName.bullet = true
    

    You can also try

    physics.continuous=true
    

    Which applies to all physics objects

  • Posts: 2,020

    Also, assuming you want touch to move the player, you shouldn't move a dynamic physics body by setting its position directly (can especially interfere with collisions). You can either make it kinematic, or, if you want it to remain dynamic, move it by applying forces.

    Also, don't use currentTouch inside a touched function, just use the t variable.

    eg, if using a force player:applyForce(vec2(t.deltaX * speed, 0))

    where speed is a variable that you can experiment with depending on the mass/ friction of the player, how much you want it to fly around etc.

  • dave1707dave1707 Mod
    Posts: 8,622

    @McCann Here's a version. Slide your finger right or left to move the square. I don't know everything you want to do, so this doesn't do much except demo the movement and collision.

    supportedOrientations(LANDSCAPE_ANY)
    
    function setup()
        rectMode(CENTER)
        dx=0
        w1=physics.body(EDGE,vec2(0,200),vec2(WIDTH,200))
        w2=physics.body(EDGE,vec2(0,0),vec2(0,HEIGHT))
        w3=physics.body(EDGE,vec2(WIDTH,0),vec2(WIDTH,HEIGHT))
    
        b1=physics.body(CIRCLE,20)
        b1.x=WIDTH
        b1.y=400
        b1.linearVelocity=vec2(-100,50)
        b1.restitution=1  
        b1.info="b1"  
    
        p1=physics.body(POLYGON,vec2(-10,10),vec2(-10,-10),vec2(10,-10),vec2(10,10))
        p1.x=50
        p1.y=250
        p1.info="p1"
    end
    
    function draw()
        background(40, 40, 50)
        stroke(255)
        strokeWidth(2)
        line(0,200,WIDTH,200)
        ellipse(b1.x,b1.y,40)
        rect(p1.x,p1.y,20,20)
        if math.abs(p1.linearVelocity.x)<1 then
            dx=0
        end
    end
    
    function touched(t)
        if t.state==MOVING then
            dx=dx+t.deltaX
            p1.linearVelocity=vec2(dx,0)
        end
    end
    
    function collide(c)
        if c.state==BEGAN then
            if c.bodyA.info=="b1" and c.bodyB.info=="p1" or 
                    c.bodyA.info=="p1" and c.bodyB.info=="b1" then
                print("collide")
            end
        end    
    end
    
Sign In or Register to comment.