cocos2d-x 炮臺旋轉和子彈移動的一點小技巧

一般在遊戲中我們避免不了處理旋轉或者子彈發射什麼的,就比如塔防遊戲來說吧,我們需要判斷敵人往哪裏走,炮塔就往哪裏轉,轉完然後朝着一個方向發射子彈是一個方向而不是朝一個點,就比如保衛蘿蔔,子彈穿過怪物繼續朝那個方向飛行,直到飛往屏幕外才移除),下面來簡單分析一下實現的過程,需要涉及到一點點平面向量的數學知識。

(注意勻速)

1. 旋轉 : 朝着某個點的方向勻速旋轉

2.發射:讓子彈朝着某個點的方向勻速移動


我們來分步驟實現,先實現旋轉功能:


嗯,現在假設平面中有點A和點B,A是炮塔,B是敵人,現在我們需要讓炮塔A的方向朝着敵人B旋轉,因爲炮塔放置的時候方向向上,所以我們要旋轉的角度爲α,如圖


現在首先,我們創建敵人和塔

  1. //敵人  
  2. auto enemy = Sprite::create("enemy.png");  
  3. enemy->setPostion(Point(100,200));  
  4. this->addChild(enemy);  
  5.   
  6. //塔  
  7. auto tower = Sprite::create("tower.png");  
  8. tower->setPostion(Point(200,100));  
  9. this->addChild(tower);  

然後我們讓塔旋轉瞄準敵人,只是爲了能射它一臉(呵呵?)

  1. //讓塔的方向旋轉對準敵人  
  2.   
  3. //射擊方向向量  
  4. Point shootVector = enemy->getPosition() - tower->getPosition();  
  5. //向量標準化(即向量長度爲1)  
  6. Point normalizedVector = ccpNormalize(shootVector) ;  
  7. //算出旋轉的弧度  
  8. float radians = atan2(normalizedVector.y, - normalizedVector.x);  
  9. //將弧度轉換成角度  
  10. float degree = CC_RADIANS_TO_DEGREES(radians);  
  11.   
  12.   
  13. //勻速旋轉需要我們設置一下速度,這裏假設旋轉速度爲 2π (rad/s)  
  14. float rotateSpeed = 2 * M_PI;  
  15. //那麼旋轉1弧度所用時間爲  
  16. float rotate_1rad_time = 1 / rotateSpeed;  
  17. //所以旋轉的時長爲  
  18. float rotateDuration = fabs(radians * rotate_1rad_time);  
  19.   
  20.   
  21. //最後執行旋轉  
  22. _sprite->runAction(RotateTo::create(rotateDuration,degree- 90));  

需要注意一下

(1)假設點A爲塔,B爲敵。則 向量  shootVector = OB -OA = AB  

(2)atan2(y,x)是就是反正切函數, 算出的是  點(x,y)與x軸正方向的夾角,返回的是角的弧度值

(3)所以degree算出的角度其實是與x軸正方向的夾角

(4)由於炮塔方向向上,所以  【旋轉的角度  α 】= degree - 90


如果你想不起來什麼是反正切,那沒關係,看下面假設和圖(再想不起來我只能呵呵了)

假設 tan(α) = y / x , 則有 α = arctan(y / x)


旋轉完後接下來我們再實現射擊功能:


假設有塔,子彈和敵人,位置如圖,我們需要把子彈由位置A沿着AB方向 勻速射到C(C點在屏幕外)



我們先創建敵人,塔和子彈


  1. //敵人  
  2. auto enemy = Sprite::create("enemy.png");  
  3. enemy->setPostion(Point(100,200));  
  4. this->addChild(enemy);  
  5.   
  6. //塔  
  7. auto tower = Sprite::create("tower.png");  
  8. tower->setPostion(Point(200,100));  
  9. this->addChild(tower);  
  10.   
  11. //子彈,和塔在一個位置  
  12. auto tower = Sprite::create("bullet.png");  
  13. tower->setPostion(Point(200,100));  
  14. this->addChild(tower);  

然後這次我們真的射它一臉(再次呵呵)


  1. //射擊方向向量  
  2. Point shootVector = enemy->getPosition() - bullet->getPosition();  
  3. //向量標準化(即向量長度爲1)  
  4. Point normalizedVector = ccpNormalize(shootVector);  
  5. //移動長度向量  
  6. Point overShootVector = normalizedVector * 900;  
  7. //超出屏幕的點  
  8. Point offScreenPoint = bullet->getPosition() + overShootVector;  
  9.   
  10. //假設速度爲500(pix/s)  
  11. float moveSpeed = 500;  
  12. //移動時間  
  13. float moveDuration = overShootVector / moveSpeed;  
  14.   
  15. //執行設計  
  16. auto move = MoveTo::create(moveDuration,offScreenPoint);  
  17. CallFunc* moveDone = CallFunc::create(CC_CALLBACK_0(shootFinish,this,bullet));  
  18. bullet->runAction(Sequence::create(move,moveDone,NULL));  
射擊結束後移除子彈

  1. //射擊結束後移除  
  2. void HelloWorld::shootFinish(Node* pNode){  
  3.     Sprite* bullet = (Sprite*)pNode;  
  4.     if(bullet != NULL)  
  5.         bullet->stopAllActions();  
  6.         this->removeChild(bullet);  
  7. }  

稍稍解釋一下 :

(1)shootVector就是向量AB。

(2)overShootVector = (AB向量標準化)× 900 即得到  AC。比如說你設置的分辨率爲 800 x 400 ,那麼你可以用標準化向量 × 你最大分辨率再大一點,這樣子向量就會超出屏幕之外而且長度又固定。

(3)然後根據向量OC = OA + AC ,算出要移動到的點offScreenPoint(即點C)。

(4)設置一下速度,長度一定了,所以時間 = 長度 / 速度 。


=====================================================


其實也沒啥東西,純屬小白教程。。


轉載請註明出處:http://blog.csdn.net/shun_fzll/article/details/34430045

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章