iDev/Cocos2D

드래곤 플라이트 따라 만들기 - 4. 적 케릭터

KraZYeom 2013. 1. 24. 08:09
반응형

* 혹시 안되는것이 있거나 하면 바로 리플로 알려주세요. 구현하면서 글을 작성해야 좋은데, 구현 해놓고 역으로 글을 쓰니까 코드가 살짝 꼬이는것이 있네요. 생각하면서 작성을 하고 있긴 하지만 이상한 곳이 많을 것 같습니다. 



이번 파트에서는 적 케릭터를 추가하고 적이 없어지고 다시 생성되는 것을 구현하겠다.


적 케릭터 만들기 

드래곤 플라이트에서 적은 적의 레벨에 따라서 여러 종류의 색상으로 달라진다. 하얀색이 약한 놈, 노란색은 조금더 강한 놈 ... 점점 강하게 된다. 적의 스프라이트를 상세하게 분석하면 몸통, 기본과 공격 받을때가 달라지는 양쪽 눈, 날개 짓 하는 양쪽 날개 그리고 에너지 상태를 나타내는 에너지 바로 구분 할 수 있다. 

그리고 다섯 마리의 적들이 한 줄로 나란하게 나온다. 아래로 움직여서 내려오고 화면 밖으로 벗어나면 다시 상단에서 생성되어 내려온다. 계속해서 반복한다. 


이런 컨셉으로 적을 만들어 보도록 하겠다. 


새로운 클래스의 이름을 Enemy로 CCSprite를 상속받아서 만든다. 


그리고 Enemy.h 화일에 적의 스프라이트를 생성을 위한 프로퍼티를 아래와 같이 추가한다. 

//두종류의

typedef enum {

    kRed = 0,

    kWhite

} EnemyType;



//적의 상태를 나타내기 위해 

typedef enum {

    kDestoryed = 0,

    kNormal = 1

} State;


@interface Enemy : CCSprite {

    BOOL wingDown;

}


//적의 종류 : 약한놈과 강한놈으로 가지로만 구분

@property (nonatomic) EnemyType enemyType;

//현재 상태 : 죽었는지, 살았는지로 구분

@property (nonatomic) State state;

//에너지

@property (nonatomic) NSInteger energy;

//왼쪽 날개

@property (nonatomic, weak) CCSprite *leftWing;

//오른쪽 날개

@property (nonatomic, weak) CCSprite *rightWing;

//왼쪽

@property (nonatomic, weak) CCSprite *leftEye;

//오른쪽

@property (nonatomic, weak) CCSprite *rightEye;


-(void)reset;

그리고 init 메소드에 다음 코드를 추가 한다. 

- (id)init

{

    //몬스터 스프라이트를 위한 기본 이미지를 추가한다.

    self = [super initWithSpriteFrameName:@"dragon_01_body.png"];

    if (self) {

        //적의 기본 에너지는 100

        _state = kNormal;

        _energy = 100;

        //에너지 게이지를 만든다.

        wingDown = NO;

        

        //왼쪽 날개 스프라이트

        _leftWing = [CCSprite spriteWithSpriteFrameName:@"dragon_01_wing.png"];

        _leftWing.anchorPoint = ccp1.00 );

        //중간 정도로 위치 시킨다.

        _leftWing.position = ccp(10self.boundingBox.size.height / 2);

        [self addChild:_leftWing];

        

        //오른쪽 날개 스프라이트

        _rightWing = [CCSprite spriteWithSpriteFrameName:@"dragon_01_wing.png"];

        //동일한 이미지를 반대도 회전 시켜서 사용

        _rightWing.flipX = YES;

        _rightWing.anchorPoint = ccp0.00 );

        //중간 정도로 위치 시킨다.

        _rightWing.position = ccp(self.boundingBox.size.width - 10self.boundingBox.size.height / 2);

        [self addChild:_rightWing];

        

        //왼쪽  스프라이트

        _leftEye = [CCSprite spriteWithSpriteFrameName:@"dragon_eye_1.png"];

        //왼쪽 눈의 위치를 설정한다

        _leftEye.position = ccp(1030);

        [self addChild:_leftEye];


        //오른쪽  스프라이트

        _rightEye = [CCSprite spriteWithSpriteFrameName:@"dragon_eye_1.png"];

        //왼쪽 눈의 위치를 설정한다

        _rightEye.position = ccp(3030);

        [self addChild:_rightEye];

    }

    return self;

}


적 노드가 생성될때 몸에 해당하는 스프라이트를 추가하고, 상태를 기본상태로 설정하고 에너지는 100으로 설정한다. 에너지는 적의 종류에 따라 추후 변경된다. 그리고 왼쪽, 오른쪽 날개 스프라이트를 추가한다. 나중에 날개짓 에니메이션을 위해서 엥커포인트를 조정한다. 그리고 왼쪽, 오른쪽 눈 스프라이트를 추가한다. 


일정시간 마다 적을 아래로 움직이게 하기 위해서 init 메소드 아래에 다음 코드를 추가한다.

-(void)update:(ccTime)dt {

    //적의 움직임 가속도 

    CGPoint enemyScrollVel = ccp(0, -250);

    //현재 적의 위치 

    CGPoint enemyPos = [self position];

    //화면 아래로 벗어나는지 체크

    if (enemyPos.y + self.boundingBox.size.height / 2 <= 0) {

        //벗어나면 리셋 한다.

        [self reset];

        //아닐 경우

    } else{

        //움직이게 위치값을 아래로 이동

        enemyPos = ccpAdd(ccpMult(enemyScrollVel, dt), enemyPos);

        //위치 시킨다.

        [self setPosition:enemyPos];

    }

}

