cocos2d-x类似Temple Run 游戏恢复的321倒计时实现

本文为firedragonpzy原创,转载务必在明显处注明:
转载自【Softeware MyZone】原文链接: 
http://www.firedragonpzy.com.cn/index.php/archives/3467

近期的游戏中,需要有个类似Temple Run游戏中倒计时,出现3、2、1,然后开始游戏。至于为什么有这样的需求,你懂得……

尝试了好多方法,例如动作,时刻表等等,可是都不行,push场景也行不通,要是push场景了,做这个就没什么意义了,除非做成透明。

大体就是这样子的经历,现在说下解决方案:

在CCDirector中有个getScheduler()得到时刻表【调度者】,我们可以使用时刻表【调度者】CCScheduler,来暂停所有的调度。在CCScheduler暂停所有的调度是这样子的:

CCScheduler.h

?
1
2
3
4
5
6
7
8
9
/** Pause all selectors from all targets.
 
You should NEVER call this method, unless you know what you are doing.//提示我们不应该调用此方法,但是目前我测试中没有出现什么问题
 
@since v2.0.0
 
*/
 
CCSet* pauseAllTargets();

CCSchedule.cpp

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
CCSet* CCScheduler::pauseAllTargets()
 
{
 
return pauseAllTargetsWithMinPriority(kCCPrioritySystem);
 
}
 
CCSet* CCScheduler::pauseAllTargetsWithMinPriority( int nMinPriority)
 
{
 
CCSet* idsWithSelectors = new CCSet(); // setWithCapacity:50];
 
idsWithSelectors->autorelease();
 
// Custom Selectors
 
for (tHashSelectorEntry *element = m_pHashForSelectors; element != NULL;
 
element = (tHashSelectorEntry*)element->hh.next)
 
{
 
element->paused = true ;
 
idsWithSelectors->addObject(element->target);
 
}
 
// Updates selectors
 
tListEntry *entry, *tmp;
 
if (nMinPriority < 0) { DL_FOREACH_SAFE( m_pUpdatesNegList, entry, tmp ) { if (entry->priority >= nMinPriority)
 
{
 
entry->paused = true ;
 
idsWithSelectors->addObject(entry->target);
 
}
 
}
 
}
 
if (nMinPriority paused = true ;
 
idsWithSelectors->addObject(entry->target);
 
}
 
}
 
DL_FOREACH_SAFE( m_pUpdatesPosList, entry, tmp )
 
{
 
if (entry->priority >= nMinPriority)
 
{
 
entry->paused = true ;
 
idsWithSelectors->addObject(entry->target);
 
}
 
}
 
return idsWithSelectors;
 
}

暂停之后,我们再次执行的时候需要恢复,方法如下:

CCScheduler.h

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/** Resumes the target.
 
The 'target' will be unpaused, so all schedule selectors/update will be 'ticked' again.
 
If the target is not present, nothing happens.
 
@since v0.99.3
 
*/
 
void resumeTarget(CCObject *pTarget);
 
/** Resume selectors on a set of targets.
 
This can be useful for undoing a call to pauseAllSelectors.
 
@since v2.0.0
 
*/
 
void resumeTargets(CCSet* targetsToResume);

CCScheduler.cpp

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
void CCScheduler::resumeTarget(CCObject *pTarget)
 
{
 
CCAssert(pTarget != NULL, "" );
 
// custom selectors
 
tHashSelectorEntry *pElement = NULL;
 
HASH_FIND_INT(m_pHashForSelectors, &pTarget, pElement);
 
if (pElement)
 
{
 
pElement->paused = false ;
 
}
 
// update selector
 
tHashUpdateEntry *pElementUpdate = NULL;
 
HASH_FIND_INT(m_pHashForUpdates, &pTarget, pElementUpdate);
 
if (pElementUpdate)
 
{
 
CCAssert(pElementUpdate->entry != NULL, "" );
 
pElementUpdate->entry->paused = false ;
 
}
 
}
 
void CCScheduler::resumeTargets(CCSet* pTargetsToResume)
 
{
 
CCSetIterator iter;
 
for (iter = pTargetsToResume->begin(); iter != pTargetsToResume->end(); ++iter)
 
{
 
resumeTarget(*iter);
 
}
 
}

在看完源码之后,来说下实际运用:

点击暂停按钮:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
void MainGameScene::pauseMenuCallBack( CCObject *pSender )
 
{
 
FDDialogLayer *dialogLayer = FDDialogLayer::create(DIALOG_GAME_PAUSE);
 
_m_pBeforeTargetSets = CCDirector::sharedDirector()->getScheduler()->pauseAllTargets(); //这是关键1
 
_m_pBeforeTargetSets->retain(); //这是关键2
 
this ->addChild(dialogLayer,500,500);
 
}

点击恢复按钮:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
} else if (m_pDialogSpecies == DIALOG_GAME_FORGROUND)
 
{
 
timeFlag = 1; //这是关键3,此tag用于图片切换
 
timeSprite = CCSprite::create(RESUME_FIR);
 
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
 
timeSprite->setPosition(ccp(winSize.width/2,winSize.height/2));
 
this ->addChild(timeSprite);
 
if (timeSprite) {
 
this ->schedule(schedule_selector(FDDialogLayer::updateTime),1); //这是关键4 调度
 
}
 
}
 
void FDDialogLayer::updateTime( float dt)
 
{
 
if (timeFlag < 3) { timeFlag++; char temp[32]; sprintf (temp, "resume/t%d.png" ,timeFlag); CCTexture2D *texture = CCTextureCache::sharedTextureCache()->addImage(temp);
 
CCSize conSize = texture->getContentSize();
 
timeSprite->setTexture(texture);
 
timeSprite->setTextureRect(CCRectMake(0, 0, conSize.width, conSize.height));
 
} else
 
{
 
continueGame(); //这是关键5 返回场景
 
this ->unschedule(schedule_selector(FDDialogLayer::updateTime));
 
}
 
}
 
void FDDialogLayer::continueGame()
 
{
 
MainGameScene *mainGame = (MainGameScene*)CCDirector::sharedDirector()->getRunningScene()->getChildren()->objectAtIndex(0);
 
CCSet *set = mainGame->getBeforeTargetSets(); //这是关键6,这是暂停所有调度者时的返回值
 
CCDirector::sharedDirector()->getScheduler()->resumeTargets(set); //这是关键7 恢复游戏
 
this ->removeFromParentAndCleanup( true );
 
CCTextureCache::sharedTextureCache()->removeTextureForKey(RESUME_FIR);
 
CCTextureCache::sharedTextureCache()->removeTextureForKey(RESUME_SEC);
 
CCTextureCache::sharedTextureCache()->removeTextureForKey(RESUME_TIR);
 
}

好嘞,大体就这样子,感兴趣的朋友可以尝试下……

补充:还有一种方法就是调用节点的ONEXIT()/ONENTER(),这个大家可以尝试下……

2013、06、25 经测试,可用……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值