文档章节

仿《雷霆战机》飞行射击手游开发--GameObject

雁惊寒
 雁惊寒
发布于 2017/01/20 14:13
字数 1024
阅读 184
收藏 0

在上一篇中,我们介绍了各种游戏对象的功能及类的集成关系,现在我们来看看GameObject的源代码

碰撞体

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.h

    virtual void pause() override;
    virtual void resume() override;
    void pause(Node *pNode);
    void resume(Node *pNode);

GameObject.cpp

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。这样,当玩家飞机暂停时,僚机作为它的子节点,也会跟着暂停。

初始化 

先看代码

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上。

    这里就有一个疑问了,为什么既要支持帧序列动画,又要支持骨骼动画呢?我们知道骨骼动画的表现形式比帧序列动画更丰富,但是随之而来的问题就是骨骼动画更占资源。如果只有一个简单的动画,或者像子弹那样速度比较快并且数量比较多的游戏对象,应该尽量使用帧序列动画,甚至对于子弹来说,只用单张图片来表现就可以了,根本用不着动画。而对于玩家飞机、boss来说,因为涉及到变形,那就不得不用骨骼动画了。

    另外,这里也有一个可以优化的地方。我们可以把GameObject继承自Node,当游戏对象是序列帧动画时,就添加一个Sprite子节点,如果是骨骼动画,就添加一个Armature子节点。

 

转载请注明:https://my.oschina.net/u/1986600/blog/828371

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

© 著作权归作者所有

雁惊寒
粉丝 20
博文 13
码字总数 20195
作品 1
南京
程序员
私信 提问
thorqq/RaidenFree

功能介绍 本游戏是一款基于Cocos2dx开发的纵版飞行射击单机手游。玩家可以控制一架飞机与敌机进行对战,飞机可以发射子弹、导弹甚至激光,除此之外,玩家还能对自己的飞机进行强化改造,提升...

thorqq
2017/01/20
0
0
cocos2d-x支持c++、js、lua开发

作者:左文 链接:https://www.zhihu.com/question/21130385/answer/21789568 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 纯属个人观点 1 Unity3d支...

壹峰
2017/10/18
201
0
写给对 ”游戏开发” 感兴趣的朋友们

我们程序员能为世界带来什么? 有些程序员做出了 淘宝/Amazon,为世界带来了电子商务。 有些程序员做出了 微信/Twitter,为世界带来了社交平台。 而有些程序员做出的东西,虽然无法应用于我们...

程序员小灰
03/05
0
0
仿雷电飞行射击手游--Raiden

游戏介绍 本游戏是一款基于Cocos2dx开发的纵版飞行射击单机手游。玩家可以控制一架飞机与敌机进行对战,飞机可以发射子弹、导弹甚至激光,除此之外,玩家还能对自己的飞机进行强化改造,提升...

雁惊寒
2017/01/20
8K
6
【U3D入门小白教程——案例篇】之二:全民打飞机

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/iceSony/article/details/77801934 个人学习第二章节:雷电游戏 1.通过上一章的了解,初步入门了Unity引擎。现...

唐三十胖子
2017/09/02
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Tensorflow 2.0安装

Tensorflow2.0安装环境: Ubuntu 16.04或更高(64位) Windows 7或者更高(64位,且支持python3) 安装Tensorflow 2.0 GPU版本的需要安装NVIDIA相关软件包: NVIDIA驱动 :版本必须410.x或更...

JosiahMg
15分钟前
4
0
TL138/1808/6748F-EasyEVM开发板硬件、CPU、FLASH、RAM

TL138/1808/6748F-EasyEVM是广州创龙基于SOM-TL138/SOM-TL1808/SOM-TL6748F核心板开发的一款开发板。由于SOM-TL138/SOM-TL1808/SOM-TL6748核心板管脚兼容,所以此三个核心板共用同一个底板。...

Tronlong创龙
23分钟前
2
0
百度嵌入式AI解决方案EdgeBoard之内存驱动设计介绍

1. 背景介绍 由于 FPGA 具备可编程和高性能计算的特点,基于FPGA硬件的AI计算加速,正广泛地应用到计算机视觉处理领域。其中极具代表性的部署方式之一就是使用FPGA和CPU组合构成异构计算系统...

AI君
29分钟前
5
0
开放应用模型(OAM):全球首个云原生应用标准定义与架构模型

Kubernetes 项目作为容器编排领域的事实标准, 成功推动了诸如阿里云 Kubernetes (ACK)等云原生服务的迅速增长。但同时我们也关注到,Kubernetes 的核心 API 资源比如 Service、Deploymen...

Mr_zebra
32分钟前
3
0
《Linux操作系统-Exynos4412》编译和安装Busybox

开发环境:Exynos4412-iTOP-4412开发板 现在 Busybox 的配置已经完成了,接下来开始编译 Busybox,在 Ubuntu 的终端输入 “make”命令开始编译 Busybox,如下图。 下图为编译过程中的截图。 ...

书白
35分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部