游戏的基本元素
CCDirector 控制游戏流程的主要组件
bool AppDelegate::applicationDidFinishLaunching() { //初始化导演类 CCDirector *pDirector = CCDirector::sharedDircor(); pDirector->setOpenGLView(&CCEGLView::sharedOpenGLView); //高分辨率屏幕的资源管理 pDirector->enableRetinaDisplay(this); //启用FPS显示 pDirector->setDisplayStats(true); //设置FPS上限。如果不加设置,则默认FPS上限为60 pDirector->setAnimationInterval(1.0/60); //创建一个场景,场景是一个autorelease对象 CCScene *pScene = HelloWorld::scene(); //运行场景 pDirector->runWithScene(pScene); return true; }
游戏呈现方面的设定,包括设定游戏呈现的窗口,FPS显示,默认帧率上限,纹理颜色位宽等。
切换当前的游戏场景,暂停或恢复游戏场景的运行。
总之,游戏在CCDirector的管理下完成了呈现设定与流程控制。
管理场景的方法:
runWithScene(CCScene *scene):启动游戏,并运行scene场景。
replaceScene(CCScene *scene):直接传入scene并替换场景
pushScene(CCScene *scene):将当前场景暂停并压入到代执行场景栈中,再将传入的scene设置为当前运行场景。
popScene:释放当前场景,再从代执行场景栈中弹出栈顶的场景,并设置为当前场景。
pause:暂停
resume:恢复,与pause配合使用
end:结束场景,退出
CCScene 场景
CCLayer 层
1、作为容器
向场景中添加层
void addChild(CCNode* child);
void addChild(CCNode* child, int zOrder);
void addChild(CCNode* child, int zOrder, int tag);
2、接受用户输入事件
CCSprite 精灵
创建精灵:
CCSPrite* fish = CCSprite::create("fish.png");
CCSprite* smallFish = CCSPrite::create("fish.png",CCRectMake(0,0,100,100));
设置精灵的属性:
创建精灵后,需要考虑精灵的位置,方向,缩放比例等参数。
例如:
获取屏幕大小,然后根据屏幕大小把精灵至于屏幕中央:
CCSize size = CCDirector::sharedDirector()->getWinSize();
CCPoint pos = ccp(size.width/2, size.height/2);
fish->setPositon(pos);
向层中添加精灵: 实际上CCSprite 与 CCLayer 继承自CCNode
详看层添加
CCSprite常用的成员
1、初始化方法
使用图片文件
static CCSprite* create(const char *pszFileName);
static CCSprite* create(const char *pszFileName, const CCRect& rect);
bool initWithFile(const char *pszFilename);
bool initWithFile(const char *pszFilename, const CCRect& rect);
使用CCTexture2D纹理创建精灵
static CCSprite* create(CCTexture2D *pTexture);
static CCSprite* create(CCTexture2D *pTexture, const CCRect& rect);
bool initWithTexture(CCTexture2D *pTexture);
bool initWithTexture(CCTexture2D *pTexture, const CCRect& rect);
使用CCSpriteFrame精灵框帧创建精灵
static CCSprite* create(CCSpriteFrame *pSpriteFrame);
bool initWithSpriteFrame(CCSpriteFrame *pSpriteFrame);
纹理相关的属性
CCTexture2D* Texture:获取或设置精灵所用的纹理
CCRect TextureRect:获取或设置纹理显示部分
CCSpriteBatchNode* BatchNode:获取或设置精灵所属的批节点
纹理相关的方法
void setDisplayFrame(CCSpriteFrame *pNewFrame):设置显示中的纹理框帧
CCSpriteFrame* displayFrame:获取正在显示的纹理框帧
bool isFrameDisplayed(CCSpriteFrame *pFrame):返回一个值,表示pFrame是否正在显示中的纹理框帧
颜色相关的属性
ccColor3 Color:获取或设置叠加在精灵上的颜色
GLubyte Opacity:获取或设置精灵的不透明度
bool OpacityModifyRGB:获取或设置精灵所使用的纹理数据是否已经预乘Alpha通道
CCNode 与 坐标系
CCNode 定义了一个可绘制对象的通用特性,包括位置、缩放、是否可见、旋转角度等。节点的最基本的功能包括:
1、包括其他CCNode对象
2、接受各种事件与回调函数,如定时器事件
3、运行动作
Cocos2d-x中存在两种坐标系
1、绘图坐标系 左下角为原点 向右为x轴正方形 向上为y轴正方向
2、纹理坐标系 左上角为原点 向右为x轴正方形 向下为y轴正方向
绘图属性
CCRect ContentSize:获取或设置此节点的内容大小
CCPoint AnchorPoint 与 CCPoint Position:AnchorPoint用于设置一个锚点,以便精确地控制节点的位置和变换
float Scale(float ScaleX 与 float ScaleY):Scale 用于获取或设置节点的缩放比例。节点以锚点为中心缩放该比例
bool Visible:获取或设置节点的可见性
bool isVisible();
void setVisible(bool visible);
float SkewX 与 float SkewY:获取或设置斜切角度。节点以锚点为中心,平行x轴或y轴方向作一定角度的变形。 单位为角度 SkewX 与 SkewY 的默认值为0,表示节点没有斜切变形
int Tag:获取或设置节点的标号
void* UserData:获取或设置与节点相关的额外信息
定时器事件
1、update定时器 刷新事件 CCNode默认并没有启动update事件,为了启动定时器,我们需要调用sceduleUpdate方法,并重载update以执行自己的代码。对应地,我们可以使用unscheduleUpdate方法停止定时器。
2、schedule定时器 实现以一定的时间间隔连续调用某个函数。时间间隔必须大于两帧的间隔,否则两帧期间的多次调用回被合并成为一次调用。所有schedule定时器通常用在间隔较长的定时调用中,一般来说,时间间隔应在0.1秒以上。
例如:
this->schedule(schedule_selector(GameScene::updateGame)); void GameScene::updateGame(ccTime dt) { SPriteLayer* sLayer = (SpriteLayer*)this->getChildByTag(sprite_layer_tag); sLayer->updateFishMovement(dt); sLayer->checkBulletCollideWithFish(); }
定时器机制是Cocos2d-x调度机制的基础。Cocos2d-x的调度是纯粹的串行机制,因此所有函数都运行在同一个线程,不会存在并行程序的种种麻烦,这大大简化了编程的复杂性。
例如:
void GameScene::onEnter() { CCScene::onEnter(); this->playBackgroundMusic(); }
Cocos2d-x内置的常用层
1、CCLayerColor:一个单纯的实心色块
2、CCLayerGradient:一个色块,但可以设置两种颜色的渐变效果
3、CCMenu:十分常用的游戏菜单
菜单由两部分组成,分别是菜单项和菜单本身。 CCMenuItem表示一个菜单项,每个菜单项都是一个独立的按钮,定义了菜单的视觉表现和响应动作;CCMenu则是菜单,它负责将菜单项组织到一起并添加到场景中,转换屏幕的触摸事件到各个菜单项。
CCMenuItemImage::create( "CloseNormal.png",//普通状态下的图片 "CloseSelected.png",//按下状态下的图片 this, //响应对象 menu_selector(HelloWorld::menuCloseCallback)); //响应函数
其中响应函数必须满足SEL——MenuHandler形式:返回值为空,带一个CCNode* 型的参数
创建一个菜单,在菜单中添加一个菜单项供用户点击,再把菜单添加到场景中。
bool StartScene::init() { bool bRet = false; do{ CC_BREAK_IF(!CCScene::init()); CCSize winSize = CCDirector::sharedDirector()->getWinSize(); CCMenuItem *startGameItem = CCMenuItemFont:: create("Start", this, menu_selector(StartScene::startGame)); CC_BREAK_IF(!startGameItem); startGameItem->setPosition(ccp(winSize.width/2 , winSize.height/2)); CCMenu* menu = CCMenu::create(startGameItem, NULL); CC_BREAK_IF(!menu); menu->setPosition(CCPointZero); this->addChild(menu); bRet = true; }while(0); return bRect; }
响应函数里添加场景切换
void StartScene::startGame(CCNode *sender) { CCDirector::sharedDirector()->replaceScene(CCTransitionShrinkGrow::create(1.2f, GameScene::node)); }
游戏暂停
void GmaeMenuLayer::pauseGame(CCObject* sender) { CCDirector::sharedDirector()->pause(); resumeGameItem->setIsVisible(true); pauseGameItem->setIsVisible(false); }
游戏恢复
void GmaeMenuLayer::resumeGame(CCObject* sender) { CCDirector::sharedDirector()->resume(); resumeGameItem->setIsVisible(false); pauseGameItem->setIsVisible(true); }
Cocos2d-x调度原理
1、游戏主循环
游戏乃至图形界面的本质是不断地绘图,但并不是随意的,任何游戏都需要遵循一定的规则。游戏不断地重复以下动作:处理用户输入 处理定时事件 绘图
CCDirector::mainLoop()方法,负责调用定时器,绘图,发送全局通知,并处理内存回收池。该方法按帧调用,每帧调用一次,而帧间间隔取决于两个元素,一个是预设的帧率,默认为60帧每秒,另一个是每帧的计算量大小。当逻辑处理与绘图计算量过大时,设备无法完成每秒60次绘制,此时帧率就会降低。
void CCDisplayLinkDirector::mainLoop() { //判断是否需要释放CCDirector 如果需要,则删除CCDirector占用的资源。通常游戏结束的时候才会执行这步 if(m_bPurgeDirectorInNextLoop) { m_bPurgeDirectorInNextLoop = false; purgeDirector(); } else if(!m_bInvalid) { //绘制当前场景并进行其他必要的处理 drawScene(); //释放对象 CCPollManager::sharedPoolManager->pop(); } }
void CCDirector::drawScene() { //计算全局帧间时间差dt calculateDeltaTime(); if(!m_bPaused) { //调用定时调度器的update方法,引发定时器事件 m_pScheduler->update(m_fDeltaTime); } glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); if(m_pNextScene) { //如果场景需要被切换,调用setNextStage方法,在显示场景前切换场景 setNextScene(); } kmGLPushMatrix(); //绘制场景 if(m_pRunningScene) { m_pRunningScene->visit(); } //处理通知节点 if(m_pNotificationNode) { //调用当前场景的visit方法,绘制当前场景 m_pNotificationNode->visit(); } if(m_bDisplayStats) { showStats(); } if(m_pWatcherFun && m_pWatcherSender) { (*m_pWatcherFun)(m_pWatcherSender); } kmGLPopMatrix(); m_uTotalFrames++; //交换缓存区 if(m_pobOpenGLView) { m_pobOpenGLView->swapBuffers(); } if(m_bDisplayStats) { calculateMPF(); } }
2、定时调度器
在游戏主循环drawScene方法中,我们可以看到每一帧引擎都会调用m_pScheduler的update方法
m_pScheduler是CCScheduler类型的对象,是一个定时调度器。所谓定时调度器,就是一个管理所有节点定时器的对象,它负责记录定时器,并在合适的时间触发定时事件。
复习一下两种定时器,分别是
1、update定时器,每一帧都被出发,使用scheduleUpdate 方法来启用
2、schedule定时器,可以设置触发的间隔,使用schedule方法来启用
代码:
void CCNode::scheduleUpdateWithPriority(int priority) { m_pScheduler->scheduleUpdateForTarget(this, priority, !m_bIsRunning); }
void CCNode::schedule(SEL_SCHEDULE selector, float interval, unsigned int repeat, float delay) { CCAssert(selector, "Argument must be non-nil"); CCAssert(interval >= 0, "Argument must be positive"); m_pScheduler->scheduleSelector(selector, this, interval, !m_bIsRunning, repeat, delay); }
事件驱动的普通定时器调用顺序为:系统的时间事件驱动游戏主循环,游戏主循环调用CCScheduler的update方法,CCScheduler调用普通定时器对应的CCTimer对象的update方法,CCTimer类的update方法调用定时器对应的回调函数。
第三章总结
游戏中最基础的3种元素-----场景,层和精灵。
CCDirector:控制游戏流程的总管类,提供绘图方面的选项以及平台相关的功能
CCScene:场景的实现类,是层的容器
CCLayer:层的实现类,是精灵的容器。层还可以用来接收用户输入,例如触摸事件和加速度计事件
CCSprite:精灵的实现类,显示一个静态或动态的图形。图形在引擎中以纹理的形式存在,精灵不仅能显示完整的纹理,也可以显示部分纹理
CCNode:一切游戏元素的根类,也是构成渲染树的节点。它提供了基本的绘图属性,可以作为其他节点的容器,提供定时器的功能,可以执行动作
CCMenu:特殊的层,封装了游戏中常用的菜单功能
定时器:分为update定时器与schedule定时器,前者每一帧触发一次,而后者可以指定触发间隔。定时器由定时调度器控制,每个定时器互不干扰,串行执行。
第四章----动作
基本概念
CCAction是动作类的基类,所有的动作都派生自这个类,它创建的一个对象代表了一个动作。动作作用于CCNode,因此,任何一个动作都需要由CCNode对象来执行。
CCSprite* sprite = CCSprite::create("fish.png"); CCAction* action = CCMoveTo::create(1.0f, ccp(0, 0)); sprite->runAction(action);
值得注意的是,一个CCAction只能使用一次,这是因为动作对象不仅描述了动作,还保存了这个动作持续过程中不断改变的一些中间参数。对于需要反复使用的动作对象,可以通过copy方法复制使用。
CCAction作为一个基类,其实质是一个接口,由它派生的实现类才是我们实际使用的动作。CCAction的绝大多数实现类都派生自CCFiniteTimeAction,这个类定义了在有限时间内可以完成的动作。CCFiniteTimeAction定义了reverse方法,通过这个方法获得一个与原动作相反的动作。
由CCFiniteTimeAction派生出的两个主要类分别是瞬时动作和持续性动作。
瞬时动作:指能立刻完成的动作,是CCFiniteTimeAction中动作持续时间为0的特例。
常用的瞬时动作:
1、CCPlace
2、CCFlipX 和 CCFlipY
3、CCShow 和 CCHide
4、CCCallFunc系列包括CCCallFunc CCCallFuncN CCCallFuncND CCCallFuncO 四个动作
持续性动作:在持续的一段时间里逐渐完成的动作
每一种持续性动作通常都存在两个不同的变种动作,分别具有To和By后缀:后缀为To的动作描述了节点属性值得绝对变化,而后缀为By的动作则描述了属性值相对的变化
持续性动作分为4大类:
位置变化动作
属性变化动作
视觉特效动作
控制动作
位置变化动作
CCMoveTo 和 CCMoveBy:用于使节点做直线运动
初始化方法:
CCMoveTo::create(ccTime duration, CCPoint& pos);
CCMoveBy::create(ccTime duration, CCPoint& pos);
duration代表动作持续的时间
CCJumpTo 和 CCJumpBy:使节点以一定的轨迹跳跃到指定位置
初始化方法:
CCJumpTo::create(ccTime duration, CCPoint& pos, float height,int jumps);
CCJumpBy::create(ccTime duration, CCPoint& pos, float height,int jumps);
jumps表示跳跃次数
CCBezierTo 和 CCBezierBy:使节点进行曲线运动,运动的轨迹由贝塞尔曲线描述。角度决定了曲线的方向,长度控制曲线的曲率。控制箱越长,它所控制的曲线离控制线越近。
属性变化动作
CCScaleTo 和 CCScaleBy:产生缩放效果,使节点的缩放洗漱随时间线性变化。
初始化方法:
CCScaleTo::cretae(ccTime duration, float s);
CCScaleBy::create(ccTime duration, float s);
其中,s为缩放系数的最终值或变化量
CCRotateTo 和 CCRotateBy:产生旋转效果
初始化方法:
CCRotateTo::create(ccTime duration, float fDeltaAngle);
CCRotateBy::create(ccTime duration, float fDeltaAngle);
其中fDeltaAngle的单位是角度,正方向为顺时针方向
CCFadeIn 和 CCFadeOut:产生淡入淡出效果,其中前者实现了淡入效果,后者实现了淡出的效果效果
初始化方法:
CCFadeIn::create(ccTime duration);
CCFadeOunt::create(ccTime duration);
只有实现了CCRGBAProtocol接口的节点才可以执行这类动作,这是因为与透明度或颜色相关的属性都继承自CCRGBAProtocol接口。
CCFadeTo:用于设置一段时间内透明度的变化效果
初始化方法:
CCFadeTo::create(ccTime duration, Glubyte opacity);
参数中的Glubyte是8位无符号整数,因此,opacity可取0至255中的任意整数。与透明度相关的动作值能应用在精灵上,且子节点不会受到父节点的影响
CCTintTo 和 CCTintBy:设置色调变化
初始化方法:
CCTintTo::create(ccTime duration, GLubyte r, Glubyte g, Glubyte b);
CCTintBy::create(float duration, GLshort deltaRed, GLshort deltaGreen, GLshort deltaBlue);
r,g,b的取值范围0~255
视觉特效动作
CCBlink:使目标节点闪烁
初始化方法:
CCBlink::create(ccTime duration, unsigned int uBlicks);
其中,uBlicks是闪烁次数
CCAnimation:播放帧动画,用帧动画的形式实现动画效果
控制动作
动作包括CCDelayTime CCRepeat 和 CCRepeatForever
CCDelayTime 可以将动作延时一定的时间
CCRepeat 可以把现有的动作重复一定次数
CCRepeatForever 可以使一个动作不断重复下去
复合动作
1、重复
CCRepeat* CCRepeat::create(CCFiniteTimeAction *pAction, unsigned int times);
CCRepeatForever *CCRepeatForever::create(CCActionInterval *pAction);
其中pAction参数表示需要重复的动作 第一个方法允许指定动作的重复次数,第二个方法使节点一直重复该动作直到动作被停止
2、并列
CCSpawn从CCActionInterval派生而来的
两个方法:
CCSpawn::create(CCFiniteTimeAction *pAction1,...);
CCSpawn::create(CCFiniteTimeAction *pAction1, CCFinteTimeAction *pAction2);
其中第一个静态方法可以将多个动作同时并列执行,参数表中最后一个动作后需要紧跟NULL表示结束。第二个只能指定两个动作复合,不需要再最后一个动作后紧跟NULL。
3、序列
CCSequence派生自CCActionInterval
两个方法:
CCSequence::create(CCFiniteTimeAction *pAction1,...);
CCSequence::create(CCFiniteTimeAction *pAction1,CCfiniteTimeAction *pAction2);
它们的作用分别是建立多个和两个动作的顺序执行的动作序列
4、延时
CCDelayTime::create(float d);
其中仅包含一个实型参数,表示动作占用的时间
变速动作
变速动作包括CCSpeed动作 与 CCEase系列动作
CCSpeed:线性地改变某个动作的速度
创建一个animation动作的CCRepeatForever复合动作repeat,使动画被不断地重复执行
repeat动作创建一个CCSpeed变速动作。create初始化方法中的两个参数分别为目标动作与变速比率。设置变速比率为1,目标动作的速度将不会改变
speed动作设置一个tag属性,并把动作交给fish精灵,让精灵执行变速动作。
CCRepeatForever* repeat = CCRepeatForever::create(animation); CCSpeed* speed = CCSpeed::create(repeat, 1.0f); speed->setTag(action_speed_tag); fish->runAction(speed);
修改变速动作的speed属性来改变动作速度,将上面设置的动画速度变为原来的两倍
CCSpeed* speed = fish->getActionByTag(action_speed_tag);
speed->setSpeed(2.0f);
CCActionEase系列
5类动作:指数缓冲 Sine缓冲 弹性缓冲 跳跃缓冲 回震缓冲
每一类动作都有3个不同时期的变化 :In Out 和 InOut
代码实现InSine变速运动:
CCEaseSinIn* sineIn = CCEaseSineIn::create(action); sineIn->setTag(action_sine_in_tag); fish->runAction(sineIn);
创建自定义动作
CCAction包括两个重要的方法:step与update
step方法会在每一帧动作更新时触发,该方法接受一个表示调用时间间隔的参数dt,dt的积累即为动作运行的总事件。
下面编写一个继承于CCAction的CCRotateAction动作。
class RotateWithAction:public CCActionInterval { public: CCObject* copyWithZone(CCZone* pZone); ~RotateWithAction(); static RotateWithAction* create(CCActionInterval * action); virtual void startWithTarget(CCNode* pTarget); bool initWithAction(CCActionInterval* pAction); bool isDone(); void step(ccTime dt); protected: void RotateWithAction::setInnerAction(CCActionInterval* pAction); CCNode* pInnerTarget; CCActionInterval* pInnerAction; }; RotateWithAction::~RotateWithAction() { CC_CAFE_RELEASE(pInnerAction); } RotateWithAction* RotateWithAction::create(CCActionInterval* pAction) { RotateWithAction* action = new RotateWithAction(); if(action && action->initWithAction(pAction)) { action->autorelease(); return action; } CC_SAFE_DELETE(action); return NULL; } bool RotateWithAction::initWithAction(CCActionInterval* pAction) { RotateWithAction* action = new RotateWithAction(); if(action && action->initWithAction(pAction)) { action->autorelease(); return action; } CC_SAFE_DELETE(action); return NULL; } bool RotateWithAction::initWithAction(CCActionInterval* pAction) { pAction->retain(); pInnerAction = pAction; return true; } void RotateWithAction::startWithTarget(CCNode* pTarget) { pInnerTarget = pTarget; CCAction::startWithTarget(pTarget); pInnerAction->startWithTarget(pTarget); } bool RotateWithAction::isDone() { return pInnerAction->isDone(); } void RotateWithAction::step(ccTime dt) { CCPoint prePos = pInnerTarget->getPosition(); pInnerAction->step(dt); CCPoint curPos = pInnerTarget->getPosition(); float tan = -(curPos.y - prePos.y) / (curPos.x - prePos.x); float degree = atan(tan); degree = degree / 3.14159f *180; pInnerTarget->setRotation(degree); } void RotateWithAction::setInnerAction(CCActionInterval* pAction) { if(pInnerAction != pAction) { CC_SAFE_RELEASE(pInnerAction); pInnerAction = pAction; CC_SAFE_RETAIN(pInnerAction); } } CCObject* RotateWithAction::copyWithZone(CCZone* pZone) { CCZone* pNewZone = NULL; RotateWithAction* pCopy = NULL; if(pZone&& pZone->m_pCopyObject) { pCopy = (RotateWithAction*)(pZone->m_pCopyObject); } else { pCopy = new RotateWithAction(); pZone = pNewZone = new CCZone(pCopy); } CCActionInterval::copyWithZone(pZone); pCopy->initWithAction(dynamic_cast<CCActionInterval*>(pInnerAction->copy()->autorelease())); CC_SAFE_DELETE(pNewZone); return pCopy; }
菜单的弹出代码
CCSize size = CCDirector::sharedDirector()->getWinSize(); CCMenu* menu = CCMenu::create(item0,item1,item2,item3,NULL); menu->alignItemsVerticallyWithPadding(5.0f); menu->setPosition(ccp(size.width/2.0f,size.height)); menu->setTag(ment_pause_tag);
菜单的收起代码
CCSize size = CCDirector::sharedDirector()->getWinSize(); CCMenu* menu (CCMenu*)this->getChildByTag(menu_pause_tag); CCPoint point = ccp(size.width/2.0f, size.height + menu->getContentSize().height / 2.0f); menu->runAction(move);
进场动作:由快到慢,快速进入后缓慢停下,在停止前给玩家足够的视觉时间分辨清楚进入的图像
出场动作:先慢后快,展示了出场趋势和方向后快速移出屏幕,不拖泥带水
选择CCEaseExponential动作来实现减速效果
弹出菜单的代码
CCMenu* menu = CCMenu::create(item0,item1,item2,item3,NULL); menu->alignItemsVerticallyWithPadding(5.0f); menu->setPosition(ccp(size.width/2.0f,size.height)); menu->setTag(ment_pause_tag); this->addChild(menu,5); CCMoveTo* move = CCMoveTo::create(0.5f,ccp(size.width/2, size.height/2)); CCAction* action = CCEaseExponentialOut::create(move); menu->runAction(action);
收起菜单的代码
CCSize size = CCDirector::sharedDirector()->getWinSize(); CCMenu* menu (CCMenu*)this->getChildByTag(menu_pause_tag); CCPoint point = ccp(size.width/2, size.height + menu->getContentSize().height / 2); CCMoveTo* move = CCMoveTo::create(0.5f,point); CCAction* action = CCEaseExponentialIn::create(move); menu->runAction(action);
Cocos2d-x 动作原理
先看CCAction类
class CC_DLL CCAction:public CCObject { public: CCAction(void); virtual ~CCAction(void); const char* description(); virtual CCObject* copyWithZone(CCZone *pZone); virtual bool isDone(void); virtual void startWithTarget(CCNode *pTarget); virtual void stop(void); virtual void step(float dt); virtual void update(float time); inline CCNode* getTarget(void) { return m_pTarget;} inline void setTarget(CCNode *pTarget) { m_pTarget = pTarget}; inline CCNode* getOriginalTarget(void) { return m_pOriginalTarget;} inline void setOriginalTarget(CCNode *pOriginalTarget) { m_pOriginalTarget = pOriginalTarget;} inline int getTag(void) { return m_nTag;} inline void setTag(int nTag) { m_nTag = nTag;} public: CC_DEPRECATED_ATTRIBUTE static CCAction* action(); static CCAction* creat(); protected: CCNode *m_pOriginalTarget; CCNode *m_pTarget; int m_nTag; };
继承自CCAction的CCFiniteTimeAction主要新增了一个用于保存该动作总的完成时间的成员变量:ccTime m_fDuration
CCFiniteTimeAction的两个子类CCActionInstant 和 CCActionInterval ,前者没有新增任何函数和变量,而后者增加了两个成员变量------ccTime m_elapsed 和 bool m_bFirstTick。其中 m_elapsed 是从动作开始起逝去的时间,而m_bFirstTick 是一个控制变量。
第四章小结
本章主要学习了动作以及控制所有动作的动作管理器CCActionManager。对持续性动作 瞬时动作 复合动作 变速动作的基本了解。
第五章-----动画与场景特效
首先创建一个场景,称作原场景,然后把原场景当做参数来创建一个特效场景,使用时值需要把特效场景传入CCDirtector的replaceScene方法即可,相关代码如下:
CCDirector::sharedDirector()->replaceScene(CCTransitionFlipX::transitionWithDuration(2, pScene));
第五章小结
框帧:包含纹理与纹理中的一个矩形区域,表示纹理的一部分。一个精灵显示的内容就可以用框帧表示,同时框帧还是帧动画的基本元素
动画帧:由框帧与单位延时组成,可以表示变速动画的一帧。通常,匀速动画的单位延时为1
动画:由动画帧组成,表示一个动画的内容
动画动作:动画的播放器,使用动画对象创建,只能作用于精灵。为了播放一个动画,通常首先创建动画帧或框帧,然后用它们创建动画,最后利用动画创建动画动作,并指派一个精灵来执行此动作。
场景特效:一类特殊的场景,可以把另一个场景包装起来,实现诸如特殊翻页、波纹等华丽的场景切换特效
第六章-----音乐与音效
CocosDenshion音效引擎库
引入头文件 #include "SimpleAudioEngin.h"
播放音乐与音效: SimpleAudioEngine::sharedEngine();
预加载
void preloadEffect(const char* pszFilePath):用于预加载音效文件,其中pszFilePath为音效文件所在的目录位置
void preloadBackgroundMusic(const char* pszFilePath):用于预加载背景音乐,pszFilePath为音效文件所在的目录位置
播放与停止
unsigned int playEffect(const char* pszFilePath, bool bLoop = false);播放音效,bLoop参数控制是否 循环播放,默认为false,即只播放一次
例如:
SimpleAudioEngine::sharedEngine()->playEffect("coin.wav",false);
void playBackgroundMusic(const char* pszFilePath, bool bLoop = false);播放背景音乐
void stopEffect(unsigned int nSoundId);停止播放指定的音效,nSoundId参数playEffect方法的返回值
void stopAllEffects();停止播放所有音效
void stopBackgroundMusic();停止播放背景音乐
void pauseBackgroundMusic();暂停播放音乐
void pauseEffect(unsigned int nSoundId);暂停播放指定的音效
例如:
unsigned int nCoinSoundId = SimpleAudioEngine::sharedEngine()->playEffect("coin.wav", false); SimpleAudioEngine::sharedEngine()->pauseEffect(nCoinSoundId);
void pauseAllEffects();暂停所有播放中的音效
void resumeBackgroundMusic();恢复音乐播放
void resumeEffect(unsigned int nSoundId);恢复播放某一被暂停的音效
例如:
SimpleAudioEngine::sharedEngine()->resumeEffect(nCoinSoundId);
void resumeAllEffects();恢复所有被暂停的音效
void rewindBackgroundMusic();重新播放背景音乐
bool isBackgroundMusicPlaying();返回一个布尔类型的值,表示是否正在播放背景音乐
void unloadEffect(const char* pszFilePath);卸载已与载入的音效文件,以释放系统资源
float EffectsVolume属性:获取或设置音效的音量大小,其取值为0.0到1.0之间的浮点数。注意,对此属性的设置回影响到所有音效的音量大小。
float BackgroundMusicVolume属性:获取或设置背景音乐的音量大小,其取值为0.0到1.0之间的浮点数。注意,对此属性的设置回影响到所有音效的音量大小。
void end();当不再使用音频引擎时,调用此方法来释放SimpleAudioEngine所占用的资源
第六章小结
主要学习 音频引擎库CocosDenshion。CocosDenshion的核心是SimpleAudioEngine
使用 SimpleAudioEngine时,应注意以下三点:
1、播放音效或背景音乐前,一定要提前加载音效或背景音乐文件
2、在播放背景音乐时,若要切换背景,不需要手动暂停背景音乐,Cocos2d-x会自动先把前场景的背景音乐停止,并播放新场景中的背景音乐(如果新场景会播放新的背景音乐的话)。
3、在退出后且不再需要音乐时,要调用end方法来释放引擎占用的资源
第七章-----用户输入
1、触摸输入
TouchEnable属性来开启或关闭接受触摸输入
在开启层的触摸输入支持后,层便可以处理触摸事件了。
virtual void ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent);开始
virtual void ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent);移动
virtual void ccTouchesEnded(CCSet *pTouches, CCEvent *pEvent);结束
virtual void ccTouchesCancelled(CCSet *pTouches, CCEvent *pEvent);取消
为了使一个对象接受标准触摸事件,主要有以下4个步骤
1、需要此对象实现CCStandardTouchDelegate接口
2、使用addStandardDelegate方法把自己注册给触摸事件分发器
3、重载事件回调函数,处理触发事件
4、当不再需要接收触摸事件时,使用removeDelegate方法来注销触摸事件的接收
带目标的触摸事件的使用步骤:
1、实现CCTargetedTouchDelegate接口
2、使用addTargetedDelegate方法注册到触摸事件分发器
3、重载事件回调函数。注意,我们必须在触摸开始事件中针对需要接受的事情返回true以捕捉事件。
4、当不再需要接收触摸事件时,使用removeDelegate方法来注销触摸事件的接受。与标准触摸事件相比,不同之处主要在于开始触摸事件需要返回一个代表是否捕捉事件的值
触摸分发器原理
无论使用哪一种机制,最关键的一步都是把接受事件的对象注册到接触分发器中。这是因为接触分发器会利用系统的API获取触摸事件,然后把事件分发给游戏中接收触摸事件的对象。
CCTouchDispatcher中的主要成员,其中addStandardDelegate 与 addTargetedDelegate两个方法接收一系列参数,包括事件的注册者。