Quick Links: Download Gideros Studio | Gideros Documentation | Gideros community chat | DONATE
Event.TOUCHES_END fired twice when there are two instances of a class — Gideros Forum

Event.TOUCHES_END fired twice when there are two instances of a class

CesarCesar Member
edited April 2016 in General questions
Here is my code:

*******************************************************
File: main.lua:
HoldButton = Core.class(Sprite)
function HoldButton:init(id, posx, posy)
	self.id=id
	self:setPosition(posx, posy)
 
	self.shape = Shape.new()
	self.shape:beginPath()
	self.shape:setFillStyle(Shape.SOLID, 0xff0000)
	self.shape:setLineStyle(1, 0x000000)
	self.shape:moveTo(0,0)
	self.shape:lineTo(0,50)
	self.shape:lineTo(50,50)
	self.shape:lineTo(50,0)
	self.shape:lineTo(0,0) 
	self.shape:endPath() 
 
	self:addChild(self.shape)
 
	self:addEventListener(Event.TOUCHES_BEGIN, self.beginTouch, self)
	self:addEventListener(Event.TOUCHES_END, self.endTouch, self)
end
 
function HoldButton:beginTouch(event)	
	if self:hitTestPoint(event.touch.x, event.touch.y) then		
		print("beginTouch: "..self.id)
	end
end	
 
function HoldButton:endTouch(event)
	print("endTouch: "..self.id)
end
 
 
a = HoldButton.new("First Instance", 100, 100)	
	stage:addChild(a)
b = HoldButton.new("Second Instance", 200, 200)	
	stage:addChild(b)
******************************************************

When I touch the button a, it prints:

beginTouch: First Instance
endTouch: Second Instance
endTouch: First Instance

I have no problems to isolate beginTouch for the first Instance with hitTestPoint; however, the hitTestPoint method doesn't work with TOUCHES_END in case I move my finger out of the first instance HoldButton limits (for example, move the finger to position 100,200).

I would like to isolate the endTouch for each instance, including when on touch moving. Any suggestions?

Thank you in advance.

