在上一篇中,咱們介紹了各類遊戲對象的功能及類的集成關係,如今咱們來看看GameObject的源代碼ide
GameObject.h函數
class GameObject : public Sprite { public: GameObject(); virtual void setBodySize(const Size& s); virtual void setBodySize(float w, float h); virtual const Size& getBodySize(); virtual const Size& getOrignBodySize() const; virtual void setBodyCenter(const Vec2& v); virtual void setBodyCenter(float x, float y); virtual const Vec2& getBodyCenter() const; //獲取世界座標下的body的位置和大小 virtual Rect getBodyBox() const; protected: //用於碰撞檢測的剛體大小和位置 Vec2 m_bodyCenter; //剛體的中心點座標(相對於精靈錨點的座標) Size m_bodySize; //剛體的寬高 };
GameObject.cpp優化
void GameObject::setBodySize(const Size& s) { m_bodySize = s; } void GameObject::setBodySize(float w, float h) { setBodySize(Size(w, h)); } const Size& GameObject::getBodySize() { return m_bodySize; } void GameObject::setBodyCenter(const Vec2& v) { m_bodyCenter = v; } void GameObject::setBodyCenter(float x, float y) { m_bodyCenter = Vec2(x, y); } const Vec2& GameObject::getBodyCenter() const { return m_bodyCenter; } //獲取世界座標下的body的位置和大小 Rect GameObject::getBodyBox() const { Vec2 pos = getPosition(); return Rect(pos.x + m_bodyCenter.x - m_bodySize.width * getAnchorPoint().x, pos.y + m_bodyCenter.y - m_bodySize.height * getAnchorPoint().y, m_bodySize.width, m_bodySize.height); }
碰撞體的定義很簡單,中心座標+寬高,而後加上常見的get/set方法。其中比較有用的是getBodyBox()方法。因爲碰撞體的中心座標是相對於Sprite錨點的座標,因此若是要用來判斷兩個碰撞體是否發生碰撞(是否有重疊區域),必需要獲取兩個碰撞體在世界座標下的位置和大小,這時就要調用getBodyBox()方法來獲得Rect對象,而後再調用Rect的bool intersectsRect(const Rect& rect)方法來判斷兩個碰撞體是否發生了碰撞。動畫
GameObject.hthis
virtual void pause() override; virtual void resume() override; void pause(Node *pNode); void resume(Node *pNode);
GameObject.cppspa
void GameObject::pause() { this->pause(this); } void GameObject::resume() { this->resume(this); } void GameObject::pause(Node *pNode) { Node::pause(); for (auto p : pNode->getChildren()) { p->pause(); } } void GameObject::resume(Node *pNode) { Node::resume(); for (auto p : pNode->getChildren()) { p->resume(); } }
調用pause和resume的同時,會調用全部子節點的pause和resume。這樣,當玩家飛機暫停時,僚機做爲它的子節點,也會跟着暫停。.net
先看代碼code
bool GameObject::initSpriteWithFileList(const std::vector<std::string>& fileList, float dura) { SpriteFrame *frame = SpriteFrameCache::getInstance()->getSpriteFrameByName(fileList.at(0)); if (NULL == frame) { DEBUG_LOG("Error get frame of '%s'", fileList.at(0).c_str()); CCASSERT(frame, "Error get frame"); } Sprite::initWithSpriteFrame(frame); //動畫 if (fileList.size() > 1) { Animation* animation = Animation::create(); animation->setDelayPerUnit(dura); for (unsigned i = 0; i < fileList.size(); i++) { SpriteFrame* pFrame = CCSpriteFrameCache::getInstance()->getSpriteFrameByName(fileList[i]); if (NULL == pFrame) { continue; } animation->addSpriteFrame(pFrame); } //設置重複 Animate* animate = Animate::create(animation); Repeat* repeat = Repeat::create(animate, CC_REPEAT_FOREVER); m_pAnimateSequence = Sequence::create(repeat, NULL); m_pAnimateSequence->retain(); runAction(m_pAnimateSequence); } return true; }
這個函數是經過幀序列來初始化。這裏有兩個輸入參數:fileList是圖片列表,dura是每張圖片之間個時間間隔。如何是骨骼動畫呢?看下面這個代碼:對象
bool GameObject::initArmature(const std::string& armatureName, float scale) { if (armatureName.length() <= 0) { return true; } m_pArmature = cocostudio::Armature::create(armatureName); m_pArmature->setPosition(getContentSize() / 2); m_pArmature->getAnimation()->play(GlobalData::getInstance()->getArmatureData(armatureName)->defaultAction); m_pArmature->setScale(scale); addChild(m_pArmature); return true; }
首先經過骨骼動畫的名稱armatureName建立骨骼動畫,而後執行默認動做defaultAction(defaultAction是從配置文件中獲取的,配置文件的讀寫將在之後詳述)。最後把骨骼動畫添加到Sprite上。blog
這裏就有一個疑問了,爲何既要支持幀序列動畫,又要支持骨骼動畫呢?咱們知道骨骼動畫的表現形式比幀序列動畫更豐富,可是隨之而來的問題就是骨骼動畫更佔資源。若是隻有一個簡單的動畫,或者像子彈那樣速度比較快而且數量比較多的遊戲對象,應該儘可能使用幀序列動畫,甚至對於子彈來講,只用單張圖片來表現就能夠了,根本用不着動畫。而對於玩家飛機、boss來講,由於涉及到變形,那就不得不用骨骼動畫了。
另外,這裏也有一個能夠優化的地方。咱們能夠把GameObject繼承自Node,當遊戲對象是序列幀動畫時,就添加一個Sprite子節點,若是是骨骼動畫,就添加一個Armature子節點。