When working with multitouch, I usually have a vector where CustomTouch is a subclass of ofTouchEventArgs. Let me give you an example of the CustomTouch class, in this case it’s called ‘POFinger’.
POFinger.h
#pragma once
#include "ofMain.h"
class POFinger: ofTouchEventArgs {
public:
POFinger(int id, float x, float y);
POFinger(ofTouchEventArgs &touch);
void update(ofTouchEventArgs &touch);
int id;
float x;
float y;
float accel;
float angle;
float prevX;
float prevY;
};
POFinger.cpp
#include "POFinger.h"
POFinger::POFinger(int _id, float _x, float _y){
id = _id;
x = _x;
y = _y;
prevX = x;
prevY = y;
accel = 0;
angle = 0;
}
POFinger::POFinger(ofTouchEventArgs &touch){
id = touch.id;
x = touch.x;
y = touch.y;
prevX = x;
prevY = y;
accel = 0;
angle = 0;
}
void POFinger::update(ofTouchEventArgs &touch){
x = touch.x;
y = touch.y;
accel = ofDist(prevX, prevY, x, y); // acceleration is the distance between the previous point and this point
angle = atan2(prevY - y, prevX - x) + PI; // atan2 calculates num of radians
prevX = x;
prevY = y;
}
So basically I add the acceleration and angle functionality which can be extremely useful. Then in testApp.h (in this case physOSCApp.h) :
vector<POFinger> touches;
And the three important methods in physOSCApp.mm:
//--------------------------------------------------------------
void physOSCApp::touchDown(ofTouchEventArgs &touch) {
if(touches.size() < 5) touches.push_back(POFinger(touch));
for(int i = 0; i < particles.size(); i++){
if(ofDist(particles[i].x, particles[i].y, touch.x, touch.y) < particles[i].radius){
particles[i].fingerIndex = touches.size() - 1;
break;
}
}
}
//--------------------------------------------------------------
void physOSCApp::touchMoved(ofTouchEventArgs &touch) {
int indexOfMovedTouch = -1;
for(int i = 0; i < touches.size(); i++){ // find touch in vector of touches by id
if(touches[i].id == touch.id) indexOfMovedTouch = i;
}
if(indexOfMovedTouch != -1){
touches[indexOfMovedTouch].update(touch); // update the touch
}
for(int i = 0; i < particles.size(); i++){
if(particles[i].fingerIndex == indexOfMovedTouch){
float tempXVel = cos(touches[indexOfMovedTouch].angle) * touches[indexOfMovedTouch].accel;
float tempYVel = sin(touches[indexOfMovedTouch].angle) * touches[indexOfMovedTouch].accel;
particles[i].updatePos(touches[indexOfMovedTouch].x, touches[indexOfMovedTouch].y, tempXVel, tempYVel);
break;
}
}
}
//--------------------------------------------------------------
void physOSCApp::touchUp(ofTouchEventArgs &touch) {
int indexOfReleasedTouch = -1;
for(int i = 0; i < touches.size(); i++){
if(touches[i].id == touch.id) indexOfReleasedTouch = i;
}
if(indexOfReleasedTouch != -1) touches.erase(touches.begin() + indexOfReleasedTouch); // erase the touch
for(int i = 0; i < particles.size(); i++){
if(particles[i].fingerIndex == indexOfReleasedTouch){
particles[i].fingerIndex = -1;
break;
}
}
}
So I have a class POParticle, which has a member called fingerIndex. If a new touch is within the radius of the particle, fingerIndex is set to the index of the new touch. If the fingerIndex of a particle matches the index of a moved or released touch, the particle is updated accordingly. I placed some break-statements to prevent multiple particles being bound to a single touch, I’ve noticed that most users are content with the random nature of picking one of two particles at the same position.
This system of organizing touches gives me the idea that I’m in control of it. If you have lots of ‘touchable’ or ‘draggable’ objects, it would of course be wise to make a superclass ‘touchable’ and let all of your classes inherit from that class.