Search code examples
luacoronasdk

corona set physics limitation


How can I make my game character's physic is limited only to 'tilt' left and right a bit? Here's how I declared my character

collector = display.newImage ("ms_throw.png")
collector.x = 10
collector.y = 10
physics.addBody(collector, {friction = 1.0, bounce = 0.6})

ms_throw.png is an image of a man standing... so basically collector will move left to right (using accelerometer) and I need the actor to only tilt a bit when he's moving.. means I don't want it to turn upside down when I tilt the phone.. How do I achieve this?


Solution

  • The trick is to tweak the coordinatey of applyForce(forcex,forcey,coordinatex,coordinatey).

    If there is significant friction, the object will tilt.
    To limit the tilt angle, use a box to cage it.

    local physics = require("physics")
    physics.start()
    physics.setGravity(0,10)
    
    centerx = display.viewableContentWidth/2+(display.contentWidth-display.viewableContentWidth)/2
    centery = display.viewableContentHeight/2+(display.contentHeight-display.viewableContentHeight)/2
    
    borderx = (display.contentWidth-display.viewableContentWidth)/2
    bordery = (display.contentHeight-display.viewableContentHeight)/2
    local w = display.viewableContentWidth/2
    local h = 100/2
    local allowanceHeight = 15
    
    local collectorLimiter = {}
    --cannot do in createScene because need to do together with physics
    local ix,iy  = centerx,bordery+display.viewableContentHeight-60
    collectorLimiter[1] = display.newRect(0,0,display.viewableContentWidth,4)
    collectorLimiter[1].x,collectorLimiter[1].y = ix,iy-h-allowanceHeight
    collectorLimiter[2] = display.newRect(0,0,display.viewableContentWidth,4)
    collectorLimiter[2].x,collectorLimiter[2].y = ix,iy+h
    collectorLimiter[3] = display.newRect(0,0,4,h*2+allowanceHeight)
    collectorLimiter[3].x,collectorLimiter[3].y = ix-w,iy
    collectorLimiter[4] = display.newRect(0,0,4,h*2+allowanceHeight)
    collectorLimiter[4].x,collectorLimiter[4].y = ix+w,iy
    
    for i = 1,#collectorLimiter do
        --collectorLimiter[i].isVisible = false
    end
    
    physics.addBody(collectorLimiter[1],"static", {friction = 0.3,bounce = 0, filter = {categoryBits = 4,maskBits = 6} })
    physics.addBody(collectorLimiter[2],"static", {friction = 0.3,bounce = 0, filter = {categoryBits = 4,maskBits = 6} })
    physics.addBody(collectorLimiter[3],"static", {friction = 0.3,bounce = 0, filter = {categoryBits = 4,maskBits = 6} })
    physics.addBody(collectorLimiter[4],"static", {friction = 0.3,bounce = 0, filter = {categoryBits = 4,maskBits = 6} })
    
    local collector = display.newRect(0,0,80,100)
    collector.x,collector.y = centerx,centery+480
    
    physics.addBody(collector, {friction = 0.3, density = 0.2, bounce = 0, filter = {categoryBits = 2}} )
    
    local function OnTouch(event)
            -- Move our collector based on the accelerator values
        if event.phase == "began" then
            collector.ix,collector.iy = event.x,event.y
        elseif event.phase == "moved" then
            if collector.ix and collector.iy then
                local dx = (event.x-collector.ix)*0.4
                collector:applyForce(dx,0,collector.x,collector.y-10)
                collector.ix,collector.iy = collector.x,collector.y
            end
        elseif event.phase == "ended" or event.phase == "cancelled" then
            collector.ix,collector.iy = nil,nil
        end
    end
    
    Runtime:addEventListener("touch",OnTouch)