轉載請注明: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的子類