cocos2d的虚拟摇杆有现在的类库可供调用,国内的同伴也将其移植为了cocos2d-x的,也有自己实现的。
在网上找了一篇实现 cocos2d-x摇杆JoyStick,地址为:http://blog.csdn.net/jukai7/article/details/8623033
作者讲得很清楚了,本着不重复发明轮子的原则,我把代码抄了一份,以后项目中应该能用得到。
代码下载地址:http://vdisk.weibo.com/s/BqB5v/1368522809
HelloWorldScene.h代码:
#ifndef __HELLOWORLD_SCENE_H__ #define __HELLOWORLD_SCENE_H__ #include "cocos2d.h" USING_NS_CC; enum { TileMapNode = 0, }; class HelloWorld : public cocos2d::CCLayer { public: // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone virtual bool init(); // there's no 'id' in cpp, so we recommand to return the exactly class pointer static cocos2d::CCScene* scene(); // a selector callback void menuCloseCallback(CCObject* pSender); virtual void ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent); virtual void ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent); virtual void ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent); float heronsformula(float x1,float y1,float x2,float y2,float x3,float y3); bool triangleContainPoint(float x1,float y1,float x2,float y2,float x3,float y3,float px,float py); CC_SYNTHESIZE(cocos2d::CCTMXTiledMap*, _tileMap, TileMap); CC_SYNTHESIZE(cocos2d::CCTMXLayer*, _background, Background); // implement the "static node()" method manually CREATE_FUNC(HelloWorld); private: void flying(float dt); cocos2d::CCSprite *joystick; //中心点O cocos2d::CCPoint O; //大圆半径 float R; cocos2d::CCSprite *plane; //飞机飞行的速度分量值 float speedX; float speedY; //是否飞行的标志 bool isFlying; }; #endif // __HELLOWORLD_SCENE_H__
HelloWorldScene.cpp代码:
#include "HelloWorldScene.h" using namespace cocos2d; CCScene* HelloWorld::scene() { CCScene * scene = NULL; do { // 'scene' is an autorelease object scene = CCScene::create(); CC_BREAK_IF(! scene); // 'layer' is an autorelease object HelloWorld *layer = HelloWorld::create(); CC_BREAK_IF(! layer); // add layer as a child to scene scene->addChild(layer); } while (0); // return the scene return scene; } // on "init" you need to initialize your instance bool HelloWorld::init() { bool bRet = false; do { ////////////////////////////////////////////////////////////////////////// // super init first ////////////////////////////////////////////////////////////////////////// CC_BREAK_IF(! CCLayer::init()); ////////////////////////////////////////////////////////////////////////// // add your codes below... ////////////////////////////////////////////////////////////////////////// // 1. Add a menu item with "X" image, which is clicked to quit the program. // Create a "close" menu item with close icon, it's an auto release object. CCMenuItemImage *pCloseItem = CCMenuItemImage::create( "CloseNormal.png", "CloseSelected.png", this, menu_selector(HelloWorld::menuCloseCallback)); CC_BREAK_IF(! pCloseItem); // Place the menu item bottom-right conner. pCloseItem->setPosition(ccp(CCDirector::sharedDirector()->getWinSize().width - 20, 20)); // Create a menu with the "close" menu item, it's an auto release object. CCMenu* pMenu = CCMenu::create(pCloseItem, NULL); pMenu->setPosition(CCPointZero); CC_BREAK_IF(! pMenu); // Add the menu to HelloWorld layer as a child layer. this->addChild(pMenu, 5); CCSize size = CCDirector::sharedDirector()->getWinSize(); //创建瓦片地图 this->setTileMap(CCTMXTiledMap::create("pd_tilemap1.tmx")); _tileMap->setAnchorPoint(ccp(0.0f, 0.0f)); //设置瓦片地图的锚点为屏幕正中间 _tileMap->setPosition(ccp(0, 0)); //设置瓦片地图的位置为屏幕左下角 this->setBackground(_tileMap->layerNamed("Layer1")); this->addChild(_tileMap, 2, TileMapNode); //加入场景层 //获取Objects对象层 CCLOG("_tileMap %d", _tileMap->retainCount()); CCTMXObjectGroup *objects = _tileMap->objectGroupNamed("Objects"); CCLOG("_tileMap %d", _tileMap->retainCount()); CC_BREAK_IF(!objects); //如果失败,退出 //获取SpawnPoint的字典(包含坐标,高和宽等信息) CCDictionary *spawnPoint = objects->objectNamed("SpawnPoint"); CC_BREAK_IF(!spawnPoint); //如果失败,退出 //分别取x和y坐标的值 int x = spawnPoint->valueForKey("x")->intValue(); int y = spawnPoint->valueForKey("y")->intValue(); plane = CCSprite::create("hartnett.jpg"); plane->setPosition(ccp(size.width/2, size.height/2)); plane->setScale(0.3f); this->addChild(plane, 2); //创建摇杆下面部分 CCSprite *joystick1 = CCSprite::create("joystick1.png"); //设置透明度,锚点,位置 joystick1->setOpacity(191); joystick1->setAnchorPoint(ccp(0, 0)); joystick1->setPosition(ccp(0, 0)); joystick1->setColor(ccWHITE); //大圆半径 R=joystick1->getContentSize().width/2; //中心点 O = ccp(R, R); //添加进布景 this->addChild(joystick1, 3); //创建摇杆上面圆圈部分 joystick = CCSprite::create("joystick2.png"); //设置位置为摇杆中心点并添加进布景 joystick->setPosition(ccp(O.x, O.y)); joystick->setColor(ccRED); joystick->setScale(0.8f); this->addChild(joystick, 4); //初始化需要的变量 isFlying = false; speedX = speedY = 0; //设置可触摸 this->setTouchEnabled(true); //每帧要执行的函数 this->schedule(schedule_selector(HelloWorld::flying)); bRet = true; } while (0); return bRet; } void HelloWorld::menuCloseCallback(CCObject* pSender) { // "close" menu item clicked CCDirector::sharedDirector()->end(); } void HelloWorld::ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent) { CCTouch *touch = (CCTouch*)pTouches->anyObject(); CCPoint location = touch->getLocation(); CCRect rect=joystick->boundingBox(); if (rect.containsPoint(location)) { isFlying=true; } } void HelloWorld::ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent) { CCTouch *touch = (CCTouch*)pTouches->anyObject(); CCPoint location = touch->getLocation(); //判断触摸滑动点是否在摇杆范围内 bool inRange = pow(O.x - location.x, 2) + pow(O.y - location.y, 2) < pow(R, 2); if (isFlying && inRange) { CCPoint position=plane->getPosition(); joystick->setPosition(location); float r = R * 2 / 6; float d = R * 2 / 3; //上,区域2或5 if(triangleContainPoint(O.x, O.y, O.x - r, O.y + r, O.x +r, O.y + r, location.x, location.y) || CCRectMake(O.x - r, O.y + r, d, d).containsPoint(location)) { speedX=0; speedY=1; } //下,区域6或11 else if (triangleContainPoint(O.x, O.y, O.x - r, O.y - r, O.x + r, O.y - r, location.x, location.y) || CCRectMake(O.x - r, O.y - r - d, d, d).containsPoint(location)) { speedX=0; speedY=-1; } //左,区域4或7 else if (triangleContainPoint(O.x, O.y, O.x - r, O.y + r, O.x - r, O.y - r, location.x, location.y) || CCRectMake(O.x - r - d, O.y - r, d, d).containsPoint(location)) { speedX=-1; speedY=0; } //右,区域9或8 else if (triangleContainPoint(O.x, O.y, O.x + r, O.y + r, O.x + r, O.y - r, location.x, location.y) || CCRectMake(O.x + r, O.y - r, d, d).containsPoint(location)) { speedX=1; speedY=0; } //右上,区域3 else if (location.x - (O.x + r) > 0 && location.y - (O.y + r) > 0) { speedX = 0.7f; speedY = 0.7f; } //左上,区域1 else if (location.x - (O.x - r) < 0 && location.y - (O.y + r) > 0) { speedX=-0.7f; speedY=0.7f; } //左下,区域10 else if (location.x - (O.x - r) < 0 && location.y - (O.y - r) < 0) { speedX = -0.7f; speedY = -0.7f; } //右下,区域12 else if (location.x - (O.x + r) > 0 && location.y - (O.y - r) < 0) { speedX = 0.7f; speedY = -0.7f; } } } void HelloWorld::ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent) { isFlying = false; joystick->setPosition(O); speedX = speedY = 0; } void HelloWorld::flying(float dt) { if (isFlying && (speedX != 0 || speedY != 0)) { //飞机飞行 CCPoint position=ccp(plane->getPosition().x+speedX, plane->getPosition().y + speedY); CCSize size=CCDirector::sharedDirector()->getWinSize(); CCRect rect=CCRectMake(0, 0, size.width, size.height); //判断触摸点是否在屏幕内 if(rect.containsPoint(position)) { plane->setPosition(position); } } } float HelloWorld::heronsformula(float x1,float y1,float x2,float y2,float x3,float y3) { //求边长a float a = sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2)); //求边长b float b = sqrt(pow(x2 - x3, 2) + pow(y2 - y3, 2)); //求边长c float c = sqrt(pow(x3 - x1, 2) + pow(y3 - y1, 2)); //求半周长s float s = (a + b + c) / 2; //根据海伦公式返回三角形面积 return sqrt(s * (s - a) * (s - b) * (s - c)); } //判断三个新三角形面积和是否等于原先三角形面积的函数的实现 bool HelloWorld::triangleContainPoint(float x1,float y1,float x2,float y2,float x3,float y3,float px,float py) { //求S1的面积 float s1=heronsformula(x1,y1,x2,y2,px,py); //求S2的面积 float s2=heronsformula(x2,y2,x3,y3,px,py); //求S3的面积 float s3=heronsformula(x3,y3,x1,y1,px,py); //求S的面积 float s=heronsformula(x1,y1,x2,y2,x3,y3); //返回S是否等于S1,S2,S3的和 return abs(s-(s1+s2+s3))<0.001f; }