0

我想用力移动一个物体,那个特定的物体会撞到另一个物体并使它在施加的力的方向上移动,这取决于施加的力的大小,我试图计算施加的力的大小鼠标的移动量,但用户可以在不抬起鼠标拖动按钮的情况下多次点击其他对象,请提出任何想法..谢谢...

  local physics = require("physics")
physics.start()
physics.setGravity(0,0)
physics.setDrawMode("normal")


local source
local target

local function onCollision( event )
     if event.object1.name == "object1"  and event.object2.name=="object2" or event.object1.name == "object2"  and event.object2.name=="object1" then
          target:applyForce(source.x_force, source.y_force, source.x_direction, source.y_direction )
     end
 end

Runtime:addEventListener("collision",onCollision)

local function move( event )
    local t = event.target
    local phase = event.phase
    if "began" == phase then
        local parent = t.parent
        display.getCurrentStage():setFocus( t )
        t.isFocus = true
        -- Store initial position
        t.x0 = event.x - t.x
        t.y0 = event.y - t.y
    elseif t.isFocus then
        if "moved" == phase then
            t.x = event.x - t.x0
            t.y = event.y - t.y0

            source.x_direction=(t.x0-event.x)
            source.y_direction=(t.y0-event.y)
            source.x_force=t.x0
            source.y_force=t.y0

        elseif "ended" == phase or "cancelled" == phase then
            display.getCurrentStage():setFocus( nil )
            t.isFocus = false
        end
    end
     return true
end

 target = display.newCircle( 250, 250, 60 )
target.x = 200; target.y = 500
target:setFillColor(240, 200, 0)
target.name="object1"
physics.addBody(target,"dynamic",{radius = 70})

source = display.newCircle( 250, 250, 60 )
source.x = 650; source.y = 100
source:setFillColor( 240,125,0 )
source.name="object2"
physics.addBody(source,"dynamic",{radius = 70})
source:addEventListener( "touch", move)
4

1 回答 1

1

要拥有与物理交互的可拖动物体,您需要使用触摸关节。正如 krs 所提到的,您可以使用“CoronaSDK/SampleCode/Physics/MultiPuck”示例开始。触摸关节的运动确实有一点弹性,它们跟不上触摸事件。

local physics = require("physics")
physics.start()
physics.setGravity(0,0)
physics.setDrawMode("normal")

local source

function move( event )
    local body = event.target
    local phase = event.phase
    local stage = display.getCurrentStage()

    if "began" == phase then
        stage:setFocus( body, event.id )
        body.isFocus = true

        -- Create a temporary touch joint and store it in the object for later reference
        if params and params.center then
            -- drag the body from its center point
            body.tempJoint = physics.newJoint( "touch", body, body.x, body.y )
        else
            -- drag the body from the point where it was touched
            body.tempJoint = physics.newJoint( "touch", body, event.x, event.y )
        end
    elseif body.isFocus then
        if "moved" == phase then        
            -- Update the joint to track the touch
            body.tempJoint:setTarget( event.x, event.y )
        elseif "ended" == phase or "cancelled" == phase then
            stage:setFocus( body, nil )
            body.isFocus = false            
            -- Remove the joint when the touch ends         
            body.tempJoint:removeSelf()            
        end
    end

    -- Stop further propagation of touch event
    return true
end

local target = display.newCircle( 250, 250, 60 )
target.x = display.contentCenterX
target.y = display.contentCenterY
target:setFillColor(240, 200, 0)
physics.addBody(target,"dynamic",{radius = target.width / 2})


source = display.newCircle( 250, 250, 60 )
source.x = display.contentCenterX
source.y = display.contentHeight - 100
source:setFillColor( 240,125,0 )
physics.addBody(source,"dynamic",{radius = target.width / 2})


source:addEventListener( "touch", move)

如果您不想要 Touch 关节的弹性并且希望您的圆盘移动得与用户的触摸一样快,您必须自己进行一些物理操作。你需要计算触球的速度来确定力和冲击的方向来确定推球的方向。

local sqrt = math.sqrt
local physics = require("physics")
physics.start()
physics.setGravity(0,0)
physics.setDrawMode("debug")


local source
local target

-- Track velocity
local velocityTracker = {
    points = {}    
}

function velocityTracker:reset()
    self.points = {}
