요즘 매주 일요일 아이폰 게임 개발 스터디에서 게임을 개발하는 즐거운 시간을 보내고 있습니다. 2주차 과제는 지금까지 학습한 내용만으로 나만의 개성있는 아이폰 게임을 만들어 보는 것이었습니다. 그래서 간단한 슈팅 게임을 만들었고 바로 이 전 포스트에서 동영상으로도 소개했습니다. 아래 보이는 오브젝티브C 소스 코드는 그 슈팅 게임의 기능을 구현한 클래스 소스입니다. 생각보다 간단한가요? 구현한 기능이 단조로운 이유도 있겠지만 게임 엔진을 활용한 덕분에 코딩해야할 것이 많이 줄어든 것이 이유겠지요. 다음주 스터디의 주제는 물리엔진입니다. 물리엔진에 대해 어느 정도 파악하게 되면 이제 제대로 된 게임을 만들 수 있게 되겠군요.^^ 슬슬 chipmunk 와 box2d 물리엔진을 마구 파헤쳐 봐야겠어요.

CocosGame.zip

// ShootGame.m

#import "ShootGame.h"

@implementation ShootGame

@synthesize enemySprites, missileSprites;

+(id) scene {
    CCScene *scene = [CCScene node];
    ShootGame *layer = [ShootGame node];
    [scene addChild: layer];
    return scene;
}

-(id)init{
    if ( (self=[super init]) ) {
        self.isTouchEnabled = YES;
        self.isAccelerometerEnabled = YES;
       
        //sprite = nil;
        //CGSize size = [[CCDirector sharedDirector] winSize];
       
        CCSprite *sprite = [CCSprite spriteWithFile:@"shooter.png"];
        [sprite setPosition:ccp(26, 50)];
        [self addChild:sprite z:1 tag:1];
       
        self.enemySprites = [[NSMutableArray alloc] init];
        self.missileSprites = [[NSMutableArray alloc] init];
       
        [self schedule:@selector(scheduleEnemy:) interval:1.0];
        [self schedule:@selector(scheduleCollision:)];
    }
    return self;
}

- (CGRect) spriteRect:(CCSprite *)sprite {
    CGRect rect = CGRectMake(
        sprite.position.x - (sprite.contentSize.width/2),
        sprite.position.y - (sprite.contentSize.height/2),
        sprite.contentSize.width,
        sprite.contentSize.height);
    return rect;
}

- (void) moveFinished : (id) sender {
    CCSprite *sprite = (CCSprite *) sender;
    if (sprite.tag == 101) {
        [enemySprites removeObject:sprite];
    } else if (sprite.tag == 102) {
        [missileSprites removeObject:sprite];
    }
    [self removeChild:sprite cleanup:YES];
}

- (void) addEnemySprite {
    int rand = arc4random() % 2;
    CCSprite *enemy = [CCSprite spriteWithFile:[NSString stringWithFormat:@"enemy%d.png",rand]];
    CGSize winsize = [[CCDirector sharedDirector] winSize];
    int pointY = (arc4random() % 200 + 100);
    int timeDuration = (arc4random() % 4 + 1);
    enemy.position = ccp( winsize.width + (enemy.contentSize.width/2) , pointY);
    enemy.tag = 101;
    [enemySprites addObject:enemy];
    [self addChild:enemy];
    id actionMove = [CCMoveTo actionWithDuration:timeDuration position:ccp( -enemy.contentSize.width/2 , pointY)];
    id moveDone = [CCCallFuncN actionWithTarget:self selector:@selector(moveFinished:)];                
    [enemy runAction:[CCSequence actions:actionMove, moveDone, nil]];
}    

- (void) destroyEnemy:(CCSprite *)enemy {
    [enemy stopAllActions];
    id shaky = [CCShaky3D actionWithRange:4 shakeZ:NO grid:ccg(15,10) duration:1];
    id clear = [CCCallFuncN actionWithTarget:self selector:@selector(moveFinished:)];
    [enemy runAction: [CCSequence actions:shaky, clear, nil]];
}

