yes, its a group where I have all the display elements joined.
I have also stripped the code to the minimum. Just drag the circle up, let it go and drag again. Then it starts to get strange.
local physics = require( "physics" ) physics.start() physics.setContinuous( false ) display.setStatusBar( display.HiddenStatusBar ) physics.setScale( 60 ) physics.setDrawMode( "hybrid" ) local height = display.contentHeight local width = display.contentWidth local allElements = display.newGroup() local texsGroup = display.newGroup() local backGround = display.newRect(0,0-height,width,2\*height) backGround:setFillColor(91,91,91) backGround:toBack() local wallBottom = display.newRect(texsGroup, 0,height-20,width,20) physics.addBody(wallBottom, "static", { density=5, friction=0.5, bounce=0.3 } ) local tex = {} local numberRips = 60 local texSize = { -- w: texwidth, h: texheight, s: strength required {w=30, h=20, s=1}, {w=20, h=10, s=1.5}, {w=10, h=10, s=2}, } local r local lim = display.newGroup() local function createRips() local originX = 0 local originY = height -75 for i=0,numberRips do r = math.random(3) local x = originX + math.random(width) local y = originY - math.random(2\*height) tex[i] = display.newRect(lim, x, y, texSize[r].w, texSize[r].h) tex[i].status = "active" tex[i].size = texSize[r].s if (r == 1) then tex[i]:setFillColor(51,255,0) elseif (r == 2) then tex[i]:setFillColor(255,51,51) elseif (r == 3) then tex[i]:setFillColor(51,51,255) end end end createRips() local w, h, r = width/2, height - 265, 12 local L = display.newCircle(w-115,h+29,r) local buttonRadius = 35 local button3 = display.newCircle((L.x),(L.y),buttonRadius) button3.myName = "L" allElements:insert(button3) allElements:insert(lim) allElements:insert(L) local krog = display.newCircle(lim,w+117,h+29,40) local d, f, b = 15, 1, 0.15 physics.addBody(L, "dynamic", { density=d, friction=f, bounce=b, radius=r } ) button3.isVisible = false button3.isHitTestable = true physics.addBody( button3, "static", { density=1, radius=buttonRadius } ) local function addFrictionJoint(a, b, posX, posY, lowerAngle, upperAngle, mT) local j = physics.newJoint ( "pivot", a, b, posX, posY, rFrom, rTo) j.isLimitEnabled = true j:setRotationLimits (lowerAngle, upperAngle) return j end -- JOINTS addFrictionJoint( button3, L, L.x, L.y, 0, 0 ) local function startDrag( event, params ) local body = event.target local phase = event.phase local stage = display.getCurrentStage() local direction = event.direction if "began" == phase then stage:setFocus( body, event.id ) body.isFocus = true event.target.bodyType = "dynamic" -- 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 --body.tempJoint.maxForce = 0.25\*body.tempJoint.maxForce -- Apply optional joint parameters if params then local maxForce, frequency, dampingRatio if params.maxForce then -- Internal default is (1000 \* mass), so set this fairly high if setting manually body.tempJoint.maxForce = params.maxForce end if params.frequency then -- This is the response speed of the elastic joint: higher numbers = less lag/bounce body.tempJoint.frequency = params.frequency end if params.dampingRatio then -- Possible values: 0 (no damping) to 1.0 (critical damping) body.tempJoint.dampingRatio = params.dampingRatio end 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() body.bodyType = "static" end end -- Stop further propagation of touch event return true end function moveCamera(e) if button3.y \< -lim.y + 300 then allElements.y = -(button3.y - 300) end end Runtime:addEventListener("enterFrame", moveCamera) button3:addEventListener( "touch", startDrag )
Just wondering… Do you want the dragged character to always stay in the centre of the screen or would it be better to have a little drift? The former is pretty easy, but the latter can be a little tricky to fine tune.
Well, you know what? I went and wrote my own version of your code off the top of my head - not using yours as a reference - just to see what I could get. This little script took an hour to build and I think I pretty much have the same result as you. I’ll keep working on this and let you know if I succeed, if you can let us know if you do too!
local physics = require( "physics" ) physics.start() physics.setGravity(0,0) physics.setDrawMode( "hybrid" ) local sWidth, sHeight = display.contentWidth, display.contentHeight local stage = display.getCurrentStage() local arena = display.newGroup() local border = display.newRect( arena, 0, 0, sWidth\*2, sHeight\*2 ) border:setFillColor(0,50,0,0) border.strokeWidth = 10 border:setStrokeColor(255,255,255) -- random fill for i=1, 10 do display.newCircle( arena, math.random(50, sWidth\*2-50), math.random( 50, sHeight\*2-50 ), math.random(1,40) ):setFillColor(0,255,0,50) end local player = display.newCircle( arena, 250, 250, 25 ) physics.addBody( player ) local touchBorder = 150 local xOffset, yOffset = 0, 0 local function calcTouchOffset( e ) local x, y = 0, 0 if (e.x \< touchBorder) then x = e.x - touchBorder elseif (e.x \> sWidth-touchBorder) then x = e.x - (sWidth-touchBorder) end if (e.y \< touchBorder) then y = e.y - touchBorder elseif (e.y \> sHeight-touchBorder) then y = e.y - (sHeight-touchBorder) end return x, y end function drag(e) if (e.phase == "began") then e.target.hasFocus = true local x, y = arena:contentToLocal( e.x, e.y ) e.target.touchjoint = physics.newJoint( "touch", e.target, x, y ) stage:setFocus( e.target ) xOffset, yOffset = 0, 0 return true elseif (e.target.hasFocus) then if (e.phase == "moved") then e.target.touchjoint:setTarget( e.x+arena.x, e.y+arena.y ) xOffset, yOffset = calcTouchOffset( e ) else e.target.hasFocus = false e.target.touchjoint:removeSelf() e.target.touchjoint = nil stage:setFocus( nil ) xOffset, yOffset = 0, 0 timer.performWithDelay( 150, function() e.target:setLinearVelocity( 0, 0 ) e.target.angularVelocity = 0 end, 1 ) end return true end xOffset, yOffset = 0, 0 return false end player:addEventListener("touch",drag) function arena:update() arena.x, arena.y = arena.x - xOffset, arena.y - yOffset if (arena.x \> 0) then arena.x = 0 elseif (arena.x \< -sWidth) then arena.x = -sWidth end if (arena.y \> 0) then arena.y = 0 elseif (arena.y \< -sHeight) then arena.y = -sHeight end end function enterFrame() arena:update() end Runtime:addEventListener("enterFrame", enterFrame)
Great, thank you very much. I’m a beginner here and this problem is way over my head. Completly stuck here.
I have also tryed to scroll just the non-physics objects, which work fine. But then the physics object won’t reat to them.
I have also tryed to move the camera with this http://developer.coronalabs.com/code/perspective#comment-142501. But got the same results.
@horacebury, I ran your code and edited just two lines (marked below), and it seems to achieve the effect you guys are going for:
[lua]
local physics = require( “physics” )
physics.start()
physics.setGravity(0,0)
physics.setDrawMode( “hybrid” )
local sWidth, sHeight = display.contentWidth, display.contentHeight
local stage = display.getCurrentStage()
local arena = display.newGroup()
local border = display.newRect( arena, 0, 0, sWidth*2, sHeight*2 )
border:setFillColor(0,50,0,0)
border.strokeWidth = 10
border:setStrokeColor(255,255,255)
– random fill
for i=1, 10 do
display.newCircle( arena, math.random(50, sWidth*2-50), math.random( 50, sHeight*2-50 ), math.random(1,40) ):setFillColor(0,255,0,50)
end
local player = display.newCircle( arena, 250, 250, 25 )
physics.addBody( player )
local touchBorder = 150
local xOffset, yOffset = 0, 0
local function calcTouchOffset( e )
local x, y = 0, 0
if (e.x < touchBorder) then
x = e.x - touchBorder
elseif (e.x > sWidth-touchBorder) then
x = e.x - (sWidth-touchBorder)
end
if (e.y < touchBorder) then
y = e.y - touchBorder
elseif (e.y > sHeight-touchBorder) then
y = e.y - (sHeight-touchBorder)
end
return x, y
end
function drag(e)
if (e.phase == “began”) then
e.target.hasFocus = true
local x, y = arena:contentToLocal( e.x, e.y )
e.target.touchjoint = physics.newJoint( “touch”, e.target, x, y )
stage:setFocus( e.target )
xOffset, yOffset = 0, 0
return true
elseif (e.target.hasFocus) then
if (e.phase == “moved”) then
local x,y = arena:contentToLocal(e.x, e.y) – This line is changed
e.target.touchjoint:setTarget( x, y ) – This line is changed
xOffset, yOffset = calcTouchOffset( e )
else
e.target.hasFocus = false
e.target.touchjoint:removeSelf()
e.target.touchjoint = nil
stage:setFocus( nil )
xOffset, yOffset = 0, 0
timer.performWithDelay( 150, function()
e.target:setLinearVelocity( 0, 0 )
e.target.angularVelocity = 0
end, 1 )
end
return true
end
xOffset, yOffset = 0, 0
return false
end
player:addEventListener(“touch”,drag)
function arena:update()
arena.x, arena.y = arena.x - xOffset, arena.y - yOffset
if (arena.x > 0) then
arena.x = 0
elseif (arena.x < -sWidth) then
arena.x = -sWidth
end
if (arena.y > 0) then
arena.y = 0
elseif (arena.y < -sHeight) then
arena.y = -sHeight
end
end
function enterFrame()
arena:update()
end
Runtime:addEventListener(“enterFrame”, enterFrame)
[/lua]
Great, its working. Thank you, aukStudios. I will try this solution in my game and will let you know. Just have some questions, since I’m a begginer at programing.
-
Why are those two changed lines so important?
-
Why you use hasFocus instead of setFocus?
-
What does contentToLocal do? As I have read the documentation, you get with this method the distance from the touch event towards to groups center. Is this true?
Great, I’m glad it’s working! As for your questions:
-
When the user moves their touch, these two lines control how the coordinates of the touch are interpreted in moving the arena and the joint connecting the touch to the player. Since that was the aspect of the original version that wasn’t working, it was a clue that maybe it was these two lines that needed to be fixed.
-
The code is actually using both. The setFocus() method tells Corona to set the focus on a particular object. However, there’s no API to ask Corona which object has the focus. So, when you set the focus on an object, the strategy is to also add a custom property to that object, hasFocus, which you can refer to later. This is a common strategy in multitouch applications, although it may not be necessary here.
-
Basically, contentToLocal converts x,y coordinates on the screen into “local” coordinates for a particular display group. Each display group has its own local coordinate system, and contentToLocal is a method that helps translate from the screen to it. For example, let’s say you had the screen coordinates 100,200. If you had a display group called group that was centered at 100,200, then group:contentToLocal(100,200) would (I think) return 0,0.
- Andrew
Super, its working also in my game now. Thank you also for answering my additional questions. It was realy kind of you…
Tomaz
This should be stickyfied
Works and solved the problem I also described in
Thnaks!
This should be stickyfied
Works and solved the problem I also described in
Thnaks!