시작점으로 부터 일정 주기마다 자신의 현재 위치에서 계속 아래로 내려온다. 그리고 자신의 바운딩 박스 크기가 영역을 벗어나면 초기 위치로 이동한다. 


영역을 벗어나면 초기 위치로 이동하고, 적의 레벨을 랜덤으로 변경한다. 아래 코드를 추가하자. 

#define kMaxEnemyType 2


-(void)reset{

    CGSize winSize = [[CCDirector sharedDirectorwinSize];

    //적의 위치를 화면 상단으로 부터 시작한다.

    self.position = ccpself.position.x, winSize.height + self.boundingBox.size.height / 2 - 1 );

    //적의 이미지를 바꿔주기 위해 랜덤  생성

    int random = ( (float)arc4random() / (float)0xffffffff ) * kMaxEnemyType;

    

    switch (random) {

        case kWhite:

            //에너지를 100으로 할당

            _energy = 100;

            //적의 타입설정

            _enemyType = kWhite;

            //이미지 변경을위해 프레임에 파일이름으로 스프라이트 프레임 케쉬로 부터 찾아서 할당

            [self setDisplayFrame:[[CCSpriteFrameCache sharedSpriteFrameCachespriteFrameByName:@"dragon_01_body.png"]];

            [_leftWing setDisplayFrame:[[CCSpriteFrameCache sharedSpriteFrameCachespriteFrameByName:@"dragon_01_wing.png"]];

            [_rightWing setDisplayFrame:[[CCSpriteFrameCache sharedSpriteFrameCachespriteFrameByName:@"dragon_01_wing.png"]];

            _rightWing.flipX = YES;

            break;

        case kRed:

            //에너지를 200으로 할당

            _energy = 200;

            //적의 타입설정

            _enemyType = kRed;

            //프레임에 파일이름으로 스프라이트 프레임 케쉬로 부터 찾아서 할당

            [self setDisplayFrame:[[CCSpriteFrameCache sharedSpriteFrameCachespriteFrameByName:@"dragon_02_body.png"]];

            [_leftWing setDisplayFrame:[[CCSpriteFrameCache sharedSpriteFrameCachespriteFrameByName:@"dragon_02_wing.png"]];

            [_rightWing setDisplayFrame:[[CCSpriteFrameCache sharedSpriteFrameCachespriteFrameByName:@"dragon_02_wing.png"]];

            _rightWing.flipX = YES;

            break;

        default:

            break;

    }

}


화면의 상단 밖으로 적의 스프라이트를 위치하고, 랜덤으로 적의 종류를 선택한다. 적의 종류에 따라서 에너지와 관계된 스프라이트의 이미지를 변경을 한다. 


-(void)onEnter{

    [super onEnter];

    //스케쥴러 호출

    [self scheduleUpdate];

}

-(void)update:(ccTime)dt;  스케쥴러 메소드를 호출하기 위해서 onEnter 되었을 때 [self scheduleUpdate];를 호출 한다.


적이 완성되었으니 이제는 적을 게임 화면에 추가 할 차례이다. GameLayer.h로 이동해서 아래 코드를 추가 하도록 하자.

    CCArray *enemysArray; //적을 저장할 배열

적을 배열에 넣고, 재사용을 할 목적의 배열을 생성한다. 


GameLayer.m으로 이동해서 아래 코드를 추가한다. 

#import "Enemy.h"

상단에 아래와 같이 적을 불러올 수 있게 임포트 해준다.


그리고 적을 생성하기 위해서 위해서 아래코드를 추가한다. 

#define kMaxMonster //기본 적의 수는 5마리


- (void)initEnemys {

    //적을 저장할 배열을 생성한다.

    enemysArray = [[CCArray allocinitWithCapacity:kMaxMonster];

    //화면을 균등하게 나눈다.

    float width = winSize.width / kMaxMonster;

    //적의 최대 갯수 만큼 화면에 나타내고배열에 저장

    for ( int i = 0; i < kMaxMonster ; i++ ) {

        // 노드를 생성.

        Enemy *enemy = [Enemy node];

        //화면에 위치 시킨다.

        [self addChild:enemy z:98];

        //균등하게 나눈 화면에서 가운데에 위치 시킨다.

        enemy.position = ccp( i * width + width / 2winSize.height + enemy.boundingBox.size.height / 2);

        //그리고 나중에 충돌 등을 위해 배열에 넣는다.

        [enemysArray addObject:enemy];

    }

}

배열을 생성하고 화면에서 균등하게 나눈 위치에 적을 위치시키고 배열에 저장한다. 배열에 넣는 이유는 재사용하기도 좋고, 나중에 충돌 등 각각을 다루는 것 보다 배열에서 꺼내서 사용하는게 더 편리 하기 때문이다. 


- (void)initEnemys호출을 위해서 init 메소드에서 [self initPlayer];  바로 아래에 다음 코드를 추가한다.

        [self initEnemys];


Cmd(⌘) + R으로 Run을 해보자. 아래 동영상 처럼 적들이 아래로 내려가고, 화면에서 없어지면 위에서 또 생성되서 나온다. :]





다음 파트에서는 플레이어가 총알을 쏘고, 적을 없애는 것을 다루도록 하겠다. 



* 혹시 안되는것이 있거나 하면 바로 리플로 알려주세요. 구현하면서 글을 작성해야 좋은데, 구현 해놓고 역으로 글을 쓰니까 코드가 살짝 꼬이는것이 있네요. 생각하면서 작성을 하고 있긴 하지만 이상한 곳이 많을 것 같습니다. 


반응형