How to handle simultaneous(2) touches on screen?

Hello Guys!!!

Defold it is amazing!!! i never had make a professional game before!!! But Defold (and you too, guys haha) allow me to do one with a easy step-to-step! super cool!

But comming back to reality… I have a new problem. :smiley:

This is my game situation:

My problem:
My controls are working very well by key board and by mouse click. But aren’t working well by touch screen. When using keyboard the girl can run and cast her fire, at the same time. But by using touchscreen she can OR run OR cast her fire. never both together.

Here is my input commands:

Here is my pad (left/right) function to handle the touch action:

function on_input(self, action_id, action)
  
  if ( action_id == hash("click") or action_id == hash("touch") ) and action.repeated then 
      if inMyArea(self,action.x,action.y) and pointToRight(self,action.x,action.y) then
         self.canAct = true
         self.pointToRight = true
         self.pointToLeft = false
      end  
   end

Here is my fireButton function to handle the touch action: (the red one)

function on_input(self, action_id, action)
  
  if ( action_id == hash("click") or action_id == hash("touch_btn1") ) and action.pressed then 
      if inMyArea(self,action.x,action.y) then
         self.canAct = true
      end  
   end
   
end

What am I doing wrong? any ideas?

Thanks!

You should only have one TOUCH_MULTI input binding. When you detect a multi-touch action_id you will get a list of touch points, and you should loop through that list of touch points and check each of them if they press on any of your virtual/on-screen gamepad controls. Something like this:

function on_input(self, action_id, action)
	if action_id == hash("touch") then
		if action.touch then
			for _,touchpoint in ipairs(action.touch) do
				if touchpoint.pressed then
					-- handle pressed event for the touch point
					print("Pressed touch point at", touchpoint.x, touchpoint.y)
				elseif touchpoint.released then
					-- handle released event for the touch point
					print("Released touch point at", touchpoint.x, touchpoint.y)
				else
					print("Touch point at", touchpoint.x, touchpoint.y)
				end
			end
		end
	end
end

This is all documented in the input manual under the touch trigger section.

2 Likes

Hi @britzl I followed your instructions and again my problem was solved!
new i can two or more action at same time using the touch. However a strange behavior risen up.

I can’t make a gif for you because i’m using my phone to test the touch behavior…

So… please try to imagine these steps:

  1. The game starts
  2. I touch on right arrow pad… the girl starts to run to right.
  3. with girl running I touch the red button (and keep it pressed) and so she cast her fireBall and her keep running
  4. Now I have two points pressed on screen and the girl keep running.
  5. So… I release the right arrow point and keep the redButton pressed.
  6. At this step the girl should stoped running… but her insists to keep running.

I know, I know… looks like Dark Magic… :joy:
But I guess that I made another logic error. What do you think about?

Here is my input code:
pad script (left/right)

if (action_id == hash("touch") ) and action.released then 
      if inMyArea(self,action.x, action.y) then
	      self.canAct       = true
	      self.pointToRight = false
	      self.pointToLeft  = false
      end
  end 
  
  
  if action_id == hash("touch")  and #action.touch > 1 and #action.touch < 4 then
     for i, tpoint in ipairs(action.touch) do
		 if inMyArea(self,tpoint.x, tpoint.y) and pointToRight(self,tpoint.x, tpoint.y) then
		     self.canAct = true
		     self.pointToRight = true
		     self.pointToLeft  = false
		    --break
		 end 
		 if inMyArea(self,tpoint.x, tpoint.y) and pointToLeft(self,tpoint.x, tpoint.y) then
		     self.canAct = true
		     self.pointToRight = false
		     self.pointToLeft  = true
		     --break
		 end   
    end
  end

redButton script (fireBall)

  if action_id == hash("touch") and #action.touch > 1 and #action.touch < 4 then
     for i, tpoint in ipairs(action.touch) do
		 if inMyArea(self,tpoint.x, tpoint.y) then
		     self.canAct = true
		     --break
		 end 
	end
  end

Thanks Man. I afraid that I owe you a lot of beer mugs. hahah

Havent used touches before, but i suppose you have to check that touch was released for every touch - in for loop, you should add this inside the loop, instead of checking it outside.

  if tpoint.released then 
      if inMyArea(self,tpoint.x, tpoint.y) then
	      self.canAct       = true
	      self.pointToRight = false
	      self.pointToLeft  = false
      end
  end 

Thanks for your hint @Xorboo. I have tryed but didn’t work too.

Basically my problem is:
I have two points of contact in my screen, How can I check when only one of those were released?

Here is my actual script:

 if action_id == hash("touch")  and #action.touch > 1 and #action.touch < 4 then
     for i, tpoint in ipairs(action.touch) do
		 if inMyArea(self,tpoint.x, tpoint.y) and pointToRight(self,tpoint.x, tpoint.y) then
		     self.canAct = true
		     self.pointToRight = true
		     self.pointToLeft  = false
		     break
		 end 
		 if inMyArea(self,tpoint.x, tpoint.y) and pointToLeft(self,tpoint.x, tpoint.y) then
		     self.canAct = true
		     self.pointToRight = false
		     self.pointToLeft  = true
		     break
		 end   
		 if tpoint.released then 
		      if inMyArea(self,tpoint.x, tpoint.y) then
			      self.canAct       = true
			      self.pointToRight = false
			      self.pointToLeft  = false
		      end
		  end 
    end
  end

any ideas?

Uh, sad to hear that. I see 2 things now:

  1. You should probably remove and #action.touch > 1 and #action.touch < 4 as it was in manual to be an example for specifing ‘using 2 or 3 fingers’.
  2. If it doesn’t help, then you’ll probably have to check that any touch was found in your area, otherwise - none were found.
local area_touched = false
for ...
  if inMyArea() then 
    area_touched = true 
    -- Checking left and right points (and tpoint.released)
  end
end

if not area_touched then -- no touches on the arrows
  self.canAct = true
  ...
end

Though this means that there is something wrong with recieving release callbacks for touches or we are doing something wrong, probably should wait for more experienced guys to show us the solution :slight_smile:

Well well …

After @Xorboo hints I made more 3 test. but with out success.

Now I’m starting to think about a possible bug.
This behavior only happens when the game is running on mobile.

It is impossible detects when a finger release a point on screen.

Any ideas guys?


Here are my last tests:
T1

if action_id == hash("touch")  then
     local nothingFound = true;
     for i, tpoint in ipairs(action.touch) do
		 if inMyArea(self,tpoint.x, tpoint.y) and pointToRight(self,tpoint.x, tpoint.y) then
		     self.canAct = true
		     self.pointToRight = true
		     self.pointToLeft  = false
		     nothingFound = false
		     break
		 end 
		 if inMyArea(self,tpoint.x, tpoint.y) and pointToLeft(self,tpoint.x, tpoint.y) then
		     self.canAct = true
		     self.pointToRight = false
		     self.pointToLeft  = true
		     nothingFound = false
		     break
		 end   
		 
	end
	if nothingFound then
		self.canAct       = true
		self.pointToRight = false
		self.pointToLeft  = false
	end
  end

T2

if action_id == hash("touch")  then
    
     for i, tpoint in ipairs(action.touch) do
		
		 if inMyArea(self,tpoint.x, tpoint.y) and pointToRight(self,tpoint.x, tpoint.y) then
		     self.canAct = true
		     self.pointToRight = true
		     self.pointToLeft  = false
		     break
		 else
		 	 self.canAct       = true
			 self.pointToRight = false
			 self.pointToLeft  = false
		 end 
		 
		 if inMyArea(self,tpoint.x, tpoint.y) and pointToLeft(self,tpoint.x, tpoint.y) then
		     self.canAct = true
		     self.pointToRight = false
		     self.pointToLeft  = true
		     break
		 else
		 	 self.canAct       = true
			 self.pointToRight = false
			 self.pointToLeft  = false
		 end   
		 
	 end

T3

 if action_id == hash("touch")  then
    
     for i, tpoint in ipairs(action.touch) do
		
		 if not inMyArea(self,tpoint.x, tpoint.y) then
		 	 self.canAct       = true
			 self.pointToRight = false
			 self.pointToLeft  = false
		 end 
		 
		 if inMyArea(self,tpoint.x, tpoint.y) and pointToRight(self,tpoint.x, tpoint.y) then
		     self.canAct = true
		     self.pointToRight = true
		     self.pointToLeft  = false
		     break
		 end
		 
		 if inMyArea(self,tpoint.x, tpoint.y) and pointToLeft(self,tpoint.x, tpoint.y) then
		     self.canAct = true
		     self.pointToRight = false
		     self.pointToLeft  = true
		     break
		 end   
		 
	 end

Each individual touch point will contain a released boolean flag indicating if it was released. Can’t you use that variable? In most cases you probably don’t need to think of the touch points in any way different from a single touch. Something like this:

if action.touch then
	for i,tpoint in ipairs(action.touch) do
		if tpoint.pressed then
			if gui.pick_node(button1, tpoint.x, tpoint.y) then
				self.button1_pressed = true
			elseif gui.pick_node(button2, tpoint.x, tpoint.y) then
				self.button2_pressed = true
			end
		elseif tpoint.released then
			if gui.pick_node(button1, tpoint.x, tpoint.y) then
				self.button1_pressed = false
			elseif gui.pick_node(button2, tpoint.x, tpoint.y) then
				self.button2_pressed = false
			end
		end
	end
end
2 Likes