本文为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 经测试,可用……