Cocos3.4 横版游戏制作-《KillBear》-加入Hero

转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。
资源为网上寻找的,仅研究学习用,若是侵犯版权请通知本人整改。


上一篇:Cocos3.4 横版游戏制作-《KillBear》-添加地图
在这一篇中,我们实现生成一个基础的Role类,Hero继承Role类创建.(我们敌人Enemy也会继承这个类)
最后把它放在我们的GameLayer中


开发环境


  • win64 : vs2010
  • Cocos2d-x v3.4Final
  • TexturePackerGUI
  • MapEdit

代码构建

角色Role

基础类Role

这是基础类,所有的角色都继承他.
受限篇幅,下面代码贴出一部分看注释吧

  • .h
typedef struct _BoundingBox
{
    Rect actual;
    Rect original;
}BoundingBox;
typedef enum {
    ACTION_STATE_NONE = 0,
    ACTION_STATE_IDLE,
    ACTION_STATE_WALK,
    ...
    ACTION_STATE_DEAD
}ActionState;

//基础角色类,主角和NPC都需要继承它
//单纯的控制播放动画,何时播放它在具体的类里面设置
class Role :public Sprite
{
public:
    Role(void);
    ~Role(void);
    /* 角色状态设定,初始化角色状态等 */
    CC_SYNTHESIZE(std::string,Name,Name);                           //角色名称
    CC_SYNTHESIZE(float,curtLifevalue,CurtLifeValue);               //角色当前生命值
    ...
    /* 需要用creatNomalAnimation创建,只有普通动画,有受伤判定,无攻击判定 */
    CC_SYNTHESIZE_RETAIN(Action*, m_pidleaction, IdleAction);       //角色空闲时序列
    CC_SYNTHESIZE_RETAIN(Action*, m_pwalkaction, WalkAction);       //角色移动时动画帧序列
    ...
    void Role::callBackAction(Node* pSender);                       //动画执行完毕的通用回调处理

    /*  下面是所有的动画回调函数,用来执行此动画,   */
    virtual void runIdleAction();                               //执行闲置动画
    virtual void runWalkAction();                               //执行移动行走动画
    ...
    BoundingBox createBoundingBox(Vec2 origin,Size size);
    CC_SYNTHESIZE(BoundingBox, m_bodyBox, BodyBox);             //身体碰撞盒子
    CC_SYNTHESIZE(BoundingBox, m_hitBox, HitBox);               //攻击碰撞盒子
    virtual void setPosition(const Vec2 &position);

    void updateBoxes();
protected:
    static Animation* createNomalAnimation(const char* formatStr, int frameCount, int fps);
    static Animation* createAttackAnimation(const char* formatStr, int frameCountBegan, int frameCountEnd,int fps);
private:
    bool changeState(ActionState actionState);
    ActionState proActionState;

CC_SYNTHESIZE(float,curtLifevalue,CurtLifeValue);宏定义
我们可以通过target->getCurtLifeValue()获得target的curtLifevalue,也可以通过set改变curtLifevalue的值.curtLifevalue是Role内部的一个私有成员.
其他宏功能类似

  • .cpp

//各种动作
void Role::runIdleAction()
{   //通过changeState判断是否可以变更状态,之后执行动作
    if(changeState(ACTION_STATE_IDLE))
    {
        this->runAction(m_pidleaction);
    }
}
    ...
Animation* Role::createAttackAnimation(const char* formatStr, int frameCountBegan, int frameCountEnd,int fps)
{
    //通过frameCountBegan,frameCountEnd从SpriteFrameCache中创建一个动作
    Vector<SpriteFrame*> pFrames; 
    for(int i = frameCountBegan; i < frameCountEnd; i++ )
    {
        const char* imgName = String::createWithFormat(formatStr, i)->getCString();
        SpriteFrame *pFrame = SpriteFrameCache::getInstance()->getSpriteFrameByName(imgName);
        pFrames.insert(i-frameCountBegan,pFrame);
    }
    return Animation::createWithSpriteFrames(pFrames, 1.0f / fps);
}
    ...
bool Role::changeState(ActionState actionState)
{
    //允许改变状态,死了和状态不变不会在接受其他状态改变指令
    if(currActionState == ACTION_STATE_DEAD || currActionState == actionState)
    {
        return false;
    }
    this->stopAllActions();
    this->currActionState = actionState;
    return true;
}
    ...
BoundingBox Role::createBoundingBox(Vec2 origin, Size size)
{
    //创建一个BoundingBox,用于设置身体碰撞和攻击碰撞检测
    BoundingBox boundingBox;
    boundingBox.original.origin= origin;
    boundingBox.original.size= size;
    boundingBox.actual.origin = this->getPosition() + boundingBox.original.origin;
    boundingBox.actual.size= size;
    return boundingBox;
}
void Role::updateBoxes()
{
    //通过方向刷行盒子位置
    bool isFlippedX = this->isFlippedX();
    float x = 0.0f;
    if(isFlippedX) 
    {
        x = this->getPosition().x - m_hitBox.original.origin.x;
    }else 
    {
        x = this->getPosition().x + m_hitBox.original.origin.x;
    }
    m_hitBox.actual.origin = Vec2(x, this->getPosition().y + m_hitBox.original.origin.y);
    m_bodyBox.actual.origin = this->getPosition() + m_bodyBox.original.origin;
}

void Role::setPosition(const Vec2 &position)
{
    //每次重新设定坐标的时候刷新盒子
    Sprite::setPosition(position);
    this->updateBoxes();
}

英雄Hero

主角类
还是比较长的,关注下注释,.h只有一个init没啥好说的

  • .cpp
        this->initWithSpriteFrameName("boy_idle_00.png");

        //站立时播放动画
        Animation *idleAnim = this->createNomalAnimation("boy_idle_%02d.png", 3, 5);
        this->setIdleAction(RepeatForever::create(Animate::create(idleAnim)));
        ...
        //普通攻击A,分出招和收招,期间夹杂攻击判定.自己可以通过调节fps控制出招速度之类的
        Animation *attackAnima1 = this->createAttackAnimation("boy_attack_00_%02d.png", 0, 4, 10);
        Animation *attackAnima2 = this->createAttackAnimation("boy_attack_00_%02d.png", 4, 8, 15);
        this->setNomalAttackA(Sequence::create(
            Animate::create(attackAnima1), 
            //CallFuncN::create(CC_CALLBACK_1(Hero::attackCallBackAction,this)),
            Animate::create(attackAnima2),
            Role::createIdleCallbackFunc(),
            NULL));
        ...
        //碰撞盒子设定
        this->m_bodyBox = this->createBoundingBox(Vec2(0,30), Size(30,60));
        this->m_hitBox = this->createBoundingBox(Vec2(35,50), Size(80, 90));

游戏Game

GameLayer

  • cpp

init中

this->addHero();

实现方法是

void GameLayer::addHero()
{
    m_pHero = Hero::create();
    m_pHero->setPosition(_visibleOrigin + Vec2(100, 50));
    m_pHero->runIdleAction();
    m_pHero->setLocalZOrder(_visibleSize.height - m_pHero->getPositionY());
    this->addChild(m_pHero);
}

效果

至此我们的第二步已经完成了,运行下可以看到一个窗口中我们的英雄站在那里(帧数不同是录制问题.):

结语

基础Role一次性构建完,之后调用就可以了.后续通过其他理解BoundingBox
下一篇,实现摇杆的添加和Hero的控制

你可能感兴趣的:(cocos2d-x,移动游戏开发,游戏编程)