The image object attached to event listener is nil - lua

--up in the level1.lua
local target
--in the enter frame function of scene
function target:touch(event)
if event.phase=="began" then
local target=display.newImage("target.png",event.x,event.y)
return true
end
end

function target:touch(event)
You have not created target yet. You cannot assign a touch handler to an object that doesn't exist yet.
It sounds like what you need to do is add a touch handler to the stage. I would pre-create the image and just hide it using .isVisible = true. Then in your touch handler, show and hide the object. But regardless you have to put the touch handler on the whole screen and not an individual small image.

Remove the "local" in target:touch: it hides the module local, using a variable local to target:touch(). Also, if you want image to disappear after touch done, use the "ended" and "cancelled" phases of touch event. Finally, I'm assuming that you initialized target to something but if not, you must add that too, otherwise how can you define touch:event (thanks to Rob for noticing this btw):
-- first create the target, but don't show it:
local target = display.newImage("target.png", 0, 0)
target.isVisible = false
--in the enter frame function of scene
function target:touch(event)
if event.phase=="began" then
target.x = event.x
target.y = event.y
return true
else if event.phase == "ended" or event.phase == "cancelled" then
if target ~= nil then
target:removeSelf()
target = nil
end
return true
end
end

Related

How to draw circles of variable sizes on touch using Lua

Circles of variable sizes will be drawn on blank.png (800 X 800) on touch and in run time. On touch, the coordinates (the positions of x-axis and y-axis coordinates in runtime on touch) will be stored in two variables myCoordx and myCoordy in began event. When a user moves his/her fingers on screen, circle will be drawn based on calculated radius and coordinates. Now the error keeps on appearing. Please help me to debug this code.
Runtime error
d:\corona projects\enterframeevent\main.lua:14: attempt to index global 'drawCircle' (a nil value)
stack traceback:
d:\corona projects\enterframeevent\main.lua:14: in main chunk
This is my main.lua file.
local screen = display.newImage( "blank.png")
function drawCircle:touch(event)
if event.phase == "began" then
local myCoordx = event.x
local myCoordy = event.y
elseif event.phase == "moved" then
local rad = (event.x - myCoordx) ^ 2
local myCircle = display.newCircle(event.x, event.y, rad )
myCircle:setFillColor( 1, 0, 1 )
end
end
Runtime:addEventListener( "touch", drawCircle )
Apparently you try to add :touch method to drawCircle, but you don't define it anywhere. You should init it to something at very least an empty table - i.e. {} or use relevant Corona method to create it.
As per my comment, the code posted can't write, or the error message is wrong. I'll assume the error is wrong, because the statement function drawCircle:touch(event) on line 3 attempts to add a method called touch(self) to a drawCircle table; yet the code does not create this table anywhere. You are either missing drawCircle = display.newSomething..., OR you could simply use a function not a method:
function touch(event)
...
end
Runtime:addEventListener( "touch", touch)
The latter works only because your touch function doesn't use the keyword self, which is an implicitly created variable for methods.
I think you could go with something like this:
-- I think you should define these outside the function
-- since they'll be out of scope in the "moved" phase
local myCoordx = 0
local myCoordy = 0
-- Moved this declaration outside the function
-- so it can be reused, and removed
local myCircle
function onTouch(event)
if event.phase == "began" then
myCoordx = event.x
myCoordy = event.y
elseif event.phase == "moved" then
local rad = (event.x - myCoordx) ^ 2
-- Keep in mind that this line will draw a new circle everytime you fall into the "moved" phase, keeping the old one
-- if i understood well, this is not what you want
-- local myCircle = display.newCircle(event.x, event.y, rad )
-- Try this instead, removing the old display object...
if myCircle then
myCircle:removeSelf()
myCircle = nil
end
-- ...and adding it again
myCircle = display.newCircle(event.x, event.y, rad )
myCircle:setFillColor( 1, 0, 1 )
end
end
-- Since "drawCircle" is not defined, point it directly to a function (in this case, "onTouch")
-- Runtime:addEventListener( "touch", drawCircle )
Runtime:addEventListener( "touch", onTouch )
Didn't have the chance to test the code on Simulator, i'll try it later and update the answer if needed.
UPDATE:
Tested it, and it works as i expected.

How to call removeBody function of physics dynamically on a touch event in corona

I want to call removeBody function when i click on an object. As soon as i click
the object the removeBody function must be called on an object and after i release the
mouse then it must again behave like a physics object. These are the code that i
was trying. please give any suggestion
local function removephysics(objId)
physics.removeBody(objId)
end
local Bodyobject={density=3.0, friction=0.2, bounce=0.3, radius=20}
object1=display.newImage("img1.png")
object1.x=325
object1.y=200
object1.id="obj"
physics.addBody(object1,Bodyobject)
object1.addEventListener("touch",removephysics)
you can use event.phase to get the state of touch listener see this code
physics = require("physics")
physics.start()
local Bodyobject={density=3.0, friction=0.2, bounce=0.3, radius=20}
function removephysics(event)
if event.phase == "began" then
physics.removeBody(object1)
elseif event.phase == "ended" then
physics.addBody(object1,Bodyobject)
end
end
object1=display.newImage("img1.png")
object1.x=325
object1.y=200
object1.id="obj"
physics.addBody(object1,Bodyobject)
object1:addEventListener("touch",removephysics)

