底部操作栏的封装

来源:互联网 发布:linux怎么创建文本文件 编辑:程序博客网 时间:2024/05/02 02:50

底部操作栏包括手柄,按钮和一个梯度



手柄:

手柄的实现来自于Joystick(网上有其实现的源码)

当把摇杆往最右方向移动,然后靠着边绕一圈,发现其值是-1和1之间,即单位向量,所以如何计算出这个单位向量是实现的核心。

void Joystick::updateVelocity(CCPoint point) {if(_diable) //不可用,则返回,不需计算return;// Calculate distance and angle from the center.float dx = point.x;//当前的触摸点的x值float dy = point.y;//当前的触摸点的y值if(!_autoCenter && dx == 0 && dy == 0) {//原点则返回,不需计算return;}float dSq = dx * dx + dy * dy;//计算x的平方加上y的平方if(dSq <= _deadRadiusSq) {//如果小于死亡半径的平方(如果有设置死亡半径的话),返回原点坐标和向量_velocity = CCPointZero;_degrees = 0.0f;_stickPosition = point;return;}float angle = atan2f(dy, dx); //计算弧度if(angle < 0){//弧度小于0,则加上2 * pi,即弧度的范围控制在0到2 * pi之间angle+= SJ_PI_X_2;}float cosAngle;float sinAngle;if(_isDPad){float anglePerSector = 360.0f / _numberOfDirections * SJ_DEG2RAD;angle = round(angle/anglePerSector) * anglePerSector;}cosAngle = cosf(angle);//计算余弦sinAngle = sinf(angle);//计算正弦// NOTE: Velocity goes from -1.0 to 1.0.if (dSq > _joystickRadiusSq || _isDPad) { //计算x和y值dx = cosAngle * _joystickRadius;dy = sinAngle * _joystickRadius;}_velocity = CCPointMake(dx / _joystickRadius, dy / _joystickRadius);//计算控制器的点_degrees = angle * SJ_RAD2DEG;if(_isOverRange) {dx = dx / 2;dy = dy / 2;}// Update the thumb's position_stickPosition = ccp(dx, dy);}
其思路可以概括为:

1、当触摸移动时,获取当前的坐标(节点内),根据坐标的x值和y值利用反正切函数求出当前的坐标的弧度

2、确保弧度范围是在0到2 * pi之间

3、利用弧度计算正弦和余弦

4、利用正弦和余弦计算出单位向量值


按钮:

实现思路如下:

1、判断触摸点是否在按钮的范围内

2、判断按钮是否需要冷却

2.1 不需冷却:那么在触摸移动时继续判断是否还是在按钮范围内,如果是,按钮的功能继续保持

2.2 需要冷却:那么当点击完按钮后,不需要往下分发触摸事件,点击完后执行冷却效果

bool Button::ccTouchBegan(CCTouch *touch, CCEvent *event) {if(_active || _disable || GameLayer::shareGameLayer()->getShip()->getIsHyperspaceJump()) {//处于激活状态或者超空间跳跃状态return false;}float radiusSq = _radius * _radius;CCPoint location = CCDirector::sharedDirector()->convertToGL(touch->getLocationInView());location = this->convertToNodeSpace(location);//判读触摸点是否在按钮上if(location.x < -_radius || location.x > _radius || location.y < -_radius || location.y > _radius){return false;}else{float dSq = location.x * location.x + location.y * location.y;if(radiusSq > dSq){if(this->_coolingEnd) {// 是否冷却结束this->_active = true;if(_cool && !_limit) {//执行冷却效果_target->triggerButton(this->_buttonType);//执行按钮功能this->_coolingEnd = false;//执行冷却CCProgressFromTo* to = CCProgressFromTo::create(_coolingTime, _percentage, 0);CCProgressTimer* progress = CCProgressTimer::create(_sprite);progress->setType(kCCProgressTimerTypeRadial);progress->setTag(99);progress->setReverseProgress(true);this->getParent()->addChild(progress);CCCallFunc* func = CCCallFunc::create(this, callfunc_selector(Button::onCallback));//按钮重置可用progress->runAction(CCSequence::create(to, func, NULL));return false;//结束触摸分发}else {_target->triggerButton(this->_buttonType);}}return true;}}return false;}
void Button::ccTouchMoved(CCTouch *touch, CCEvent *event) {if(_limit && _active && !_cool) {//判断是否需要冷却float radiusSq = _radius * _radius;CCPoint location = CCDirector::sharedDirector()->convertToGL(touch->getLocationInView());location = this->convertToNodeSpace(location);if(location.x < -_radius || location.x > _radius || location.y < -_radius || location.y > _radius){//触摸点是否离开按钮_active = false;return;}else{float dSq = location.x*location.x + location.y*location.y;if(radiusSq > dSq){//触摸点还在按钮上,继续执行该按钮的功能_target->triggerButton(this->_buttonType);_active = true;}}}}

其中按钮的功能通过一个协议来触发

在放置按钮的层上,继承了该协议,再由此层指派按钮的功能到各自实现类去实现,即MVC模式

首先定义一个协议

class ButtonDelegate{public:virtual void triggerButton(HW_BUTTON_TYPE buttonType) = 0;//触发按钮事件virtual void unTriggerButton(HW_BUTTON_TYPE buttonType) = 0;//触发结束事件};

其次定义按钮的功能类别

typedef enum {MIN_SPPED = 0,ADD_SPEED,DODGE,SHOOT_QUANTUM_GUN,HYPERSPACE_JUMP,SWITCH_HEAVY_MISSILE,ADD_ION_LIMIT_TIME,SAME_LOCKING_ENEMY,BLACK_HOLE,EMP}HW_BUTTON_TYPE;

最后,继承该协议,重写协议的两个方法

class BorderLayer : public CCLayer, public ButtonDelegate

void BorderLayer::triggerButton(HW_BUTTON_TYPE buttonType) {    switch (buttonType) {    case MIN_SPPED:break;    case ADD_SPEED:break;    case DODGE:break;    case SHOOT_QUANTUM_GUN:break;    ...    }}void BorderLayer::unTriggerButton(HW_BUTTON_TYPE buttonType) {    //do something}



0 0
原创粉丝点击