- (void) checkCollision {
    NSMutableArray *crashMissiles = [[NSMutableArray alloc] init];
    for (CCSprite *missile in missileSprites)     {
        CGRect missileRect = [self spriteRect:missile];
        //NSLog(@"%@",NSStringFromCGRect(missileRect));
        NSMutableArray *crashSprites = [[NSMutableArray alloc] init];
        for ( CCSprite *enemy in enemySprites ) {
            CGRect enemyRect = [self spriteRect:enemy];
            if( CGRectIntersectsRect (missileRect, enemyRect) ) {
                [crashSprites addObject:enemy];
            }                                        
        }
        if (crashSprites.count > 0) {
            [crashMissiles addObject:missile];
        }
        for (CCSprite *enemy in crashSprites) {
            [enemySprites removeObject:enemy];
            //[self removeChild:enemy cleanup:YES];
            [self destroyEnemy:enemy];
        }
        [crashSprites release];
    }
   
    for (CCSprite *missile in crashMissiles) {
        [missileSprites removeObject:missile];
        [self removeChild:missile cleanup:YES];
    }
    [crashMissiles release];
}
                   
- (void) scheduleEnemy: (ccTime)dt {
    [self addEnemySprite];
}                    

- (void) scheduleCollision: (ccTime)dt {
    [self checkCollision];
}    

-(void)doTask{
    NSLog(@"doTask");
}

- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    if( touch ) {
        //CGSize winsize = [[CCDirector sharedDirector] winSize];
        CGPoint location = [touch locationInView: [touch view]];
        CGPoint convertedPoint = [[CCDirector sharedDirector] convertToGL:location];

        CCNode *sprite = [self getChildByTag:1];
       
        CCSprite *missile = [CCSprite spriteWithFile:@"missile.png"];
        [missileSprites addObject:missile];
       
        int touchY = convertedPoint.y;
        int positionX = sprite.position.x;
        int positionY = sprite.position.y;
        id moveSprite;
        if (touchY > positionY) {
            moveSprite = [CCMoveTo actionWithDuration:0.5f position:ccp(positionX, positionY+40)];
        } else {
            moveSprite = [CCMoveTo actionWithDuration:0.5f position:ccp(positionX, positionY-40)];
        }
        [sprite runAction:moveSprite];
       
        missile.position = ccp(40, positionY);
        //missile.tag = 102;
        [self addChild:missile z:102 tag:102];
        id moveMissile = [CCMoveTo actionWithDuration:1.5f position:ccp(460, positionY)];
        id clearMissile = [CCCallFuncN actionWithTarget:self selector:@selector(moveFinished:)];
        //id actonMissile [CCSequence actions:moveMissile, clearMissile, nil];
        [missile runAction:[CCSequence actions:moveMissile, clearMissile, nil]];
    }
}

- (void)accelerometer:(UIAccelerometer*)accelerometer didAccelerate:(UIAcceleration*)acceleration {
    CCNode *sprite = [self getChildByTag:1];
    CGPoint converted = ccp( (float)-acceleration.y, (float)acceleration.x);
    sprite.rotation = (float) CC_RADIANS_TO_DEGREES( atan2f( converted.x, converted.y) + M_PI );
    sprite.scale = 0.5f + sqrtf( (converted.x * converted.x) + (converted.y * converted.y) );
}

@end

웹프로그래머의 홈페이지 정보 블로그 http://hompy.info/603

[연관 포스트]
아이폰 게임 제작을 위한 2D 그래픽 엔진 Cocos2D 설치 및 실행 동영상
아이폰 아이팟 코코아 터치 애플리케이션 개발 샘플 동영상
직장인을 위한 아이폰 게임 디자인 스터디를 추진해 봅니다.
직장인을 위한 아이폰 앱 개발 Cocos2D 스터디를 추진합니다.

[아이폰 스터디 그룹 맴버쉽 게시판]
http://flashcafe.org/iphone_study

트랙백 주소 :: http://hompy.info/trackback/603

댓글을 달아 주세요