Touch Hold Event In corona SDK

I was wondering how I would check if the user has touched the screen, but is holding their touch down and is not moving. Please help if you have anything I can go from. Ive been looking around and have yet to find anything to handle this.
You can use/modify this: (It's what Rob Miracle says)
local holding = false
local function enterFrameListener()
if holding then
-- Holding button
-- Code here
-- Code here
-- Code here
else
-- Not holding
-- Code here
-- Code here
-- Code here
end
end
local 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
I believe its obvious what touchHandler function is ^^
You will need a touch listener added to either an object covering your whole screen or you can add it to the system's RunTime.
See this guide: http://docs.coronalabs.com/guide/events/detectEvents/index.html#hit
Now, there are three "Phases" for these touch events. You get one when the press starts ("began"), one if the person moves their finger ("moved") and when they stop touching, there is an "ended" phase.
Depending on what you are trying to do, if you are say moving something while holding the button down, then you can set a flag like:
if event.phase == "began" then
pressed = true
elseif event.phase == "ended" then
pressed = false
end
Then where ever you're moving you can check to see "if pressed then move".

dragging of loqSprite object in corona

i am new to using loqSprite, i am trying to drag a loqSprite sprite object but its not getting done , however it calls its listener only once and then after neither its touch listner is getting called nor even it gives any error, the sprite is playing. Also i thought that might my drag/listener function might be buggy but when i tried the same dragging (movePen() function ) on the inbult corona's Sprite object it works fine. what i am missing i dont know . Can anyone please help me .... below is the code snippet. thanks
local function movePen(event)
local targetObj= event.target;
if event.phase == 'began' then
display.getCurrentStage():setFocus(targetObj);
targetObj.isFocus = true;
targetObj.y = event.y;
elseif event.phase == 'moved' then
targetObj.x = event.x;
targetObj.y = event.y;
elseif event.phase == 'ended' then
display.getCurrentStage():setFocus(nil);
targetObj.isFocus = false;
end
return true;
end --end of touch/move function
local spriteFactoryForPen = loqsprite.newFactory('penAnimation')
local penSpriteAnim = spriteFactoryForPen:newSpriteGroup('pen_write')
penSpriteAnim.x = 100
penSpriteAnim.y = 200
local function spriteEvent (e) --listener to play in loop
if(e.phase == "end") then
penSpriteAnim:play()
end
end -- end of sprit event function
penSpriteAnim:addEventListener("touch", movePen); -- adding listener to move pen object
penSpriteAnim:addEventListener("sprite", spriteEvent) -- adding listener to play in loop
penSpriteAnim:play('pen_write') -- playing pen Sprite
First of all there is no need to call penSpriteAnim:play() in loop. Because it will automatically play in loop untill you don't call the penSpriteAnim:pause() function.
For your touch listener, You should declare all the local variable on top of the page.
I am not sure about this, but hope this will work. Because lua is compiling top to bottom.

Corona SDK - change a variable for the duration of a drag event

I have a "seed" object which has an instance method seed:fall() which is called by my update function (which runs every frame). I've got a "touch" event listener on it so the user can drag it around. When it's being dragged, however, it's still trying to fall, which makes the drag interaction glitchy.
I've added an instance variable to my seed "class" called seed.falling. The fall() function now checks that seed.falling is true before moving the seed down the screen. The next step is to set seed.falling to false when the drag starts, and then set it back to true when the drag stops. I can't figure out this last part though.
Any ideas anyone? Is there a "stop dragging" event i could set a listener for, to switch seed.falling back on? Is there a nicer way of achieving what i want?
physics.start()
physics.setGravity(0,1)
local dd = display.newRect(400,100,200,200)
physics.addBody(dd,"dynamic")
dd:addEventListener("touch", function(event)
if event.phase == "began" then
dd.bodyType = "static"
elseif event.phase == "moved" then
dd.x,dd.y = event.x,event.y
elseif event.phase == "ended" then
dd.bodyType = "dynamic"
end
end)
I think this case is what you want?
Just for the record, here's how i solved this.
Basically i have an attribute "seed.falling" which the seed:fall method checks before moving the seed. And i set that attribute to false if we're not at the "ended" phase of the drag event, which stops the seed falling.
function Seed:new(x,y)
print("Seed:new, x = " .. (x or nil) .. ", y = " .. (y or nil) )
local seed = display.newImage("seed_icon.png")
seed.x = x
seed.y = y
seed.name = 'seed'
seed.falling = true
function seed:fall()
if(self.falling) then
self.y = self.y + 1
end
end
function seed:drag(event)
seed.x = event.x
seed.y = event.y
if(event.phase == "ended") then
seed.falling = true
else
seed.falling = false
end
end
seed:addEventListener("touch", drag)
return seed
end
function drag(event)
seed = event.target
seed:drag(event)
end
It's not a very good solution i think as it leaves the seed stranded on the screen sometimes - possibly when you drag a seed over another falling seed.

Resources