「cocos2d-x」虚拟摇杆实现(1)

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;  
}  

 

posted @ 2013-05-14 17:23  netxfly  阅读(917)  评论(0编辑  收藏  举报