Comments

  • piepie Member
    edited April 2016
    @Cesar place a "unique id" property into each instance and send it to your function handler
    just to clarify things: :)
    Button = Core.class(Sprite)
     
    function Button:init(id)
    self.id = id
     
    local shape = TextField.new(nil, self.id)
    self:addChild(shape)
     
    local function sendEvent()
    	local sentEvent = Event.new("touchend")
    	sentEvent.id = self.id
    	self:dispatchEvent(sentEvent)
    end
     
    self:addEventListener(Event.TOUCHES_END, function(event)
     
    	if  self:hitTestPoint(event.touch.x, event.touch.y) then
    		sendEvent()
    	end
    end)
     
    end
     
    local bt = {}
     
    for i = 1, 20 do
    	bt[i] = Button.new(i)
    	stage:addChild(bt[i])
    	bt[i]:setPosition(5, 10*i)
    	bt[i]:addEventListener("touchend", function(event)
    	print("touch end on instance#", event.id)
    	end)
     
    end

    [edit: your update happened while I was posting, I cant elaborate it right now I hope that you can understand how to tweak it from my example.

    If you just need it to happen on instance 1 just avoid placing the listener in the other instances: it's faster to edit my own example right now :P
    Button = Core.class(Sprite)
     
    function Button:init(id)
    self.id = id
     
    local shape = TextField.new(nil, self.id)
    self:addChild(shape)
     
    local function sendEvent()
    	local sentEvent = Event.new("touchend")
    	sentEvent.id = self.id
    	self:dispatchEvent(sentEvent)
    end
     
    	if self.id == 1 then --place listener only on instance 1
    		self:addEventListener(Event.TOUCHES_END, function(event)
     
    			if  self:hitTestPoint(event.touch.x, event.touch.y) then
    				sendEvent()
    			end
    		end)
    	end
    end
     
    local bt = {}
     
    for i = 1, 20 do
    	bt[i] = Button.new(i)
    	stage:addChild(bt[i])
    	bt[i]:setPosition(5, 10*i)
    	bt[i]:addEventListener("touchend", function(event)
    	print("touch end on instance#", event.id)
    	end)
     
    end
    P.S. use the C button at the top of the forum editor to display your code ;)
    ]




  • CesarCesar Member
    No, I would like it to happen in all instances. They are different buttons which fire different event on TOUCHES_END

    Thanks for your quick answer.
  • piepie Member
    Accepted Answer
    @Cesar this is the first way I thought, I suppose that there are many others:
    use variable lastTouchOn to store last touched button with event TOUCHES_MOVE
    local lastTouchOn 
     
    HoldButton = Core.class(Sprite)
    function HoldButton:init(id, posx, posy)
    	self.id=id
    	self:setPosition(posx, posy)
     
    	self.shape = Shape.new()
    	self.shape:beginPath()
    	self.shape:setFillStyle(Shape.SOLID, 0xff0000)
    	self.shape:setLineStyle(1, 0x000000)
    	self.shape:moveTo(0,0)
    	self.shape:lineTo(0,50)
    	self.shape:lineTo(50,50)
    	self.shape:lineTo(50,0)
    	self.shape:lineTo(0,0) 
    	self.shape:endPath() 
     
    	self:addChild(self.shape)
     
    	self:addEventListener(Event.TOUCHES_BEGIN, self.beginTouch, self)
    	self:addEventListener(Event.TOUCHES_END, self.endTouch, self)
    	self:addEventListener(Event.TOUCHES_MOVE, self.selectTouch, self)
    end
     
    function HoldButton:selectTouch(event)
    	if self:hitTestPoint(event.touch.x, event.touch.y) then		
    		--print("lastTouch: "..self.id)
    		lastTouchOn = self.id
    	end
    end
     
    function HoldButton:beginTouch(event)	
    	if self:hitTestPoint(event.touch.x, event.touch.y) then		
    		print("beginTouch: "..self.id)
    	end
    end	
     
    function HoldButton:endTouch(event)
    	if lastTouchOn == self.id then
    		print("endTouch: "..lastTouchOn)
    	end
    end
     
     
    a = HoldButton.new("First Instance", 100, 100)	
    	stage:addChild(a)
    b = HoldButton.new("Second Instance", 200, 200)	
    	stage:addChild(b)
  • NatWobbleNatWobble Member
    edited April 2016
    @Cesar

    A simple way to do this is:
     
    function HoldButton:beginTouch(event)	
    	if self:hitTestPoint(event.touch.x, event.touch.y) then		
    	  self.isFocus=true
              -->>self:doSomething()
    	end
    end	
     
    function HoldButton:endTouch(event)
            if self.isFocus then
    	   self.isFocus = false
               -->>self:doSomething()
            end
    end

    Likes: Cesar

    +1 -1 (+1 / -0 )Share on Facebook
  • CesarCesar Member
    Thank you @NatWobble and @pie but it doesn't work any of your solutions when the two buttons are pressed and holded simultaneously. I want to track each button begintouch and endtouch independently of the pushstate of the other button, even if any of both are moving.

    I can state my question from another perspective:

    How can I drag and drop two shapes simultaneously?. I think that problem is the same than my first question, and both can be resolved in the same way.
  • With below code, I was able to drag two shapes simultaneously. Hope it helps.
    HoldButton = Core.class(Sprite)
    function HoldButton:init(id, posx, posy)
    	self.id=id
    	self:setPosition(posx, posy)
     
    	self.shape = Shape.new()
    	self.shape:beginPath()
    	self.shape:setFillStyle(Shape.SOLID, 0xff0000)
    	self.shape:setLineStyle(1, 0x000000)
    	self.shape:moveTo(0,0)
    	self.shape:lineTo(0,50)
    	self.shape:lineTo(50,50)
    	self.shape:lineTo(50,0)
    	self.shape:lineTo(0,0) 
    	self.shape:endPath() 
    	self:addChild(self.shape)
     
    	self:addEventListener(Event.TOUCHES_MOVE, self.selectTouch, self)
    end
     
    function HoldButton:selectTouch(event)
    	if self:hitTestPoint(event.touch.x, event.touch.y) then		
    		self:setPosition(event.touch.x - 25, event.touch.y - 25)
    	end
    end
     
    a = HoldButton.new("First Instance", 100, 100)	
    	stage:addChild(a)
    b = HoldButton.new("Second Instance", 200, 200)	
    	stage:addChild(b)
  • hgy29hgy29 Maintainer
    @Cesar, you must first define the behaviour of your button class. I don't know what behaviour you want but a typical one would be:
    1. A button get select when mouse is pressed within its bounds.
    2. If mouse move while the button is selected, then the button is unselected if mouse leaves the bounds of the button and selected again if the mouse enter it again
    3 if mouse is released while the button is selected, then the button is deselected and a click event is generated

    So you can handle 1 in touch begin, 2 in touch move and 3 in touch end, independently of other button instances just by keeping some isSelected variable within each instance, similarly to @NatWooble example.

    Likes: Cesar

    +1 -1 (+1 / -0 )Share on Facebook
  • CesarCesar Member
    edited April 2016
    @hgy29. Exactly !!!. This is exactly what I want to do. The @NatWooble approach seems not working in multitouch environment (when pressing two or more buttons simultaneously). Am I right?. Any other suggestion?
  • hgy29hgy29 Maintainer
    Accepted Answer
    Something like this ?
    HoldButton = Core.class(Sprite)
    function HoldButton:init(id, posx, posy)
    	self.id=id
    	self:setPosition(posx, posy)
     
    	self.shape = Shape.new()
    	self.shape:beginPath()
    	self.shape:setFillStyle(Shape.SOLID, 0xff0000)
    	self.shape:setLineStyle(1, 0x000000)
    	self.shape:moveTo(0,0)
    	self.shape:lineTo(0,50)
    	self.shape:lineTo(50,50)
    	self.shape:lineTo(50,0)
    	self.shape:lineTo(0,0) 
    	self.shape:endPath() 
     
    	self:addChild(self.shape)
     
    	self:addEventListener(Event.TOUCHES_BEGIN, self.beginTouch, self)
    	self:addEventListener(Event.TOUCHES_END, self.endTouch, self)
    end
     
    function HoldButton:beginTouch(event)	
    	if self:hitTestPoint(event.touch.x, event.touch.y) then		
    		print("beginTouch: "..self.id.." Finger:"..event.touch.id)
    		self.touchId=event.touch.id
    	end
    end	
     
    function HoldButton:endTouch(event)
    	if self.touchId==event.touch.id then
    		print("endTouch: "..self.id.." Finger:"..event.touch.id)
    		if self:hitTestPoint(event.touch.x, event.touch.y) then
    			print("Triggered:"..self.id)
    		end
    		self.touchId=nil
    	end
    end
     
     
    a = HoldButton.new("First Instance", 100, 100)	
    	stage:addChild(a)
    b = HoldButton.new("Second Instance", 200, 200)	
    	stage:addChild(b)

    Likes: Cesar

    +1 -1 (+1 / -0 )Share on Facebook
  • CesarCesar Member
    @hgy29 Yes. That is perfect !!!

    Thank you very much. !!!!
  • hgy29hgy29 Maintainer
    You almost had it right from the beginning, I only added touch.id check.

    Likes: antix

    +1 -1 (+1 / -0 )Share on Facebook
Sign In or Register to comment.