尊重开发者的劳动成果,转载的时候请务必注明出处:http://blog.csdn.net/haomengzhu/article/details/17382889
<捕鱼达人>回顾
【cocos2d-x IOS游戏开发-捕鱼达人1】内容介绍
<城市跑酷>回顾
【cocos2d-x IOS游戏开发-城市跑酷1】跑酷游戏介绍
上节回顾
Cocos2d-X游戏【泰然网《跑酷》】JS到C++移植6:Running This Way
到目前为止runner可以向前移动。在给runner添加用户控制前,你需要处理玩家的输入。
在游戏中我们用跳上、跳下和转圈这三个手势来控制runner。
$1 Unistroke Recognizer是一个开源库。支持包含花圈在内的16个手势识别,有javaScript版本,可以很容易的导入到Cocos2dx JSB项目里,这也正是泰然网的处理方式。
还有一个C++版的【GeometricRecognizer】,http://depts.washington.edu/aimgroup/proj/dollar/others/cpp.bw.zip
但是它有个缺点:很难区分向上滑动和向下滑动。必须由你自己去识别这两个手势。
Simple Recognizer
Simple Recognizer可以识别简单手势包括swipe up, swipe down, swipe left and swipe right.
创建一个名为“SimpleRecognizer.cpp”的cpp文件。替代内容如下:
#include "SimpleRecognizer.h" #define MAX_DOUBLE std::numeric_limits<double>::max(); // class define SimpleRecognizer::SimpleRecognizer() { this->result = SimpleGesturesError; } // be called in onTouchBegan void SimpleRecognizer::beginPoint(double x, double y) { this->result = SimpleGesturesError; points.push_back(Point(x,y)); } // be called in onTouchMoved void SimpleRecognizer::movePoint(double x, double y) { points.push_back(Point(x, y)); if (result == SimpleGesturesNotSupport) { return; } SimpleGestures newRtn = SimpleGesturesError; int len = this->points.size(); //每当触点移动时,在当前触点和之前触点之间计算不同的x坐标和y坐标 double dx = this->points[len - 1].x - this->points[len - 2].x; double dy = this->points[len - 1].y - this->points[len - 2].y; if (abs(dx) > abs(dy)) { //在这种情况下,运动趋势的触点在x轴方向 if (dx > 0) { newRtn = SimpleGesturesRight; } else { newRtn = SimpleGesturesLeft; } } else { //在这种情况下,运动趋势的触点在y轴方向 if (dy > 0) { newRtn = SimpleGesturesUp; } else { newRtn = SimpleGesturesDown; } } // first set result if (result == SimpleGesturesError) { result = newRtn; return; } // if diretcory change, not support Recongnizer if (result != newRtn) { result = SimpleGesturesNotSupport; } } SimpleGestures SimpleRecognizer::endPoint() { if (this->points.size() < 3) { return SimpleGesturesError; } return result; } std::vector<Point>& SimpleRecognizer::getPoints() { return points; }
然后:Integrated into the PlayLayer
定义新的类成员变量
SimpleRecognizer *recognizer; GeometricRecognizer* geometricRecognizer;//使用GeometricRecognizer Path2D p_2dPath;
// enable touch this->setTouchEnabled(true); // set touch mode to kCCTouchesOneByOne this->setTouchMode(kCCTouchesOneByOne); //自己扩展的简单手势识别 recognizer = new SimpleRecognizer(); //加载模板然后记录触摸操作(玩家在手机上所做手势的路径) geometricRecognizer = new GeometricRecognizer; geometricRecognizer->loadTemplates();Y ou enable the touch of the layer, and set touch mode to kCCTouchesOneByOne, which receive touch point one at a time in event callbacks.
接着扩展触屏处理,添加下面代码到PlayLayer:
bool PlayScene::ccTouchBegan(CCTouch* touch, CCEvent* event) { CCLOG("PlayScene::ccTouchBegan"); CCPoint pos = touch->getLocation(); recognizer->beginPoint(pos.x, pos.y); return true; } void PlayScene::ccTouchMoved(CCTouch* touch, CCEvent* event) { //CCLOG("PlayScene::ccTouchMoved"); #if 1 CCPoint pos = touch->getLocation(); recognizer->movePoint(pos.x, pos.y); #else CCPoint location = touch->getLocation(); Point2D p_Point2DTemp; p_Point2DTemp.x = location.x; p_Point2DTemp.y = location.y; //记录 p_2dPath.push_back(p_Point2DTemp); #endif } void PlayScene::ccTouchEnded(CCTouch* touch, CCEvent* event) { CCLOG("PlayScene::ccTouchEnded"); #if 1 SimpleGestures rtn = recognizer->endPoint(); switch (rtn) { case SimpleGesturesUp: CCLOG("Runner::jump"); break; case SimpleGesturesDown: CCLOG("Runner::crouch"); break; case SimpleGesturesNotSupport: case SimpleGesturesError: // try dollar Recognizer // 0:Use Golden Section Search (original) // 1:Use Protractor (faster) CCLOG("not support or error touch,use geometricRecognizer!!"); #if 0 //通过GeometricRecognizer校准 //可以选择屏蔽玩家单击操作 if (p_2dPath.size() < 1){ return ; } RecognitionResult r = geometricRecognizer->recognize(p_2dPath); if((r.name != "Unknown") && (r.score > 0.5)) { if (r.name == "Circle") //开启runner无敌模式//return;}#endifbreak;}#endif} void PlayScene::ccTouchCancelled(CCTouch* touch, CCEvent* event) {CCLOG("onTouchCancelled!!!");}
1、在初始化的地方new一个GeometricRecognizer实例recognizer_,调用recognizer_->loadTemplates()方法。注意这个函数只是测试时使用,真正设计时,其手势模板应该是从配置文件中读取。
2、在TouchMove(或者是MouseMove,依平台而定)的时候将坐标push_back到一个集合里(touch_points_)。
3、在TouchEnd的时候调用: RecognitionResult r = recognizer_->recognize(touch_points_);
我们对其返回的结果进行判断,如果(r.name != "Unknown" && r.score > 0.5),那么这就是我们识别出来的一个手势。name是手势模板名称,score是其权重,越高则与模板越匹配。
到现在为止,你就可以支持手势识别了:
简单的识别器 识别 速度超过GeometricRecognizer。由它先识别swipe up 和 swipe down。 如果它不能识别,再使用$1 Unistroke Recognizer。
调试并运行,尝试swipe up, swipe down ,画一个圆。你将看到生成的日志。