zoukankan      html  css  js  c++  java
  • 仿《雷霆战机》飞行射击手游开发--GameObject

    转载请注明:http://www.cnblogs.com/thorqq/p/5646509.html 

    项目首页:https://www.oschina.net/p/raiden

       在上一篇中,我们介绍了各种游戏对象的功能及类的集成关系,现在我们来看看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的子类

  • 相关阅读:
    【activemq artemis】消息持久化——文件系统以及jdbc
    【activemq artemis】安全相关配置
    【微信原生支付】服务商模式-小微商户专属接口:小微商户新增对应APPID关联API
    【activemq artemis】新一代ActiveMQ —— Apache ActiveMQ Artemis
    【签名加解密】c# 对XML进行数字签名并且让java验签成功
    自省书!!!!!
    大前端完整学习路线(详解)//转载自csdn:http://blog.csdn.net/u011047006/article/details/52597178
    Javascript学习十
    Javascript学习九
    Javascript学习八
  • 原文地址:https://www.cnblogs.com/thorqq/p/5646509.html
Copyright © 2011-2022 走看看