cocos2d-xでマルチタッチを行う方法を調べてみましたので書いてみます。
###iOSでやること
まず、iOS側でのお仕事として、AppController.mmのeagleViewに次の行を加えます
// Init the CCEAGLView
CCEAGLView *eaglView = [CCEAGLView viewWithFrame: [window bounds]
pixelFormat: kEAGLColorFormatRGBA8
depthFormat: GL_DEPTH24_STENCIL8_OES
preserveBackbuffer: NO
sharegroup: nil
multiSampling: NO
numberOfSamples: 0];
// この1行を付け加える。この1行だけです!
[eaglView setMultipleTouchEnabled:YES];
//.....(以下略).....//
###□通常のシングルタッチとの比較□
通常だとこちら(setTouchEnabledがDeprecatedって言われたけどんじゃどうするんじゃい)のように、実装するといいんですね。
ではマルチタッチだとどうなるか。
auto listener = EventListenerTouchAllAtOnce::create();
listener->setEnabled(true);
listener->onTouchesBegan = CC_CALLBACK_2(PlaygroundScene::onTouchesBegan, this);
listener->onTouchesMoved = CC_CALLBACK_2(PlaygroundScene::onTouchesMoved, this);
listener->onTouchesEnded = CC_CALLBACK_2(PlaygroundScene::onTouchesEnded, this);
this->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this);
はい。書き方は同じです。しかし、挙動がやっかいなのです。
人差し指を置いて、親指を置いて、人差し指離して、親指離して、とすると
onTouchesBegan(人指し指)
onTouchesBegan(親指)
onTouchesEnded(人指し指)
onTouchesEnded(親指)
と4つ、メソッドが呼ばれます。
ちなみにcocos2d-x上で同時に押せる指の数は最大で5つのようです。
###画面上に押されている指の数の管理
同時に置かれてる指の管理にはいろいろ方法があるとは思いますが、今回はメンバ変数で管理しましょう。これはプレイヤーの意図を使うのに用います。一方の指がonTouchEndedしたときに
画面上の指が2本なら、ユーザーが2つの指でスワイプや、ピンチ、タップをしようとしてる可能性があるからです。誤タップもあるかもしれませんが...
private:
int numberOfTouch;
//////////////////
// コンストラクタで初期化しましょう。
Constructor():numberOfTouch(0){};
void PlaygroundScene::onTouchesBegan(const std::vector<Touch *> &touches, cocos2d::Event *unused_event){
// 入ってきた指の数だけ足されます。
numberOfTouch += vector.size();
}
void PlaygroundScene::onTouchesEnded(const std::vector<Touch *> &touches, cocos2d::Event *unused_event){
// 出て行った指の数だけ減ります
numberOfTouch -= vector.size();
}
onTouchesBegan(人指し指)
onTouchesBegan(親指)
onTouchesEnded(人指し指)
onTouchesEnded(親指)
と呼ばれた時,一度目のEndedが人指し指か、親指なのかをパッと見
cocos2dxには分からないように見えますが、Touchクラスには
TouchIDという指を識別するためのIDがあるのでそれを用いるといいかと思います。
cocos2d-xでは同時に5本の指(TouchID:0~4が割り当てられる)まで値を取ることができるので、例えば
vector<cocos2d::Vec2> trackedVectors;
Class::Class(){
for(int i = 0;i<5<i++){
trackedVectors.push_back(Vec2::ZERO);
}
}
とでもしておいて
void PlaygroundScene::onTouchesBegan(const std::vector<Touch *> &touches, cocos2d::Event *unused_event){
for(Touch* t : touches){
trackedVector[t->getID] = t->getLocation();
}
}
void PlaygroundScene::onTouchesEnded(const std::vector<Touch *> &touches, cocos2d::Event *unused_event){
for(Touch* t : touches){
trackedVector[t->getID] = t->getLocation()-trackedVector[t->getID];
// 単純なベクトル演算
// 各指の移動距離や方向をつかめるのでジェスチャーを捉えられる。
}
}
とすれば、各指のジェスチャーを捉えることができます。加えて、最後の指がディスプレイを離れるときnumberOfTouch = 0となることに注意すれば、最終入力時のイベントを取得できます。
void PlaygroundScene::onTouchesEnded(const std::vector<Touch *> &touches, cocos2d::Event *unused_event){
// 出て行った指の数だけ減ります
numberOfTouch -= vector.size();
// 最後の入力であればこのタイミングでnumberOfTouch = 0 となる
if(numberOfTouch == 0){
//各指の判定などを行える
}
}