您的位置:首页 > 编程语言 > C语言/C++

使用C++委托实现全方向的摇杆

2016-07-28 21:24 801 查看
1.摇杆类

//
//  Rocker.hpp
//  Rocker
//
//  Created by Forest on 16/7/11.
//
//

#ifndef Rocker_hpp
#define Rocker_hpp

#include <stdio.h>

#include "cocos2d.h"
USING_NS_CC;

class Rocker;

class RockerDelegate{
public:
virtual void rockerTouchBegan(Rocker* rocker,const Vec2& normalize) = 0;
virtual void rockerTouchMoved(Rocker* rocker,const Vec2& normalize) = 0;
virtual void rockerTouchEnded(Rocker* rocker,const Vec2& normalize) = 0;
};

class Rocker : public Node {

Rocker();
~Rocker();

Sprite* m_rocker;
Sprite* m_rockerBG;
Touch* m_touch;
EventListenerTouchAllAtOnce* m_listener;

bool isTouchInside(Touch* touch);

void touchBeganRocker(const Vec2& normalize);
void touchMovedRocker(const Vec2& normalize);
void touchEndedRocker(const Vec2& normalize);

void touchesBegan(const std::vector<Touch*>& touches, Event* event);
void touchesMoved(const std::vector<Touch*>& touches, Event* event);
void touchesEnded(const std::vector<Touch*>& touches, Event* event);

public:

static Rocker* createRocker(const std::string& rockerImage,const std::string& rockerBGImage);

bool initRocker(const std::string& rockerImage,const std::string& rockerBGImage);

void startRocker();
void stopRocker();

CC_SYNTHESIZE(RockerDelegate*, m_rockerDelegate, RockerDelegate);

};

#endif /* Rocker_hpp */


//
//  Rocker.cpp
//  Rocker
//
//  Created by Forest on 16/7/11.
//
//

#include "Rocker.hpp"

#include <algorithm>

Rocker::Rocker():
m_rocker(nullptr),m_rockerBG(nullptr),m_touch(nullptr),m_listener(nullptr)
{
}

Rocker::~Rocker(){

}

Rocker* Rocker::createRocker(const std::string &rockerImage, const std::string &rockerBGImage){
Rocker* rocker = new Rocker();
if (rocker && rocker->initRocker(rockerImage,rockerBGImage)) {
rocker->autorelease();
return rocker;
}
CC_SAFE_DELETE(rocker);
return nullptr;
}

bool Rocker::initRocker(const std::string &rockerImage, const std::string &rockerBGImage){
if (!Node::init()) {
return false;
}

m_rocker = Sprite::create(rockerImage);
this->addChild(m_rocker);
m_rocker->setVisible(false);

m_rockerBG = Sprite::create(rockerBGImage);
this->addChild(m_rockerBG);
m_rockerBG->setVisible(false);

this->startRocker();

return true;
}

void Rocker::startRocker(){
m_rocker->setVisible(true);
m_rockerBG->setVisible(true);

m_listener = EventListenerTouchAllAtOnce::create();

m_listener->onTouchesBegan = CC_CALLBACK_2(Rocker::touchesBegan, this);
m_listener->onTouchesMoved = CC_CALLBACK_2(Rocker::touchesMoved, this);
m_listener->onTouchesEnded = CC_CALLBACK_2(Rocker::touchesEnded, this);

this->getEventDispatcher()->addEventListenerWithSceneGraphPriority(m_listener, this);
}

void Rocker::stopRocker(){
m_rocker->setVisible(false);
m_rockerBG->setVisible(false);
this->getEventDispatcher()->removeEventListener(m_listener);
}

