[iOS] TileMap使用教學(5) 建立敵人Logic

敵人總不可能都不動吧?放在地圖上也挺怪的不是嗎?所以本章要讓敵人朝著player飛過去,準備閃躲吧!

開始

首先我們先想一下需要什麼方法呢?不外乎讓敵人移動的方法,還有敵人移動的動畫設定,最後是修飾讓敵人更活靈活現,不要只是把圖片移動而已。

先來加入以下的方法吧:

-(void) enemyMovefinished:(id)sender {
    CCSprite *enemy = (CCSprite *) sender;
    [self animateEnemy:enemy];
}

這方法會把接收到的參數作為敵人所儲存,之後的code會用到,那時你會很清楚為什麼會這樣寫。最後一句是要讓敵人執行某個方法,有趣的就在這邊。

-(void) animateEnemy:(CCSprite *)enemy {
    //speed of the enemy
    ccTime actualDuration = 0.3;
   
    //let the enemy's face toward the player
    CGPoint diff = ccpSub(_player.position, enemy.position);
    float angleRadians = atanf((float)diff.y/(float)diff.x);
    float angleDegrees = CC_RADIANS_TO_DEGREES(angleRadians);
    float cocosAngle = -1 * angleDegrees;
    if (diff.x <0) {
        cocosAngle += 180;
    }
    enemy.rotation = cocosAngle;
   
    //create the action
    id actionMove =[CCMoveBy actionWithDuration:actualDuration
                                       position:ccpMult(ccpNormalize(ccpSub(_player.position, enemy.position)), 10)];
    id actionMoveDone = [CCCallFuncN actionWithTarget:self
                                             selector:@selector(enemyMovefinished:)];
    [enemy runAction:[CCSequence actions:actionMove, actionMoveDone, nil]];
}

這個方法我把它分成兩部分,藍色的部分是修飾用的,你可以先注譯掉看看會怎樣?黑色的部分讓我來解釋一下。

第一行是設定實際上移動的時間,然後是設定移動的動畫,動畫的第一個部分actionMove,注意它位置上的指定,以下我由內而外分次解釋一下:

ccpSub(const CGPoint v1, const CGPoint v2):你稍微看一下他的實作,事實上,他是回傳一個向量,起始點是v1,終點是v2。

ccpNormalize(const CGPoint v):白話一點是把該向量的大小化作一個單位,而保持方向。

ccpMult(const CGPoint v, const CGFloat s):這是把向量v的大小(說是長度是不是比較好懂?)乘上一個有理數s(有理數是比較數學的講法,跟程式的型別無關)。


所以這一行是說,讓敵人朝著player飛去,然後把飛行的向量大小乘上10。







再來第二個部分,是讓敵人繼續保持飛行。當敵人停止移動後,會立刻調用這個方法,然後就會繼續移動。這一招我認為一定要學起來。

最後在-(void)addEnemyAtX:(int)x Y:(int)y方法最後加入一行,讓敵人可以執行動畫:

[self animateEnemy:enemy];

編譯看看吧,是不是移動的很好?只是敵人不會朝向player,這讓敵人顯得不逼真。

讓敵人朝著player移動吧

現在要解釋怎樣讓敵人飛行的時候,都是朝著player去飛。

    //let the enemy's face toward the player
    CGPoint diff = ccpSub(_player.position, enemy.position);
    float angleRadians = atanf((float)diff.y/(float)diff.x);
    float angleDegrees = CC_RADIANS_TO_DEGREES(angleRadians);
    float cocosAngle = -1 * angleDegrees;
    if (diff.x <0) {
        cocosAngle += 180;
    }
    enemy.rotation = cocosAngle;


請看藍色部分的code。

首先算出從敵人目前位置朝向player的方向,然後去計算角度,最後設定敵人旋轉的角度。注意atanf是算出以radians為單位的角度,然後再轉換成degree為單位的角度。

現在編譯看看,是不是更生動了呢?

留言