Scrolling and dragging in Corona --> BUG? - scroll

I have a event listener assigned to an object. This then triggers the startDrag function. I'm moving my character in the game with dragging. But as soon as I scroll or move the display, my dragging function gets all messed up. It doesn't react as it should and the object(event.target) can't be controlled at all.
Did anyone else had this experience?
Is this a corona bug?
How can I solve this?
Can I temporarily disable the startDrag event listener for the time of scrolling? Or maybe restart it?
All help would be greatly appreciated.
Here is the code...
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 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 )

When you scroll the screen the touch event and the physics object are in different coordinate systems. See localToContent/globalToContent

Related

Index error occurs when trying to use an event listener

I am trying to add a touch event listener to the image object being loaded. Although this is practically an exact copy and paste from the documentation:
https://docs.coronalabs.com/api/type/EventDispatcher/addEventListener.html
It returns the following error:
36: attempt to index local 'object' (a nil value)
local t = {}
local img = {}
local i = 1
local function showImages ()
local function networkListenerImg( event )
if ( event.isError ) then
print ( "Network error - download failed" )
else
event.target.alpha = 0
transition.to( event.target, { alpha = 1.0 } )
end
end
for k,v in pairs(t) do
img[#img + 1] = v
end
local object = display.loadRemoteImage( event.params.chapter .. img[i], "GET", networkListenerImg, img[i], system.TemporaryDirectory, 50, 50 )
function object:touch( event )
if event.phase == "began" then
print( "You touched the object!" )
return true
end
end
object:addEventListener( "touch", object )
end
The table, t, is populated elsewhere in the code and is populated properly.
While you didn't mention which of those lines is line 36 (there are only 28 lines there), I can still see your error. The issue is that object is and always will be nil: display.loadRemoteImage() does not return anything, see this.
What you need to do is have your listener callback capture object, which must be declared before the callback is. The callback should then set the value of object to the results of the download. Like so...
local t = {}
local img = {}
local i = 1
local function showImages ()
local object
local function networkListenerImg( event )
if ( event.isError ) then
print ( "Network error - download failed" )
else
event.target.alpha = 0
transition.to( event.target, { alpha = 1.0 } )
-- fill in code to save the download object into "object"
end
end
for k,v in pairs(t) do
img[#img + 1] = v
end
display.loadRemoteImage( event.params.chapter .. img[i], "GET", networkListenerImg, img[i], system.TemporaryDirectory, 50, 50 )
function object:touch( event )
if event.phase == "began" then
print( "You touched the object!" )
return true
end
end
object:addEventListener( "touch", object )
end

I cannot animating the sprite, what am I doing wrong?

Anyone can help me. I create some sprite images for a jump animate. But it cannot animated as I want, it only showing the first frame ( I set it for 7 jump frame). Here is my corona code.
function playerJump( event )
if event.phase == "ended" then
if doubleJump == false then
player:setLinearVelocity( 0, 0 )
player:applyForce(0,-30, player.x, player.y)
player:setSequence("jump")
jumpChannel = audio.play(jumpSound)
end
if singleJump == false then singleJump = true
else doubleJump = true end
end
return true
end
Then below that function, I generate the sprite
local options =
{
width = 60, height = 100,
numFrames = 33,
sheetContentWidth = 1980,
sheetContentHeight = 100
}
playerSheet = graphics.newImageSheet( "images/playerSprite.png", options)
playerSprite = {
{name="run", frames = {1,3,5,7,9,11,13,15,17,19,21,23,25}, time = 700, loopCount = 0 },
{name="jump", frames = {27,28,29,30,31,32,33}, time = 1000, loopCount = 1 },
}
--Add the jump listener
Runtime:addEventListener("touch", playerJump)
Thankyou very much
Regards
function playerJump( event )
if event.phase == "ended" then
if doubleJump == false then
player:setLinearVelocity( 0, 0 )
player:applyForce(0,-30, player.x, player.y)
player:setSequence("jump")
player:play() --- You have forgot to add this line.
jumpChannel = audio.play(jumpSound)
end
if singleJump == false then singleJump = true
else doubleJump = true end
end
return true
end

handle events in corona lua

Iam new to corona, so I dont know how to organize my code to best. I am trying to regiser click when user click on leftHam image, but I dont how to do it most efficently. Right now I am getting leftHam is nil although on creation it should be assinged a value.
local composer = require( "composer" )
local widget = require( "widget" )
local scene = composer.newScene()
local _H = display.contentHeight
local _W = display.contentWidth
leftNavBtn = nil
local navbarGroup
function scene:create( event )
local sceneGroup = self.view
local background = display.newImage("res/bg.png" )
background:scale( _W, _H )
background.x = _W
background.y = _H
local navbarGroup = display.newContainer(_W, _H/4)
navbarGroup.x = _W /2
--navbarGroup.y = 0
local top_bar = display.newImage("res/home/top_bar.png")
top_bar.y = top_bar.height/2
navbarGroup:insert(top_bar)
--local leftNavBtn = display.newImageRect("res/home/hamburger.png", 100, 100)
leftNavBtn.y = leftNavBtn.height/1.5
leftNavBtn.x = - navbarGroup.width/2 + leftNavBtn.width
leftNavBtn = display.newImageRect("res/home/hamburger.png", 100, 100)
leftNavBtn.y = leftNavBtn.height/1.5
leftNavBtn.x = - navbarGroup.width/2 + leftNavBtn.width
navbarGroup:insert(leftNavBtn)
local rightNavBtn = display.newImageRect("res/home/hamburger.png", 100, 100)
rightNavBtn.y = leftNavBtn.height/1.5
rightNavBtn.x = navbarGroup.width/2 - leftNavBtn.width
navbarGroup:insert(rightNavBtn)
end
function test()
print("clickedddddddddddd")
end
function leftNavBtn:touch(event)
if event.phase == "began" then
display.getCurrentStage( ):setFocus(self)
self.isFocus = true
elseif self.isFocus then
if event.phase == "moved" then
print("moved")
elseif event.phase == "ended" or event.phase == "cancelled" then
display.getCurrentStage( ):setFocus(nil)
self.isFocus = false
end
end
return true
end
leftNavBtn:addEventListener( "touch", test )
scene:addEventListener( "create", scene )
return scene
Do you mean leftNavBtn because leftHam doesn't exist anywhere.
You are creating leftNavBtn in scene:create but are attempting to use it before calling that function anywhere (the leftNavBtn:addEventListener( "touch", test )) line.
Within scene:create you also use leftNavBtn before creating it because you commented out this line local leftNavBtn = display.newImageRect("res/home/hamburger.png", 100, 100) without commenting out the two lines after it (which set of three lines you then duplicate immediately after that).

Making an object return to start point in corona

So I have a function which runs if someone is holding a button (an object moves). But I also have this collision between that object and another static one, when the first object hits the second one, it gets sent back to the start point. But the problem is that when I keep holding the button to move the object. It doesn't send it back to start when it collides. It just messes up.
This is the code I have for the hold button function:
local holding = false
function enterFrameListener()
if holding then
transition.to( cube, {time = 0, x= cube.x - 5} )
end
end
function touchHandler( event )
if event.phase == "began" then
display.getCurrentStage():setFocus( event.target )
event.target.isFocus = true
Runtime:addEventListener( "enterFrame", enterFrameListener )
holding = true
elseif event.target.isFocus then
if event.phase == "moved" then
elseif event.phase == "ended" then
holding = false
Runtime:removeEventListener( "enterFrame", enterFrameListener )
display.getCurrentStage():setFocus( nil )
event.target.isFocus = false
end
end
return true
end
leftbutton:addEventListener( "touch", touchHandler )
This is the code I have for the collision:
function onCollision( event )
if ( event.phase == "began" ) then
transition.cancel( )
transition.moveTo( cube, {time = 0, x = 35, y = 100} )
end
end
redblock:addEventListener( "collision", onCollision )
Try to insert a return true at the end of the onCollision(event) function as below:
function onCollision( event )
if ( event.phase == "began" ) then
transition.cancel( )
transition.moveTo( cube, {time = 0, x = 35, y = 100} )
end
return true
end
Make object as bullet.
There is a property in corona.
isBullet=true
will make your physics object as bullet so it'll check collision for several times in a second.
Then this event can thrown, otherwise it'll not raise that event.

Dynamic image creation with touch action in corona

I have touch problem with dynamic image creation. my code is
local widget = require "widget"
--Hide status bar
display.setStatusBar( display.HiddenStatusBar )
--bg image
local backgroundPortrait = display.newImage( "background.png", 0, 0 )
--local image1Group
--image1Group = display.newGroup()
--3 frames
local frame1 = display.newImageRect( "icon_1.png", 75, 75 )
frame1:setReferencePoint( display.CenterReferencePoint )
frame1.x = 160
frame1.y = 120
local frame2 = display.newImageRect( "icon_2.png", 75, 75 )
frame2:setReferencePoint( display.CenterReferencePoint )
frame2.x = 60
frame2.y = 360
local frame3 = display.newImageRect( "icon_3.png", 75, 75 )
frame3:setReferencePoint( display.CenterReferencePoint )
frame3.x = 260
frame3.y = 360
-- Center image
function createImage()
centerFrame = display.newImageRect( "additionalvampire1.jpg", 75, 75 )
centerFrame:setReferencePoint( display.CenterReferencePoint )
centerFrame.x = display.contentCenterX
centerFrame.y = display.contentCenterY
centerFrame:addEventListener("touch", centerFrame)
end
createImage()
function removeTouchEventFun()
centerFrame:removeEventListener("touch", centerFrame)
end
function transitionCompleted(centerFrame)
print("transitionCompleted called")
removeTouchEventFun()
centerFrame:removeSelf()
centerFrame=nil
createImage()
end
function centerFrame:touch(event)
if event.phase == "began" then
self.markX = self.x -- store x location of object
self.markY = self.y -- store y location of object
elseif event.phase == "moved" then
local x = (event.x - event.xStart) + self.markX
local y = (event.y - event.yStart) + self.markY
self.x, self.y = x, y -- move object based on calculations above
elseif event.phase == "ended" then
if (centerFrame.x<=160 and centerFrame.y>=240) then
transition.to( centerFrame, { time=1000, alpha=1, x=60, y=360, width=1 ,height=1, onComplete= transitionCompleted } )
elseif (centerFrame.x>=160 and centerFrame.y>=240) then
transition.to( centerFrame, { time=1000, alpha=1, x=260, y=360, width=1 ,height=1, onComplete= transitionCompleted } )
else
transition.to( centerFrame, { time=1000, alpha=1, x=160, y=120, width=1 ,height=1, onComplete= transitionCompleted } )
end
end
return true
end
when drag the image to any one frame it is zoom-out and remove the object and create the another image. for this image touch not working...
i need image creation with touch action when the image transition compete method. what should i do?...
local centerFrame
function transitionCompleted(centerFrame)
print("transitionCompleted called")
if(centerFrame) then
centerFrame:removeSelf()
centerFrame=nil
createImage()
end
end
function onCenterFrameTouch(event)
//your code here
end
function createImage()
centerFrame = display.newImageRect( "additionalvampire1.jpg", 75, 75 )
centerFrame:setReferencePoint( display.CenterReferencePoint )
centerFrame.x = display.contentCenterX
centerFrame.y = display.contentCenterY
centerFrame:addEventListener("touch", onCenterFrameTouch)
end

Resources