게임에서 일시정지와 이어서 하기를 구현하는 방법을 학습합니다.
작업할 파일은 다음과 같습니다.
(1) GameLayer.h
(2) GameLayer.m
//
// GameLayer.h
// GameDemo
//
// Created by cmpak on 5/10/10.
// Copyright 2010 thefirstgood.com. All rights reserved.
//
#import "cocos2d.h"
// 적이 쓰러질 방향
typedef enum {
kFallRight,
kFallLeft
}FallDirection;
// 현재 게임 진행 상황
typedef enum {
kGamePlaying,
kGamePaused
}GameStatus;
@class EnergyBar;
@interface GameLayer : CCLayer {
CGSize winSize;
// 방향 전환에 쓰일 버튼
// 눌리기 전과 눌렸을 때에 쓸 수 있도록 각 방향별로 두개씩 만든다.
CCSprite *rightSprite;
CCSprite *rightPressedSprite;
CCSprite *leftSprite;
CCSprite *leftPressedSprite;
// 발차기 버튼
CCSprite *kickSprite;
CCSprite *kickPressedSprite;
BOOL isLeftPressed;
BOOL isRightPressed;
// 주인공 캐릭터 - 여자 이미지를 사용하지만 prince라고 부르겠습니다.
CCSprite *princeSprite;
// 주인공 캐릭터의 걷기 애니메이션
CCAnimate *princeWalkAnimate;
// 주인공 발차기 애니메이션
CCAnimate *princeKickAnimate;
// 발차기 애니메이션이 진행 중인지 검사하는데 사용합니다.
BOOL isAnimating;
// 주인공 에너지 변수와 바
NSInteger energyValue;
EnergyBar *princeEnergyBar;
// 적 캐릭터
CCSpriteSheet *enemySpriteSheet;
// 적 캐릭터 애니메이션
CCAnimation *enemyWalkAnimation;
CCAnimation *enemyAttackAnimation;
// 점수와 라이프 값을 담을 변수와 화면에 표시할 레이블
NSInteger scoreValue;
NSInteger lifeValue;
CCBitmapFontAtlas *scoreLabel;
CCBitmapFontAtlas *lifeLabel;
// 게임을 일시정지/플레이하기 위해 상용되는 메뉴아이템(버튼)
CCMenuItem *pauseMenuItem;
CCMenuItem *playMenuItem;
// 게임이 일시정지 또는 플레이 중인지 나타냄
GameStatus gameStatus;
}
@property (nonatomic, retain) CCSprite *rightSprite;
@property (nonatomic, retain) CCSprite *rightPressedSprite;
@property (nonatomic, retain) CCSprite *leftSprite;
@property (nonatomic, retain) CCSprite *leftPressedSprite;
@property (nonatomic, retain) CCSprite *kickSprite;
@property (nonatomic, retain) CCSprite *kickPressedSprite;
@property (nonatomic, retain) CCSprite *princeSprite;
@property (nonatomic, retain) CCAnimate *princeWalkAnimate;
@property (nonatomic, retain) CCAnimate *princeKickAnimate;
@property (nonatomic, retain) EnergyBar *princeEnergyBar;
@property (nonatomic, retain) CCSpriteSheet *enemySpriteSheet;
@property (nonatomic, retain) CCAnimation *enemyWalkAnimation;
@property (nonatomic, retain) CCAnimation *enemyAttackAnimation;
@property (nonatomic, retain) CCBitmapFontAtlas *scoreLabel;
@property (nonatomic, retain) CCBitmapFontAtlas *lifeLabel;
- (void) createBackgroundParallax;
- (void) createLabels;
- (void) createArrowButtons;
- (void) createPrinceAndAnimation;
- (void) createEnemyAndAnimation;
- (void) createEnergyBar;
- (void) createGamePauseResumeMenu;
- (void) moveBackground;
- (void) startPrinceWalking;
- (void) stopPrinceWalking;
- (void) displayScore;
- (void) displayLife;
- (void) princeAttacked:(FallDirection)fallDirection;
- (void) handleKickHit:(CGPoint)effectPoint enemySprite:(CCSprite*)enemy directionToFall:(FallDirection)fallDirection;
- (void) animateScoreSprite:(CGPoint)position;
@end
(2) 정지/플레이 버튼을 만들기 위해 CCMenuItem 변수를 정의했습니다.
(3) 버튼을 만들어줄 함수를 정의했습니다.
//
// GameLayer.m
// GameDemo
//
// Created by cmpak on 5/10/10.
// Copyright 2010 thefirstgood.com. All rights reserved.
//
enum {
kTag_Parallax,
kTag_Prince,
kTag_Enemy,
kTag_Effect,
kTag_Label,
kTag_ControlButtonPressed,
kTag_ControlButton,
kTag_PauseResumeMenu
};
- (id) init {
if( (self=[super init]) ) {
// CCLayer가 터치이벤트를 처리할 수 있도록 활성화시킵니다.
self.isTouchEnabled = YES;
// 화면의 픽셀 크기를 구합니다.
winSize = [[CCDirector sharedDirector] winSize];
// 초기값 설정
gameStatus = kGamePlaying;
scoreValue = 0;
//lifeValue = 3;
lifeValue = INIT_NUM_LIFE;
energyValue = INIT_NUM_ENERGY;
[self createBackgroundParallax];
[self createLabels];
[self createPrinceAndAnimation];
[self createEnemyAndAnimation];
[self createArrowButtons];
[self createEnergyBar];
[self createGamePauseResumeMenu];
}
return self;
}
- (void) createGamePauseResumeMenu {
pauseMenuItem = [CCMenuItemImage itemFromNormalImage:@"btn_pause.png"
selectedImage:@"btn_pause_s.png"
target:self
selector:@selector(playPauseMenuCallback:)];
playMenuItem = [CCMenuItemImage itemFromNormalImage:@"btn_play.png"
selectedImage:@"btn_play_s.png"
target:self
selector:@selector(playPauseMenuCallback:)];
CCMenu *menu = [CCMenu menuWithItems: pauseMenuItem, playMenuItem, nil];
menu.position = ccp(0, 0);
pauseMenuItem.position = ccp(winSize.width - pauseMenuItem.contentSize.width / 2 -5 ,
winSize.height - pauseMenuItem.contentSize.height / 2 - 5 );
// 플레이 메뉴아이템이 일시정지 메뉴아이템 위에 표시됨. CCMenu에 추가될 때 z order가 하나씩 늘어남.
playMenuItem.position = pauseMenuItem.position;
// 처음에는 게임이 플레이 모드이므로 플레이 메뉴아이템을 보이지않도록 합니다.
playMenuItem.visible = NO;
[self addChild:menu z:kTag_PauseResumeMenu tag:kTag_PauseResumeMenu];
}
#pragma mark Menu Handlers
- (void) playPauseMenuCallback:(id)sender {
// 플레이 메뉴아이템이 보이지않는 상태이면, 게임을 일시정지 시킵니다.
if(playMenuItem.visible == NO) {
gameStatus = kGamePaused;
// 모든 애니메이션을 일시정지 시킵니다.
// pause를 시켜도 계속해서 터치이벤트를 받습니다.
[[CCDirector sharedDirector] pause];
// 플레이 메뉴아이템을 보여줍니다.
playMenuItem.visible = YES;
}else {
gameStatus = kGamePlaying;
playMenuItem.visible = NO;
// 모든 애니메이션을 다시 작동시킵니다.
[[CCDirector sharedDirector] resume];
}
}
- (void) ccTouchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
// pause를 시켜도 계속해서 터치이벤트를 받기때문에, 방향버튼과 공격버튼의
// 터치이벤트를 처리하면 안됩니다. 이를 방지하기 위하여 GameStatus 값을
// 사용합니다.
if(gameStatus == kGamePaused || isAnimating == YES) {
NSLog(@"Touch Began ignored");
return;
}
}
// 손가락을 떼는 순간 호출됩니다.
- (void)ccTouchesEnded:(NSSet*)touches withEvent:(UIEvent*)event {
if(gameStatus == kGamePaused)
return;
}
// 손가락을 움직일 때 계속해서 호출됩니다.
- (void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
if(gameStatus == kGamePaused)
return;
}
(1) 이미지를 이용하여 CCMenuItem을 만듭니다. 일시정지와 플레이용 두 개를 만듭니다. 버튼이 눌리면 playPauseMenuCallback 메서드를 호출합니다.
(2) 버튼이 보이는지 그렇지 않은지 visible 값으로 현재의 게임 상황을 판단합니다.