程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 仿《雷霆戰機》飛行射擊手游開發--GameObject,雷霆戰機超人氣飛行

仿《雷霆戰機》飛行射擊手游開發--GameObject,雷霆戰機超人氣飛行

編輯:C++入門知識

仿《雷霆戰機》飛行射擊手游開發--GameObject,雷霆戰機超人氣飛行


轉載請注明:http://www.cnblogs.com/thorqq/p/5646509.html 

 

   在上一篇中,我們介紹了各種游戲對象的功能及類的集成關系,現在我們來看看GameObject的源代碼

碰撞體

GameObject.h

 1 class GameObject : public Sprite
 2 {
 3 public:
 4     GameObject();
 5 
 6     virtual void setBodySize(const Size& s);
 7     virtual void setBodySize(float w, float h);
 8     virtual const Size& getBodySize();
 9     virtual const Size& getOrignBodySize() const;
10 
11     virtual void setBodyCenter(const Vec2& v);
12     virtual void setBodyCenter(float x, float y);
13     virtual const Vec2& getBodyCenter() const;
14 
15     //獲取世界坐標下的body的位置和大小
16     virtual Rect getBodyBox() const;
17 
18 
19 protected:
20     //用於碰撞檢測的剛體大小和位置
21     Vec2 m_bodyCenter; //剛體的中心點坐標(相對於精靈錨點的坐標)
22     Size m_bodySize;   //剛體的寬高
23 };

GameObject.cpp

 1 void GameObject::setBodySize(const Size& s)
 2 {
 3     m_bodySize = s;
 4 }
 5 
 6 void GameObject::setBodySize(float w, float h)
 7 {
 8     setBodySize(Size(w, h));
 9 }
10 
11 const Size& GameObject::getBodySize()
12 {
13     return m_bodySize;
14 }
15 
16 void GameObject::setBodyCenter(const Vec2& v)
17 {
18     m_bodyCenter = v;
19 }
20 
21 void GameObject::setBodyCenter(float x, float y)
22 {
23     m_bodyCenter = Vec2(x, y);
24 }
25 
26 const Vec2& GameObject::getBodyCenter() const
27 {
28     return m_bodyCenter;
29 }
30 
31 //獲取世界坐標下的body的位置和大小
32 Rect GameObject::getBodyBox() const
33 {
34     Vec2 pos = getPosition();
35 
36     return Rect(pos.x + m_bodyCenter.x - m_bodySize.width * getAnchorPoint().x,
37         pos.y + m_bodyCenter.y - m_bodySize.height * getAnchorPoint().y,
38         m_bodySize.width,
39         m_bodySize.height);
40 }

碰撞體的定義很簡單,中心坐標+寬高,然後加上常見的get/set方法。其中比較有用的是getBodyBox()方法。由於碰撞體的中心坐標是相對於Sprite錨點的坐標,所以如果要用來判斷兩個碰撞體是否發生碰撞(是否有重疊區域),必須要獲取兩個碰撞體在世界坐標下的位置和大小,這時就要調用getBodyBox()方法來得到Rect對象,然後再調用Rect的bool intersectsRect(const Rect& rect)方法來判斷兩個碰撞體是否發生了碰撞。

 暫停/恢復

GameObject.h

1     virtual void pause() override;
2     virtual void resume() override;
3     void pause(Node *pNode);
4     void resume(Node *pNode);

GameObject.cpp

 1 void GameObject::pause()
 2 {
 3     this->pause(this);
 4 }
 5 
 6 void GameObject::resume()
 7 {
 8     this->resume(this);
 9 }
10 
11 void GameObject::pause(Node *pNode)
12 {
13     Node::pause();
14 
15     for (auto p : pNode->getChildren())
16     {
17         p->pause();
18     }
19 }
20 
21 void GameObject::resume(Node *pNode)
22 {
23     Node::resume();
24 
25     for (auto p : pNode->getChildren())
26     {
27         p->resume();
28     }
29 }

調用pause和resume的同時,會調用所有子節點的pause和resume。這樣,當玩家飛機暫停時,僚機作為它的子節點,也會跟著暫停。

初始化 

先看代碼

 1 bool GameObject::initSpriteWithFileList(const std::vector<std::string>& fileList, float dura)
 2 {
 3     SpriteFrame *frame = SpriteFrameCache::getInstance()->getSpriteFrameByName(fileList.at(0));
 4     if (NULL == frame)
 5     {
 6         DEBUG_LOG("Error get frame of '%s'", fileList.at(0).c_str());
 7         CCASSERT(frame, "Error get frame");
 8     }
 9     Sprite::initWithSpriteFrame(frame);
10 
11     //動畫
12     if (fileList.size() > 1)
13     {
14         Animation* animation = Animation::create();
15         animation->setDelayPerUnit(dura);
16         for (unsigned i = 0; i < fileList.size(); i++)
17         {
18             SpriteFrame* pFrame = CCSpriteFrameCache::getInstance()->getSpriteFrameByName(fileList[i]);
19             if (NULL == pFrame)
20             {
21                 continue;
22             }
23             animation->addSpriteFrame(pFrame);
24         }
25 
26         //設置重復
27         Animate* animate = Animate::create(animation);
28         Repeat* repeat = Repeat::create(animate, CC_REPEAT_FOREVER);
29         m_pAnimateSequence = Sequence::create(repeat, NULL);
30         m_pAnimateSequence->retain();
31         runAction(m_pAnimateSequence);
32     }
33 
34     return true;
35 }

這個函數是通過幀序列來初始化。這裡有兩個輸入參數:fileList是圖片列表,dura是每張圖片之間個時間間隔。如何是骨骼動畫呢?看下面這個代碼:

 1 bool GameObject::initArmature(const std::string& armatureName, float scale)
 2 {
 3     if (armatureName.length() <= 0)
 4     {
 5         return true;
 6     }
 7 
 8     m_pArmature = cocostudio::Armature::create(armatureName);
 9     m_pArmature->setPosition(getContentSize() / 2);
10     m_pArmature->getAnimation()->play(GlobalData::getInstance()->getArmatureData(armatureName)->defaultAction);
11     m_pArmature->setScale(scale);
12 
13     addChild(m_pArmature);
14 
15     return true;
16 }

    首先通過骨骼動畫的名稱armatureName創建骨骼動畫,然後執行默認動作defaultAction(defaultAction是從配置文件中獲取的,配置文件的讀寫將在以後詳述)。最後把骨骼動畫添加到Sprite上。

    這裡就有一個疑問了,為什麼既要支持幀序列動畫,又要支持骨骼動畫呢?我們知道骨骼動畫的表現形式比幀序列動畫更豐富,但是隨之而來的問題就是骨骼動畫更占資源。如果只有一個簡單的動畫,或者像子彈那樣速度比較快並且數量比較多的游戲對象,應該盡量使用幀序列動畫,甚至對於子彈來說,只用單張圖片來表現就可以了,根本用不著動畫。而對於玩家飛機、boss來說,因為涉及到變形,那就不得不用骨骼動畫了。

    另外,這裡也有一個可以優化的地方。我們可以把GameObject繼承自Node,當游戲對象是序列幀動畫時,就添加一個Sprite子節點,如果是骨骼動畫,就添加一個Armature子節點。

 下載參考代碼

 

轉載請注明:http://www.cnblogs.com/thorqq/p/5646509.html 

下一篇開始,我們將逐個介紹GameObject的子類

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved