게임 데이터가 있는가?
1. 있다
(1) MenuScene : RESUME 버튼(CCMenuItem)을 활성화시킨다.
(2) GameScene : 저장된 게임 데이터를 읽어들여 게임 화면을 재구성한 후 게임을 일시정지 상태로 전환하여 플레이어가 화면을 터치하면 게임이 시작된다.
2. 없다
(1) MenuScene : RESUME 버튼을 비활성화시킨다.
(2) GameScene : 새로운 게임을 시작한다.
작업할 파일은 다음과 같습니다.
1. 새로 추가할 파일
(1) MenuScene.h
(2) MenuScene.m
2, 수정할 파일
(1) GameScene.h
(2) GameScene.m
(3) GameLayer.h
(4) GameLayer.m
(5) GameDemoAppDelegate.h
(6) GameDemoAppDelegate.m
//
// MenuScene.h
// GameDemo
//
// Created by cmpak on 6/16/10.
// Copyright 2010 thefirstgood.com. All rights reserved.
//
#import "cocos2d.h"
@interface MenuScene : CCScene {
CCMenuItem *newGameMenuItem;
CCMenuItem *resumeGameMenuItem;
CCMenuItem *scoreMenuItem;
CCMenuItem *aboutMenuItem;
}
- (void) showGameSceneWithNewGame:(BOOL)newGame;
@end
//
// MenuScene.m
// GameDemo
//
// Created by cmpak on 6/16/10.
// Copyright 2010 thefirstgood.com. All rights reserved.
//
#import "MenuScene.h"
#import "GameData.h"
#import "GameScene.h"
enum {
kTagBackground,
kTagMenu
};
@implementation MenuScene
- (id) init {
if( (self=[super init]) ) {
// 배경 이미지를 표시하기 위해 Sprite를 이용합니다.
CCSprite *bgSprite = [CCSprite spriteWithFile:@"bg.png"];
// anchorPoint는 따로 설명을 첨부하겠습니다.
bgSprite.anchorPoint = CGPointZero;
// ccp는 CGPointMake와 같습니다.
[bgSprite setPosition: ccp(0, 0)];
// MenuScene에 배경 Sprite를 Child로 넣습니다. z-index는 0으로 설정합니다.
// 위에 선언된 enum을 참고하세요. 모든 CCNode는 tag를 가질 수 있습니다.
// tag 값을 주게되면 로컬변수를 사용하여 만들어진
// CCNode를 -(CCNode*) getChildByTag:(int) aTag 메소드를 이용하여 찾을 수 있습니다.
[self addChild:bgSprite z:kTagBackground tag:kTagBackground];
// 메뉴 버튼을 만듭니다.
// itemFromNormalImage는 버튼이 눌려지기 전에 보여지는 이미지이고,
// selectedImage는 버튼이 눌려졌을 때 보여지는 이미지입니다.
// target을 self로 한 것은 버튼이 눌려졌을 때 발생하는 터치 이벤트를 MeneScene에서
// 처리를 하겠다는 것입니다.
// @selector를 이용하여 버튼이 눌려졌을 때 어떤 메소드에서 처리를 할 것인지 결정합니다.
newGameMenuItem = [CCMenuItemImage itemFromNormalImage:@"new_game.png"
selectedImage:@"new_game_s.png"
target:self
selector:@selector(newGameMenuCallback:)];
resumeGameMenuItem = [CCMenuItemImage itemFromNormalImage:@"resume_game.png"
selectedImage:@"resume_game_s.png"
target:self
selector:@selector(resumeGameMenuCallback:)];
scoreMenuItem = [CCMenuItemImage itemFromNormalImage:@"high_score.png"
selectedImage:@"high_score_s.png"
target:self
selector:@selector(highScoreMenuCallback:)];
aboutMenuItem = [CCMenuItemImage itemFromNormalImage:@"about.png"
selectedImage:@"about_s.png"
target:self
selector:@selector(aboutMenuCallback:)];
// 위에서 만들어지 각각의 메뉴 아이템들을 CCMenu에 넣습니다.
// CCMenu는 각각의 메뉴 버튼이 눌려졌을 때 발생하는 터치 이벤트를 핸들링하고,
// 메뉴 버튼들이 어떻게 표시될 것인 지 레이아웃 처리를 담당합니다.
CCMenu *menu = [CCMenu menuWithItems: newGameMenuItem, resumeGameMenuItem, scoreMenuItem, aboutMenuItem, nil];
menu.position = ccp(menu.position.x, menu.position.y - 20);
// alignItemsVerticallyWithPadding 메소드는 자동으로 모든 버튼을
// 세로로 지정된 스페이스(padding)를 주고 정렬을 시킵니다.
// 이미지 자체에 어느정도 여백이 있기때문에 padding을 0으로 잡았습니다.
[menu alignItemsVerticallyWithPadding:0.0f];
// 만들어진 메뉴를 배경 sprite 위에 표시합니다.
[self addChild:menu z:kTagMenu tag:kTagMenu];
}
return self;
}
- (void) onEnter {
[super onEnter];
// setIsEnabled:NO를 테스트하기 위하여 게임데이터를 지웁니다.
//[GameData deleteGameDataFile];
// 저장된 게임 데이터가 있으면 Resume 메뉴아이템을 enable시킵니다.
if([GameData hasSavedGameData] == YES)
[resumeGameMenuItem setIsEnabled:YES];
else
[resumeGameMenuItem setIsEnabled:NO];
}
// 메뉴 아이템(버튼)을 만들 때 이벤트 핸들러로 등록된 메소드를 만듭니다.
- (void) newGameMenuCallback: (id) sender {
[self showGameSceneWithNewGame:YES];
}
- (void) resumeGameMenuCallback: (id) sender {
[self showGameSceneWithNewGame:NO];
}
- (void) highScoreMenuCallback: (id) sender {
NSLog(@"High Score 버튼이 눌려졌음");
}
- (void) aboutMenuCallback: (id) sender {
NSLog(@"About 버튼이 눌려졌음");
}
- (void) showGameSceneWithNewGame:(BOOL)newGame {
// 새로운 게임을 시작할 경우에는 게임 데이터 파일을 삭제합니다.
if(newGame == YES && [GameData hasSavedGameData] == YES) {
[GameData deleteGameDataFile];
NSLog(@"게임 데이터 파일 삭제");
}
GameScene *scene = [[GameScene alloc] initWithNewGame:newGame];
[[CCDirector sharedDirector] pushScene:scene];
[scene release];
}
@end
//
// GameScene.h
// GameDemo
//
// Created by cmpak on 5/11/10.
// Copyright 2010 thefirstgood.com. All rights reserved.
//
#import "cocos2d.h"
@class GameLayer;
@interface GameScene : CCScene {
GameLayer *gameLayer;
}
@property (nonatomic, readonly) GameLayer *gameLayer;
- (id) initWithNewGame:(BOOL)newGame;
@end
//
// GameScene.m
// GameDemo
//
// Created by cmpak on 5/11/10.
// Copyright 2010 thefirstgood.com. All rights reserved.
//
#import "GameScene.h"
#import "GameLayer.h"
@implementation GameScene
@synthesize gameLayer;
//- (id) init {
- (id) initWithNewGame:(BOOL)newGame {
if( (self=[super init]) ) {
//gameLayer = [GameLayer node];
GameLayer *layer = [[GameLayer alloc] initWithNewGame:newGame];
gameLayer = layer;
[self addChild:gameLayer z:0 tag:0];
[layer release];
}
return self;
}
@end
//
// GameLayer.h
// GameDemo
//
// Created by cmpak on 5/10/10.
// Copyright 2010 thefirstgood.com. All rights reserved.
//
#import "cocos2d.h"
@interface GameLayer : CCLayer {
CGSize winSize;
BOOL startNewGame;
...
}
- (id) initWithNewGame:(BOOL)newGame;
- (void) createEnemySprite:(CGPoint)position speed:(CGFloat)speed flipX:(BOOL)flip;
@end
//
// GameLayer.m
// GameDemo
//
// Created by cmpak on 5/10/10.
// Copyright 2010 thefirstgood.com. All rights reserved.
//
//- (id) init {
- (id) initWithNewGame:(BOOL)newGame {
if( (self=[super init]) ) {
// CCLayer가 터치이벤트를 처리할 수 있도록 활성화시킵니다.
self.isTouchEnabled = YES;
// 화면의 픽셀 크기를 구합니다.
winSize = [[CCDirector sharedDirector] winSize];
startNewGame = newGame;
// 초기값 설정
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) onEnter {
[super onEnter];
// random 함수의 수가 실 행할 때마다 새로운 값이 되도록 합니다.
srandom(time(NULL));
// 배경음악 연주를 시작합니다.
[[AudioPlayer sharedAudioPlayer] playAudio:kAudio_Background];
// 저장된 게임데이터로 화면을 재구성합니다.
if(startNewGame == NO) {
[self createGameSceneWithSavedGameData];
// 게임을 일시정지 시킵니다.
[self pauseGame];
}else {
// 0.5초 간격으로 적 캐릭터를 만들어냅니다.
[self schedule:@selector(addNewEnemy) interval:0.5f];
}
}
- (void) createGameSceneWithSavedGameData {
// 저장된 게임 데이터를 읽습니다.
GameData *gameData = [GameData loadGameData];
if(gameData == nil)
return;
scoreValue = gameData.score;
[self displayScore];
lifeValue = gameData.numLife;
[self displayLife];
energyValue = gameData.energy;
[self.princeEnergyBar updateBar:energyValue];
self.princeSprite.position = ccp(gameData.princeXPos, gameData.princeYPos);
self.princeSprite.flipX = gameData.princeFlipX;
// 적 sprite를 만듭니다.
if(gameData.enemyDataArr != nil) {
for(EnemyData *enemyData in gameData.enemyDataArr) {
// 적의 yPos는 사용하지 않습니다.
[self createEnemySprite:CGPointMake(enemyData.xPos, 13) speed:enemyData.walkingSpeed flipX:enemyData.flipX];
}
}
}
- (void) createEnemySprite:(CGPoint)position speed:(CGFloat)speed flipX:(BOOL)flip {
EnemySprite *enemy = [[EnemySprite alloc] initWithSpriteFrameName:@"zombie_walk_0001.png"
position:position
speed:speed
gameLayer:self ];
enemy.flipX = flip;
[self.enemySpriteSheet addChild:(CCSprite*)enemy];
[enemy release];
}
//
// GameDemoAppDelegate.h
// GameDemo
//
// Created by cmpak on 5/11/10.
// Copyright 2010 thefirstgood.com. All rights reserved.
//
#import <UIKit/UIKit.h>
@class GameResumeViewController;
//@class GameLayer;
@interface GameDemoAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
GameResumeViewController *gameResumeViewController;
//GameLayer *gameLayer;
}
@property (nonatomic, retain) UIWindow *window;
@property (nonatomic, readonly) GameResumeViewController *gameResumeViewController;
@end
//
// GameDemoAppDelegate.m
// GameDemo
//
// Created by cmpak on 5/11/10.
// Copyright 2010 thefirstgood.com. All rights reserved.
//
#import "GameDemoAppDelegate.h"
#import "cocos2d.h"
#import "GameScene.h"
#import "GameResumeViewController.h"
#import "Utils.h"
#import "MenuScene.h"
#import "GameScene.h"
@implementation GameDemoAppDelegate
@synthesize window;
@synthesize gameResumeViewController;
- (void) applicationDidFinishLaunching:(UIApplication*)application
{
...
[window makeKeyAndVisible];
/*GameScene *gameScene = [[GameScene alloc] init];
gameLayer = gameScene.gameLayer;
[[CCDirector sharedDirector] runWithScene:(CCScene*)gameScene];
[gameScene release];*/
// MenuScene을 만들어 첫 화면으로 보여준다.
MenuScene *menuScene = [[MenuScene alloc] init];
[[CCDirector sharedDirector] runWithScene:(CCScene*)menuScene];
[menuScene release];
}
// 홈 버튼이 눌려지면 바로 이 메소드가 호출이 됩니다.
- (void)applicationWillTerminate:(UIApplication *)application {
// GameLayer에서 필요한 정보를 모아 파일에 저장합니다.
//SaveCurrentGameState(gameLayer);
// 현재 보여지는 scene이 GameScene일 때에만 게임 데이터를 저장합니다.
CCScene *scene = [[CCDirector sharedDirector] runningScene];
if([scene isMemberOfClass:[GameScene class]] == YES) {
// GameLayer에서 필요한 정보를 모아 파일에 저장합니다.
GameScene *gameScene = (GameScene*)scene;
SaveCurrentGameState(gameScene.gameLayer);
}
[[CCDirector sharedDirector] end];
}