这一篇,我们就来谈谈关于cocos2dx中动作类相关的问题。
cocos2dx之所以成为主流的2D游戏引擎之一,离不开的是它拥有了强大的动作类。为什么这么说呢?不妨先来看看在cocos2dx3.9这一版本中它的动作类的类结构图吧(因为条件限制,所以只能显示这么大,大家可以先把它下载另存为.jpg文件,然后放大即可清楚查看):
在这张图中我们可以很清楚的看到这一个动作(Action)类的复杂之处。
好,现在就直接进入正题吧。 其实关于cocos2dx中的动作类,如果一个个讲我觉得也没什么必要。但是,至少我们要清楚它大概的轮廓或者说是关系。从图中我们可以获取得到,Action类是继承Ref类和Clonable类的。 Ref类是一个引用类型的类,它与内存管理相关,这个我们后面会谈及。而Clonable是一个可以复制的类。也就是说它的子类或是子类的子类都是可以克隆复制的。这样一来,我们便会清楚,所有的Action类都可以克隆复制的。 而这一篇,我会简单的讲讲关于它的子类相关的实例。
第一个是Follow类,它的作用是对摄像头进行目标的锁定,这样,目标一旦即将离开摄像机视野之时,那么,摄像机会锁定目标随之移动,从而达到目标保持在视野范围内。
第二个是Speed类,它主要和ActionInterval类相关(关于这个类,我们下面会谈及)。使用这个类,可以对移动的目标进行速度的调整。
第三个是FiniteTimeAction类,它又派生出了两个子类。ActionInterval类和ActionInstant类。关于这两个类,其实可以顾名思义的看出,一个是有间隔时间的动作,一个是即时的动作。所以,刚刚说的Speed类就是需要有一个有时间间隔的动作,这样才能对移动的速度进行调整。
OK,现在就来看下关于Follow和Speed这两个类吧,关于有时间的动作,后面再来选择性的进行分析,毕竟动作类很多。不过,对于上面的类的例子,我选择了一个有时间的MoveBy类进行结合。
好,话不多说,先看实现的例子效果:
以上就是关于这两个类的简单实例演示。代码如下:
RunActionTest.h:
#ifndef __RUN_ACTION_TEST_H__
#define __RUN_ACTION_TEST_H__
#include"cocos2d.h"
using namespace cocos2d;
#define winSize Director::getInstance()->getWinSize()
enum TEST_LAYER{
TEST_NONE,
TEST_ACTION_SPEED_1,
TEST_ACTION_F0LLOW_2
};
static int currentSceneIndex = 0;
class ActionSpeedTestLayer : public Layer {
public:
const std::string title(){ return "ActionSpeedTestLayer Test"; }
virtual bool init();
CREATE_FUNC(ActionSpeedTestLayer);
};
class ActionFollowTestLayer : public Layer {
public:
const std::string title(){ return "ActionFollowTestLayer Test"; }
virtual bool init();
CREATE_FUNC(ActionFollowTestLayer);
};
class ActionScene :public Scene{
public:
virtual bool init();
CREATE_FUNC(ActionScene);
virtual void restartCallback(Ref *sender);
virtual void nextCallback(Ref *sender);
virtual void priorCallback(Ref *sender);
protected:
MenuItemImage *priorItem, *restartItem, *nextItem;
};
#endif
RunActionTest.cpp:
#include"RunActionTest.h"
bool ActionSpeedTestLayer::init(){
if (!Layer::init()){
return false;
}
//Add title
auto title = Label::createWithSystemFont(this->title(), "", 25);
this->addChild(title);
title->setPosition(Vec2(
winSize.width / 2,
winSize.height - title->getContentSize().height / 2));
//Set current scene index
currentSceneIndex = 1;
//Action
auto actionSpeed1 = Speed::create(MoveBy::create(5.0f, Vec3(300, 0, 0)), 0.5f);
auto actionSpeed2 = Speed::create(MoveBy::create(5.0f, Vec3(300, 0, 0)), 1.0f);
auto actionSpeed3 = Speed::create(MoveBy::create(5.0f, Vec3(300, 0, 0)), 1.5f);
//Icon sprite
auto IconSprite1 = Sprite::create("Icon.png");
IconSprite1->setPosition(Vec2(IconSprite1->getContentSize().width/2, winSize.height * 3 / 4));
addChild(IconSprite1);
IconSprite1->runAction(actionSpeed1);
auto IconSprite2 = Sprite::create("Icon.png");
IconSprite2->setPosition(Vec2(IconSprite1->getContentSize().width / 2, winSize.height * 1 / 2));
addChild(IconSprite2);
IconSprite2->runAction(actionSpeed2);
auto IconSprite3 = Sprite::create("Icon.png");
IconSprite3->setPosition(Vec2(IconSprite1->getContentSize().width / 2, winSize.height * 1 / 4));
addChild(IconSprite3);
IconSprite3->runAction(actionSpeed3);
return true;
}
bool ActionFollowTestLayer::init(){
if (!Layer::init()){
return false;
}
//Add title
auto title = Label::createWithSystemFont(this->title(), "", 25);
this->addChild(title);
title->setPosition(Vec2(
winSize.width / 2,
winSize.height - title->getContentSize().height / 2));
//Set current scene index
currentSceneIndex = 2;
//Draw Line
auto drawNode = DrawNode::create();
drawNode->drawLine(Vec2(0, winSize.height / 2), Vec2(winSize.width * 2, winSize.height / 2), Color4F::RED);
drawNode->drawLine(Vec2(0, winSize.height), Vec2(winSize.width * 2, winSize.height), Color4F::RED);
drawNode->drawLine(Vec2(winSize.width / 2, 0), Vec2(winSize.width / 2, winSize.height * 2), Color4F::RED);
drawNode->drawLine(Vec2(winSize.width, 0), Vec2(winSize.width, winSize.height * 2), Color4F::RED);
this->addChild(drawNode);
//Icon sprite
auto IconSprite = Sprite::create("Icon.png");
IconSprite->setPosition(Vec2::ZERO);
addChild(IconSprite);
IconSprite->runAction(MoveBy::create(2.0f,Vec3(winSize.width,winSize.height,0)));
this->runAction(Follow::create(IconSprite, Rect(0, 0, winSize.width * 2, winSize.height * 2)));
return true;
}
bool ActionScene::init(){
if (!Scene::init()){
return false;
}
//Set current search path for resource
FileUtils::getInstance()->addSearchPath("RunctionRes/");
priorItem = MenuItemImage::create("p1.png", "p2.png",
CC_CALLBACK_1(ActionScene::priorCallback, this));
priorItem->setPosition(Vec2(
-winSize.width / 2 + priorItem->getContentSize().width/2,
-winSize.height / 2 + priorItem->getContentSize().height / 2));
nextItem = MenuItemImage::create("n1.png", "n2.png",
CC_CALLBACK_1(ActionScene::nextCallback, this));
nextItem->setPosition(Vec2(
winSize.width / 2 - priorItem->getContentSize().width / 2,
-winSize.height / 2 + priorItem->getContentSize().height / 2));
restartItem = MenuItemImage::create("r1.png", "r2.png",
CC_CALLBACK_1(ActionScene::restartCallback, this));
restartItem->setPosition(Vec2(
0,-winSize.height / 2 + priorItem->getContentSize().height / 2));
auto menu = Menu::create(priorItem, nextItem, restartItem,NULL);
this->addChild(menu);
auto test_for_speed_layer = ActionSpeedTestLayer::create();
this->addChild(test_for_speed_layer);
test_for_speed_layer->setTag(TEST_ACTION_SPEED_1);
return true;
}
void ActionScene::restartCallback(Ref *sender){
switch (currentSceneIndex){
case 1:
if (this->getChildByTag(TEST_ACTION_SPEED_1)){
this->removeChildByTag(TEST_ACTION_SPEED_1);
auto test_for_speed_layer = ActionSpeedTestLayer::create();
this->addChild(test_for_speed_layer);
test_for_speed_layer->setTag(TEST_ACTION_SPEED_1);
}
break;
case 2:
if (this->getChildByTag(TEST_ACTION_F0LLOW_2)){
this->removeChildByTag(TEST_ACTION_F0LLOW_2);
auto test_for_follow_layer = ActionFollowTestLayer::create();
this->addChild(test_for_follow_layer);
test_for_follow_layer->setTag(TEST_ACTION_F0LLOW_2);
}
break;
default:
break;
}
}
void ActionScene::nextCallback(Ref *sender){
switch (currentSceneIndex){
case 1:
if (this->getChildByTag(TEST_ACTION_SPEED_1)){
this->removeChildByTag(TEST_ACTION_SPEED_1);
auto test_for_follow_layer = ActionFollowTestLayer::create();
this->addChild(test_for_follow_layer);
test_for_follow_layer->setTag(TEST_ACTION_F0LLOW_2);
}
break;
default:
break;
}
}
void ActionScene::priorCallback(Ref *sender){
switch (currentSceneIndex){
case 2:
if (this->getChildByTag(TEST_ACTION_F0LLOW_2)){
this->removeChildByTag(TEST_ACTION_F0LLOW_2);
auto test_for_speed_layer = ActionSpeedTestLayer::create();
this->addChild(test_for_speed_layer);
test_for_speed_layer->setTag(TEST_ACTION_SPEED_1);
}
break;
default:
break;
}
}
好了,具体的就不再分析了。相信大家都能够看得明白,如果有错误或是不懂得可以指出哦~