end

function velocityTracker:addPoint(time, x, y)   
    -- Only keep 10 points
    local count = #self.points + 1
    if count == 11 then
        count = 10
        for i=1,10 do
            -- Move older points to top
            self.points[i] = self.points[i+1]
        end 
    end
    self.points[count] = {time = time, x = x, y = y}
end

function velocityTracker:getVelocity(moves)
    if #self.points < 2 then
        return 0
    end

    local start = self.points[1]
    local totalVelocity = 0
    local now = system.getTimer()
    for i=2,#self.points do
        local finish = self.points[i]
        -- Use a vector to determine velocity
        local timePassed = finish.time - start.time
        local age = now - finish.time
        -- Only use recent points
        if age < 200 then
            local vector = {x = finish.x - start.x, y = finish.y - start.y}
            local distance = sqrt(vector.x^2 + vector.y^2)
            -- Calculate velocity
            totalVelocity = totalVelocity + (distance / timePassed)
        end
        start = finish
    end
    return totalVelocity
end

local function onPuckCollision( event )    
    if event.phase == "began" and event.other.isBall then
        -- Puck just hit a ball        
        local ball = event.other
        local puck = event.target

        -- Use a vector to determine direction of hit
        local vector = {x = ball.x - puck.x, y = ball.y - puck.y}
        -- normalize vector
        local magnitude = sqrt(vector.x^2 + vector.y^2)
        if magnitude > 0 then
            vector.x = vector.x / magnitude
            vector.y = vector.y / magnitude
        end        

        -- Use velocity to determine force
        local force = 10 * velocityTracker:getVelocity()

        local function smack()
            ball:applyForce(vector.x * force, vector.y * force, ball.x, ball.y)
        end

        -- We can't modify phyiscs in a collision handler so we
        -- `performWithDelay` to cause it to execute after this function
        timer.performWithDelay(0, smack)
    end
end

local function movePuck( event )
    local t = event.target
    local phase = event.phase
    if "began" == phase then
        local parent = t.parent
        display.getCurrentStage():setFocus( t )
        t.isFocus = true
        -- Store initial position
        t.x0 = event.x - t.x
        t.y0 = event.y - t.y
        -- Save velocity tracking state
        velocityTracker:reset()
        velocityTracker:addPoint(event.time, event.x, event.y)
    elseif t.isFocus then
        if "moved" == phase then
            t.x = event.x - t.x0
            t.y = event.y - t.y0

            -- Track a movement
            velocityTracker:addPoint(event.time, event.x, event.y)
        elseif "ended" == phase or "cancelled" == phase then
            display.getCurrentStage():setFocus( nil )
            t.isFocus = false
            velocityTracker:reset()
        end
    end
    return true
end


target = display.newCircle( 250, 250, 60 )
target.x = display.contentCenterX
target.y = display.contentCenterY
target:setFillColor(240, 200, 0)
target.isBall = true
-- Don't allow sleeping because a moving static body
-- won't always wake it if it's asleep
target.isSleepingAllowed = false 
physics.addBody(target,"dynamic",{radius = target.width / 2})


source = display.newCircle( 250, 250, 60 )
source.x = display.contentCenterX
source.y = display.contentHeight - 100
source:setFillColor( 240,125,0 )
source.isPuck = true
-- Use static body if you're going to move the object instead of
-- letting the physics engine move it
physics.addBody(source,"static", {radius = source.width / 2})

source:addEventListener("collision", onPuckCollision)

source:addEventListener("touch", movePuck)

local bounds = {
    left = -target.width,
    top = -target.height,
    right = display.contentWidth + target.width,
    bottom = display.contentHeight + target.height,
}

-- Reset ball position if it leaves screen
local function resetBall()
    if target.x < bounds.left or target.x > bounds.right or
        target.y < bounds.top or target.y > bounds.bottom
        then
        target.bodyType = 'static' -- Stop current movement
        target.x = display.contentCenterX
        target.y = display.contentCenterY                
        target.bodyType = 'dynamic' -- Make movable again

        source.x = display.contentCenterX
        source.y = display.contentHeight - 100        

        display.getCurrentStage():setFocus( nil )
    end
end

timer.performWithDelay(500, resetBall, 0)
于 2013-09-04T14:36:49.537 回答