void Rocker::touchesBegan(const std::vector<Touch *> &touches, cocos2d::Event *event){
const std::vector<Touch*>::const_iterator it = find_if(touches.cbegin(),touches.cend(),[this](Touch* touch){
return this->isTouchInside(touch);
});

if (it != touches.cend()) {
m_touch = *it;
Vec2 point = this->convertToNodeSpace(m_touch->getLocation());
m_rocker->setPosition(point);
point.normalize();
this->touchBeganRocker(point);
}
}
void Rocker::touchesMoved(const std::vector<Touch *> &touches, cocos2d::Event *event){
const std::vector<Touch*>::const_iterator it = find_if(touches.cbegin(),touches.cend(),[this](Touch* touch){
return m_touch == touch;
});
if (it != touches.cend()) {
Vec2 point = this->convertToNodeSpace(m_touch->getLocation());
if (this->isTouchInside(m_touch)) {
m_rocker->setPosition(point);
point.normalize();
this->touchMovedRocker(point);
}else{
point.normalize();
Vec2 rPoint = point * m_rockerBG->getContentSize().width/2;
m_rocker->setPosition(rPoint);
this->touchMovedRocker(point);
}
}
}
void Rocker::touchesEnded(const std::vector<Touch *> &touches, cocos2d::Event *event){
m_rocker->stopAllActions();
m_rocker->runAction(MoveTo::create(0.1f, Vec2(0.0f, 0.0f)));

this->touchEndedRocker(Vec2(0.0f, <
e883
span class="hljs-number">0.0f));
}

bool Rocker::isTouchInside(Touch* touch){
Vec2 point = m_rockerBG->convertToNodeSpace(touch->getLocation());
Rect rect(0.f,0.f,m_rockerBG->getContentSize().width,m_rockerBG->getContentSize().height);
return rect.containsPoint(point);
}

void Rocker::touchBeganRocker(const Vec2& normalize){
if (m_rockerDelegate) {
m_rockerDelegate->rockerTouchBegan(this, normalize);
}
}
void Rocker::touchMovedRocker(const Vec2& normalize){
if (m_rockerDelegate) {
m_rockerDelegate->rockerTouchMoved(this, normalize);
}
}
void Rocker::touchEndedRocker(const Vec2& normalize){
if (m_rockerDelegate) {
m_rockerDelegate->rockerTouchEnded(this, normalize);
}
}


2.角色类

//
//  Role.hpp
//  Rocker
//
//  Created by Forest on 16/7/11.
//
//

#ifndef Role_hpp
#define Role_hpp

#include <stdio.h>

#include "cocos2d.h"
USING_NS_CC;

#define ROLE_SPEED 5

class Role : public Node {

Role();
~Role();

Animation* createAnimate(const char* frameName,const int frameCount,const float delay = 0.1);

Sprite* m_role;
Vec2 m_movePoint;

public:

enum class Dir {RIGHT , LEFT};
enum class Statue {IDLE , WALK};

CC_SYNTHESIZE(Dir, m_dir, Dir);
CC_SYNTHESIZE(Statue, m_status, Statue);

void roleWalk(const Vec2& normalize);
void roleIdle();
void onEnter();
void onExit();

bool init();
CREATE_FUNC(Role);
};

#endif /* Role_hpp */


//
//  Role.cpp
//  Rocker
//
//  Created by Forest on 16/7/11.
//
//

#include "Role.hpp"

Role::Role(){
}

Role::~Role(){
}

void Role::onEnter(){
Node::onEnter();
}

void Role::onExit(){
SpriteFrameCache::getInstance()->removeSpriteFramesFromFile("walk.plist");
SpriteFrameCache::getInstance()->removeSpriteFramesFromFile("idle.plist");

AnimationCache::getInstance()->removeAnimation("walk");
AnimationCache::getInstance()->removeAnimation("idle");

this->unschedule("ROLE_WALK");

Node::onExit();
}

