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)

タッチ ジョイントのような弾力性を必要とせず、パックをユーザーのタッチと同じ速さで動かしたい場合は、物理演算の一部を自分で行う必要があります。タッチの速度を計算して力を決定し、インパクトの方向を計算してボールを押す方向を決定する必要があります。

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 に答える