multitouch

okay, i implemented this:

function setup()
     touches = {}
end

and this:

function touched(touch)
    t = touch
    if t.state == ENDED then
        touches[touch.id] = nil
    else
        touches[touch.id] = t
    end
end

but now: how do i implement the multitouch? please just give me a simple example of the touched function doing two or more things! im working on a makeover of the bit invader and i need this… thank you!

greetings, maxiking

@Maxiking16 - Well, your “touches” table contains every single touch.

This is your multitouch.

How you handle it creates different effect (pinch to zoom).
For example, pinch to zoom is basically getting the the delta in the distance between your two touches (there is probably a better way to implement it, haven’t really looked into it).

-- if you have two touches
        local newPt = {}
        local lastPt = {}

        -- loop through your touches, retrieve the points, and calculate the delta
        for k, p in pairs(touches) do
            local px = p.x
            local py = p.y
            table.insert(newPt, vec2(px, py))
            if state == BEGAN then
                table.insert(lastPt, vec2(px, py))
            else
                table.insert(lastPt, vec2(px - p.deltaX, py - p.deltaY))
            end
        end
 
        delta = lastPt[1]:dist(lastPt[2]) - newPt[1]:dist(newPt[2])

Is that the kind of stuff you’re asking for ?

Cheers,

Xavier

hmm, i was looking for something that presses two buttons at the same time. i already have touched functions, but i have to turn them into multitouch. ill give you a code example:

function button:touched()
     t = CurrentTouch
     if t.x > self.x1 and t.y > self.y1 and t.x < self.x2 and t.y < self.y2 then
          if t.state == BEGAN then
               self.state = 1
               self.touching = true
          elseif t.state == MOVING then
               self.state = 2
          elseif t.state == ENDED then
               if self.touching then
                    self.state = 3
               end
                    self.touching = false
                    endTime = ElapsedTime
               end
          else
               self.state = 0
          end
     end
end

this is my touched function. its a class, so i Need it for multiple Buttons. So how do i have to change the touched function?

And thanks for the code @Xavier - this will find use in some of my projects :slight_smile:

The custom touch functions in your classes do not get called automatically.
I believe you need to add them to the “touched” function.

Didn’t use your code, but it should be easy to add something like this for it works:
http://pastebin.com/qJhVVSEh

There are no checks, so you can “eat” other rectangles, but that’s an easy fix.

Cheers,

Xavier

You could have a look at my Touch class (http://www.math.ntnu.no/~stacey/HowDidIDoThat/iPad/Codea.html). I have a touch handler class which “gathers” all the touches. When a touch begins, the handler class then queries a list of objects to see if any of them would like to claim it. It then marks that touch with that object so that it knows which object to pass it to. Then on each cycle, it sends each object all of the touches that it currently has listed (I call this a gesture) for that object. Gestures are slightly analysed before sending them as there are certain standard things that one could want to know about a family of touches (was it a tap, was it a pinch, that sort of thing). So each object that wants to use touches has to define a routine that says whether or not it wants to claim a touch, and a routine that says how it wants to handle touches, and each object has to register itself with the touch handler. The handler does all the sorting out in between times, and the handler makes sure that all the necessary routines are called.

So my main files often look a bit like this:

function setup()
    touches = Touches()
    object = MyAmazingObject(touches)
end

function draw()
    touches:draw()
    object:draw()
end

function touched(touch)
    touches:addTouch(touch)
end

MyAmazingObject = class()

function MyAmazingObject:init(t)
    t.pushHandler(self)
end

So I initialise the touch handler, and pass it as an argument to the object class. In its initialisation routine, it adds itself as a handler (push means: put at the end of the list, I can also unshift to put at the start for higher priority). In the draw routine, I call the draw method of Touches which doesn’t actually draw anything but does the touch processing. This is done every cycle instead of every touch event because of two things:

  1. I want to present all the touches to the object in a single gesture, not bit-by-bit as they come in. This makes it easier for the object to decide what to do.
  2. Touches might have useful information even if they weren’t updated that round. There’s a bit of internal bookkeeping to ensure that the objects know if touches were “fresh” or not.

The main advantage of this is that I don’t have to rewrite my touch handling stuff every time I define a new thing. The only bits I have to write are the bits that do depend on the new thing I’m defining: how to claim a touch, and what to actually do with the touch information.

@Xavier :

yes, i called this custom touched() function. in the draw loop.

so, in this example there is no touches table but the multitouch works. i tried it like this (and i called the touched(touch) function in the main touched(touch)function), but then the touches behave like current touch, but strangely… well, here is the whole code… could you look at it?

http://pastebin.com/d3qdEtkY

@Andrew_Stacey :

ill read this surely helpful comment later, I’m writing an english essay in the moment. btw, if i go to the link, i get to your error page…

thank you both for your replies!!

link fixed. Sorry

@Maxiking16 - The problem is that you are setting button state to 0 if a touch is not “on” the button.
Since you’re testing all buttons, when you multitouch, a “touch” will eventually be outside the button range, so its state will be switched to 0, even if it’s supposed to be still active.

to fix it, i used the “touching” setting, and made it a class variable.
In your init, add

self.touching = false.

self.touching… ok no immature laughs please, this is a serious conversation ^^

in your button:touched() function, at the end, instead of having

function button:touched()
...
else
    self.state = 0
end

Add a “if not self.touching” check (don’t you dare laugh), so you get:

function button:touched()
    t = CurrentTouch
    if t.x > self.x1 and t.y > self.y1 and t.x < self.x2 and t.y < self.y2 then
        if t.state == BEGAN then
            self.state = 1
            self.touching = true
        elseif t.state == MOVING then
            self.state = 2
        elseif t.state == ENDED then
            if self.touching then
                self.state = 3
            end
            self.touching = false
            endTime = ElapsedTime
        end
    else
        if not self.touching then
           self.state = 0
        end
    end
end

Here is a pastebin: http://pastebin.com/kFSpWE1T

Note that you should move the touch check to the touched function (called automatically by codea on touch).
This way, you’ll avoid the unnecessary calls if no touches are happening (although I doubt it will ever be the case in your game :P)

function touched(touch)
    for b = 1,#buttons do
        buttons[b]:touched()
    end
end

Cheers,

Xavier

omg your a genius! i am such a idiot. sorry for this! this is the typical “the-mistake-is-so-easy-to-find-but-i-cant” feeling you know?? thank you very much for helping me!!

@Maxiking16 - Oh I know the feeling :smiley:

Good luck,

Xavier

I’m sorry if there’s a rule against necro posting, but I have a question.when I implemented this with my multiple buttons, there were certain instances where a button would stick and it wouldn’t stop until I pressed it again. Do you have any ideas what could be wrong?

@Mac_n_chese - impossible to say without seeing code

(And yes, we prefer not to resurrect old threads - better is to start a new one and refer to the old one if you need to)