bool Role::init(){
if (!Node::init()) {
return false;
}

SpriteFrameCache::getInstance()->addSpriteFramesWithFile("walk.plist");
SpriteFrameCache::getInstance()->addSpriteFramesWithFile("idle.plist");
// walk
AnimationCache::getInstance()->addAnimation(this->createAnimate("swk_move_%02d.png", 18, 0.05), "walk");
// idle
AnimationCache::getInstance()->addAnimation(this->createAnimate("swk_idle_%02d.png", 24), "idle");

m_role = Sprite::create();
this->addChild(m_role);
this->roleIdle();

Size visibleSize = Director::getInstance()->getWinSize();

this->schedule([=](float d){
if (m_status == Statue::WALK) {
this->setPosition(this->getPosition() + m_movePoint);

if (this->getPosition().x + m_role->getContentSize().width/2 >= visibleSize.width) {
this->setPositionX(visibleSize.width - m_role->getContentSize().width/2);
}
if (this->getPositionX() - m_role->getContentSize().width/2 <= 0) {
this->setPositionX(m_role->getContentSize().width/2);
}
}
}, 0.03, "ROLE_WALK");

return true;
}

Animation* Role::createAnimate(const char* frameName, const int frameCount,const float delay){
Animation* animation = Animation::create();

for (int i = 1; i <= frameCount ; i++) {
std::string name = StringUtils::format(frameName,i);

SpriteFrame* frame = SpriteFrameCache::getInstance()->getSpriteFrameByName(name);
animation->addSpriteFrame(frame);
}
animation->setDelayPerUnit(delay);
animation->setLoops(-1);
return animation;
}

void Role::roleWalk(const Vec2& normalize){
if (this->getStatue() != Statue::WALK){
this->setStatue(Statue::WALK);
m_role->stopAllActions();
m_role->runAction(Animate::create(AnimationCache::getInstance()->getAnimation("walk")));
}
if (normalize.x >= 0) {
this->setDir(Dir::RIGHT);
m_role->setScaleX(1);
}else{
this->setDir(Dir::LEFT);
m_role->setScaleX(-1);
}
m_movePoint = normalize * ROLE_SPEED ;
}

void Role::roleIdle(){
this->setStatue(Statue::IDLE);
m_role->stopAllActions();
m_role->runAction(Animate::create(AnimationCache::getInstance()->getAnimation("idle")));
}


3.在场景中使用摇杆

#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__

#include "cocos2d.h"
#include "Role.hpp"
#include "Rocker.hpp"

class HelloWorld : public cocos2d::Layer , public RockerDelegate
{
public:
// there's no 'id' in cpp, so we recommend returning the class instance pointer
static cocos2d::Scene* createScene();

// Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
virtual bool init();

// implement the "static create()" method manually
CREATE_FUNC(HelloWorld);

void rockerTouchBegan(Rocker* rocker,const Vec2& normalize) ;
void rockerTouchMoved(Rocker* rocker,const Vec2& normalize) ;
void rockerTouchEnded(Rocker* rocker,const Vec2& normalize) ;
private:
Role* m_role;
};

#endif // __HELLOWORLD_SCENE_H__


#include "HelloWorldScene.h"

USING_NS_CC;

Scene* HelloWorld::createScene()
{
// 'scene' is an autorelease object
auto scene = Scene::create();

// 'layer' is an autorelease object
auto layer = HelloWorld::create();

// add layer as a child to scene
scene->addChild(layer);

// return the scene
return scene;
}

// on "init" you need to initialize your instance
bool HelloWorld::init()
{
//////////////////////////////
// 1. super init first
if ( !Layer::init() )
{
return false;
}
Size visibleSize = Director::getInstance()->getWinSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();

auto sp = Sprite::create("HelloWorld.png");
this->addChild(sp);
sp->setPosition(origin.x+visibleSize.width/2,origin.y+visibleSize.height/2);

m_role = Role::create();
this->addChild(m_role);
m_role->setPosition(300,300);

Rocker* rocker = Rocker::createRocker("rocker.png", "rockerBG.png");
this->addChild(rocker);
rocker->setPosition(100,200);
rocker->setRockerDelegate(this);

return true;
}

void HelloWorld::rockerTouchBegan(Rocker *rocker, const Vec2& normalize){
m_role->roleWalk(normalize);
}
void HelloWorld::rockerTouchMoved(Rocker *rocker, const Vec2& normalize){
m_role->roleWalk(normalize);
}
void HelloWorld::rockerTouchEnded(Rocker *rocker, const Vec2& normalize){
m_role->roleIdle();
}


运行效果:







内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: