您的位置:首页 > 移动开发 > Cocos引擎

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

2013-05-14 17:23 483 查看
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: