How to do multitouch implementation

HI, i’m donig a platformer game and it have 2 game object you can control (the character, controlled with a gui, and another that goes to the point in the screen you touch) how can i separate the touch input? Now when i use the gui to move the character the other character move to the arrow of the gamepad i implemented in the gui.

Thanks for your help

Just set up a multi touch trigger in your input bindings and react to the action name you gave it. All touch points are provided in a table. See http://www.defold.com/doc/input and the “multi touch” section.

I did a thumbstick implementation like this.

function on_input(self, action_id, action)
	if action_id == ACTION_TOUCH then
		if not self.multi_touch then
			handle_touch(self, action)
		end
	elseif action_id == ACTION_TOUCH_MULTI then
		self.multi_touch = true

		if not self.touch_id then
			local touch_id = #action.touch
			local touch = action.touch[touch_id]
			if touch.pressed and gui.pick_node(self.btn_stick, touch.x, touch.y) then
				self.touch_id = touch_id
			end
		end
		if self.touch_id then
			local touch = action.touch[self.touch_id]
			if touch then
				handle_touch(self, touch)
				if touch.released then
					self.touch_id = nil
				end
			else
				self.touch_id = nil
			end
		end
	end
end
1 Like

It does have one drawback tho, if you release touch1 before touch2 then it becomes a mixup.
So touch_id should be calculated in a more elegant way than #touch

hi, I read the multitouch manual but i don’t get what i’m doing wrong in the code. I got the gui and all is working for the first touch but for the second touch don’t do anything. Thats the code i use:

if action_id == hash(“touch”) and #action.touch == 1 then
– do something
end
if action_id == hash(“touch”) and #action.touch == 2 then
– do something
end

as I said, the first touch is identified but the second never do the action (the actions are pick gui nodes and do something depending in the picked node)

If you want to check each touch to see if it is “on” a gui node you would do something like:

for i,touch in pairs(action.touch) do
  check_touch(action)
end

i mean something like first touch for right arrow to run second touch for jump while runing

Are you doing this with on-screen buttons or gestures?

i’m doing it with on-screen buttons

Ok, then I guess you need to go through each touch point and see if the x,y position is within the bounds of your button and set a state variable that the button is touched. Check out http://www.defold.com/ref/gui#gui.pick_node

i do it :

if (action_id == hash(“touch”) and #action.touch == 1) or action_id == hash(“click_1”) then
local gui_right_arrow = gui.get_node(“right”)
local gui_left_arrow = gui.get_node(“left”)
local gui_jump_button = gui.get_node(“jump”)
if gui.pick_node(gui_right_arrow,action.x,action.y) then
msg.post(“character#script”, “right”, {value=action.value})
elseif gui.pick_node(gui_left_arrow,action.x,action.y) then
msg.post(“character#script”, “left”,{value=action.value})
elseif gui.pick_node(gui_jump_button,action.x,action.y) then
if action.pressed then
msg.post(“character#script”, “jump”)
elseif action.released then
msg.post(“character#script”, “abortjump”)
end

and same code but with a 2 in the action.touch for the second touch but the character don’t jump (jump in character works if u do with the first touch or using arrow control)

EDIT: the click part is just for test with mouse

The various touch inputs are in a table “action.touch” so you need to dig into that table:

-- Iterate through all touch points in action.touch:
for i, tpoint in ipairs(action.touch) do
    -- tpoint.x, tpoint.y contains the current coordinates for this touch
    -- do something with them here...
end

i do it as u said, it still dont jump, but every time i use the arrow i get this error: bad argument #1 to ‘ipairs’ (table expected, got nil)

Do “pprint(action)” to see what you get.

If you test with mouse you won’t get the “action.touch” table.

DEBUG:SCRIPT:
{
x = 192.25,
touch = {
1 = {
x = 192,
tap_count = 0,
pressed = false,
y = 86,
dx = 0,
released = false,
dy = 0,
}
2 = {
x = 1100,
tap_count = 0,
pressed = false,
y = 69,
dx = 0,
released = false,
dy = 0,
}
}
pressed = false,
y = 86.25,
screen_y = 173,
screen_dy = 0,
screen_dx = 0,
screen_x = 384,
dx = 0,
value = 1,
repeated = false,
released = false,
dy = 0,
}

ERROR:SCRIPT: World/controller/controller.gui_script:21: bad argument #1 to ‘ipairs’ (table expected, got nil)
stack traceback:
[C]: in function 'ipairs’
World/controller/controller.gui_script:21: in function <World/controller/controller.gui_script:19>
DEBUG:SCRIPT:
{
x = 192.25,
touch = {
1 = {
x = 192,
tap_count = 0,
pressed = false,
y = 86,
dx = 0,
released = false,
dy = 0,
}
2 = {
x = 1100,
tap_count = 0,
pressed = false,
y = 69,
dx = 0,
released = false,
dy = 0,
}
}
pressed = false,
y = 86.25,
screen_y = 173,
screen_dy = 0,
screen_dx = 0,
screen_x = 384,
dx = 0,
value = 1,
repeated = false,
released = false,
dy = 0,
}
and then a large list of the same eror

Do you do:

if (action_id == hash("touch") then
    ...
    -- Iterate through all touch points in action.touch:
    for i, tpoint in ipairs(action.touch) do
        -- tpoint.x, tpoint.y contains the current coordinates for this touch
        -- do something with them here...
        ...
    end
end

if action_id == hash(“touch”) or action_id == hash(“click_1”) then
for i, tpoint in ipairs(action.touch) do
local gui_right_arrow = gui.get_node(“right”)
local gui_left_arrow = gui.get_node(“left”)
local gui_jump_button = gui.get_node(“jump”) …
this is the code i use now

Because you get the touch table:

What action is “click_1”?