我们首先来分析下如何增加暂停键。
1.思路是:首先我们需要定义一个 暂定的图层,上面add了 继续游戏,重新开始游戏的label 并注入相应的触发方法。
如果点击继续游戏,则触发[[CCDirector sharedDirector] resume]; 事件,如果重新开始游戏,则触发 [[CCDirector sharedDirector] resume]; 事件。
2如何实现呢?我们可以写一个代理方法。
代理方法名字和声明方法如下:
@protocol PauseLayerProtocol <NSObject>
@required
-(void) didRecieveResumeEvent:(PauseLayer*)layer;
-(void) didRecieveRestartEvent:(PauseLayer*)layer;
@end
这两个方法又想实现呢?只要是控制我们的暂停层的添加还是移除。
1)我们首先在mainLayer中添加了一个暂停的MenuItem,并添加了方法
init方法中的局部代码如下:
//22.添加暂停按钮和暂停画面
CCMenuItem *pauseItem = [CCMenuItemFont itemWithString:@"暂停"
block:^(id sender){
//add pause layer
PauseLayer *pl = [PauseLayer node];
//生成暂停图层
pl.position = CGPointZero;
[self addChild:pl z:100];
pl.delegate = self; //设置图层的代理方法
//pause game logic & animation
[[CCDirector sharedDirector] pause];//进行暂停
_isGamePause = YES;
}];
pauseItem.position = ccp(winSize.width - 60,winSize.height - 100);
CCMenu *menu = [CCMenu menuWithItems:pauseItem, nil];
menu.position = CGPointZero;
[self addChild:menu z:10]; //显示暂停Menu的菜单,点击menu中得暂停得时候触发停止响应
_isGamePause = NO;
2)大家要注意到 pl.delegate = self这个方法
下面的代码实现了 pauseLayerprotocol这个协议。
@interface HelloWorldLayer : CCLayer<PauseLayerProtocol>
#pragma mark - pauseLayer protocol
-(void) didRecieveResumeEvent:(PauseLayer *)layer{
[[CCDirector sharedDirector] resume]; //继续游戏
_isGamePause = NO;
[self removeChild:layer cleanup:YES]; //清除暂停图层
}
-(void) didRecieveRestartEvent:(PauseLayer *)layer{
[[CCDirector sharedDirector] resume]; /
[self removeChild:layer cleanup:YES]; //清楚暂停得menu图层
[self onRestartGame];//重新开始游戏
}
3)暂停图层里到底有什么呢 ?一个item 继续游戏,一个item 重新开始游戏 到底内部触发了什么事件?
PauseLayer图层的init代码
-(id) init{
if ((self = [super initWithColor:ccc4(128, 128, 128, 128) width:320 height:480])) { //设置了一个重新开始的Item。并触发事件 doRestart
CCMenuItem *pauseItem = [CCMenuItemFont itemWithString:@"重新开始"
target:self
selector:@selector(doRestart)];
pauseItem.position = ccp(160,200);
CCMenuItem *resumeItem = [CCMenuItemFont itemWithString:@"继续游戏"
target:self
selector:@selector(doResume)];
resumeItem.position = ccp(160,300);
CustomMenu *menu = [CustomMenu menuWithItems:pauseItem,resumeItem, nil];
menu.position = CGPointZero;
[self addChild:menu];
self.isTouchEnabled = YES;
}
return self;
}
-(void) onEnter{
[super onEnter];
//我们必须注册触摸代理,才可以相应触摸事件
[[[CCDirector sharedDirector] touchDispatcher] addTargetedDelegate:self
priority:kCCMenuHandlerPriority - 1
swallowsTouches:YES];
}
-(void) onExit{
[[[CCDirector sharedDirector] touchDispatcher] removeDelegate:self];
//取消注册
[super onExit];
}
-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event{
return YES;
}
#pragma mark - menu callback
-(void) doRestart{
//下面的代码很晦涩,大致意思是:如果delegate方法响应了SEL didRecieveRestartEvent:方法,那么就触发delegate对应事件。
if ([delegate respondsToSelector:@selector(didRecieveRestartEvent:)]) {
[self.delegate didRecieveRestartEvent:self];
}
}
-(void) doResume{
if ([delegate respondsToSelector:@selector(didRecieveResumeEvent:)]) {
[self.delegate didRecieveResumeEvent:self];
}
}
@end
delegate就是我们刚才定义的
PauseLayerProtocol 。
我们来看看 pauseLayer中的属性吧。
3.#import <Foundation/Foundation.h>
#import "cocos2d.h"
@class PauseLayer;
@protocol PauseLayerProtocol <NSObject>
@required
-(void) didRecieveResumeEvent:(PauseLayer*)layer;
-(void) didRecieveRestartEvent:(PauseLayer*)layer;
@end
//上面代码 是协议的声明。
@interface PauseLayer : CCLayerColor<CCTargetedTouchDelegate> {
id<PauseLayerProtocol> delegate;
}
@property(nonatomic,assign)id<PauseLayerProtocol> delegate;
@end
//Pauselayer继承 CCLayerColor并响应触摸事件CCTargedTuchDelegate。 关键一点是它的一个属性竟然是一个遵守pauselayerProtocol 的id属性delegate。就是为了调用那两个方法。
@interface CustomMenu : CCMenu{
}
@end
下面是 CustomMenu的实现。作用就是重写 注册触摸代理的方法
@implementation CustomMenu
//重写了registerWithTouchDispatcher 方法 设置优先级kCCMenuHandlerPriority - 2
-(void) registerWithTouchDispatcher{
[[[CCDirector sharedDirector] touchDispatcher] addTargetedDelegate:self
priority:kCCMenuHandlerPriority - 2
swallowsTouches:YES];
}
@end
我们看看暂停 layer的m文件的实现
//
// PauseLayer.m
// VerticalShootingGame
//
// Created by guanghui qu on 6/27/12.
// Copyright 2012 __MyCompanyName__. All rights reserved.
//
#import "PauseLayer.h"
@interface PauseLayer()
-(void) doRestart;
-(void) doResume;
@end
@implementation PauseLayer
@synthesize delegate;
-(id) init{
if ((self = [super initWithColor:ccc4(128, 128, 128, 128) width:320 height:480])) {
CCMenuItem *pauseItem = [CCMenuItemFont itemWithString:@"重新开始"
target:self
selector:@selector(doRestart)];
pauseItem.position = ccp(160,200);
CCMenuItem *resumeItem = [CCMenuItemFont itemWithString:@"继续游戏"
target:self
selector:@selector(doResume)];
resumeItem.position = ccp(160,300);
CustomMenu *menu = [CustomMenu menuWithItems:pauseItem,resumeItem, nil];
menu.position = CGPointZero;
[self addChild:menu];
self.isTouchEnabled = YES;
}
return self;
}
-(void) onEnter{
[super onEnter];
[[[CCDirector sharedDirector] touchDispatcher] addTargetedDelegate:self
priority:kCCMenuHandlerPriority - 1
swallowsTouches:YES];
}
-(void) onExit{
[[[CCDirector sharedDirector] touchDispatcher] removeDelegate:self];
[super onExit];
}
-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event{
return YES;
}
#pragma mark - menu callback
-(void) doRestart{
if ([delegate respondsToSelector:@selector(didRecieveRestartEvent:)]) {
[self.delegate didRecieveRestartEvent:self];
}
}
-(void) doResume{
if ([delegate respondsToSelector:@selector(didRecieveResumeEvent:)]) {
[self.delegate didRecieveResumeEvent:self];
}
}
@end
@implementation CustomMenu
//重写了registerWithTouchDispatcher 方法 设置优先级kCCMenuHandlerPriority - 2
-(void) registerWithTouchDispatcher{
[[[CCDirector sharedDirector] touchDispatcher] addTargetedDelegate:self
priority:kCCMenuHandlerPriority - 2
swallowsTouches:YES];
}
@end