zoukankan      html  css  js  c++  java
  • cocos2dx游戏--欢欢英雄传说--为敌人添加移动和攻击动作

    这里主要为敌人添加了一个移动动作和攻击动作。
    移动动作是很简略的我动他也动的方式。
    攻击动作是很简单的我打他也打的方式。
    效果:

    代码:

    #ifndef __Progress__
    #define __Progress__
    #include "cocos2d.h"
    USING_NS_CC;
    
    class Progress : public Sprite
    {
    public:
        bool init(const char* background, const char* fillname);
        /*
        the inputs are SpriteFrame Names.
        they should be loaded into SpriteFrameCache before calling this.
        */
        static Progress* create(const char* background, const char* fill);
    
        void setFill(ProgressTimer* fill){_fill=fill;}
    
        void setProgress(float percentage){_fill->setPercentage(percentage);}
        float getProgress() { return _fill->getPercentage(); }
    
    private:
        ProgressTimer* _fill;
    };
    #endif
    Progress.h
    #include "Progress.h"
    
    bool Progress::init(const char* background, const char* fillname)
    {
        this->initWithSpriteFrameName(background);
        ProgressTimer* fill = ProgressTimer::create(Sprite::createWithSpriteFrameName(fillname));
        this->setFill(fill);
        this->addChild(fill);
    
        fill->setType(ProgressTimer::Type::BAR);
        fill->setMidpoint(Point(0,0.5));
        fill->setBarChangeRate(Point(1.0, 0));
        fill->setPosition(this->getContentSize()/2);
        fill->setPercentage(100);
        return true;
    }
    
    Progress* Progress::create(const char* background, const char* fillname)
    {
        Progress* progress = new Progress();
        if(progress && progress->init(background,fillname))
        {
            progress->autorelease();
            return progress;
        }
        else
        {
            delete progress;
            progress = NULL;
            return NULL;
        }
    }
    Progress.cpp
    #ifndef __Player__
    #define __Player__
    #include "cocos2d.h"
    #include "Progress.h"
    
    USING_NS_CC;
    
    class Player : public Sprite
    {
    public:
        enum PlayerType
        {
            HERO,
            ENEMY
        };
        bool initWithPlayerType(PlayerType type);
        static Player* create(PlayerType type);
        void addAnimation();
        void playAnimationForever(std::string animationName);
        void playAnimation(std::string animationName);
        void walkTo(Vec2 dest);
        Sequence* getSeq() { return _seq; }
        void getHit();
        void autoDoAction(Player* hero);
        void autoAttack(Player* hero);
        Progress* getProgress() { return _progress; }
    private:
        PlayerType _type;
        std::string _name;
        int _animationNum = 5;
        float _speed;
        std::vector<int> _animationFrameNums;
        std::vector<std::string> _animationNames;
        Sequence* _seq;
        Progress* _progress;
        bool _isShowBar;
    };
    
    #endif
    Player.h
    #include "Player.h"
    #include <iostream>
    
    bool Player::initWithPlayerType(PlayerType type)
    {
        std::string sfName = "";
        std::string animationNames[5] = {"attack", "dead", "hit", "stay", "walk"};
        _animationNames.assign(animationNames,animationNames+5);
        switch (type)
        {
        case PlayerType::HERO:
            {
            _name = "hero";
            sfName = "hero-stay0000.png";
            _isShowBar = false;
            int animationFrameNums[5] = {10, 12, 15, 30, 24};
            _animationFrameNums.assign(animationFrameNums, animationFrameNums+5);
            _speed = 125;
            break;
            }
        case PlayerType::ENEMY:
            {
            _name = "enemy";
            sfName = "enemy-stay0000.png";
            _isShowBar = true;
            int animationFrameNums[5] = {21, 21, 24, 30, 24};
            _animationFrameNums.assign(animationFrameNums, animationFrameNums+5);
            _speed = 70;
            break;
            }
        }
        this->initWithSpriteFrameName(sfName);
        this->addAnimation();
    
        auto size = this->getContentSize();
        _progress = Progress::create("small-enemy-progress-bg.png","small-enemy-progress-fill.png");
        _progress->setPosition( size.width/2, size.height + _progress->getContentSize().height/2);
        this->addChild(_progress);
        if(!_isShowBar)
        {
            _progress->setVisible(false);
        }
    
        return true;
    }
    Player* Player::create(PlayerType type)
    {
        Player* player = new Player();
        if (player && player->initWithPlayerType(type))
        {
            player->autorelease();
            player->setAnchorPoint(Vec2(0.5, 0));
            return player;
        }
        else
        {
            delete player;
            player = NULL;
            return NULL;
        }
    }
    void Player::addAnimation()
    {
        auto animation = AnimationCache::getInstance()->getAnimation(String::createWithFormat("%s-%s", _name.c_str(),
                                                                _animationNames[0].c_str())->getCString());
        if (animation)
            return;
        for (int i = 0; i < _animationNum; i ++)
        {
            auto animation = Animation::create();
            animation->setDelayPerUnit(1.0f / 10.0f);
            for (int j = 0; j < _animationFrameNums[i]; j ++)
            {
                auto sfName = String::createWithFormat("%s-%s%04d.png", _name.c_str(), _animationNames[i].c_str(), j)->getCString();
                animation->addSpriteFrame(SpriteFrameCache::getInstance()->getSpriteFrameByName(sfName));
                if (!animation)
                log("hello ha ha");
            }
            AnimationCache::getInstance()->addAnimation(animation, String::createWithFormat("%s-%s", _name.c_str(),
                                                                _animationNames[i].c_str())->getCString());
        }
    }
    void Player::playAnimationForever(std::string animationName)
    {
        auto str = String::createWithFormat("%s-%s", _name.c_str(), animationName.c_str())->getCString();
        bool exist = false;
        for (int i = 0; i < _animationNum; i ++) {
            if (animationName == _animationNames[i])
            {
                exist = true;
                break;
            }
        }
        if (exist == false)
            return;
        auto animation = AnimationCache::getInstance()->getAnimation(str);
        auto animate = RepeatForever::create(Animate::create(animation));
        this->runAction(animate);
    }
    
    void Player::playAnimation(std::string animationName)
    {
        auto str = String::createWithFormat("%s-%s", _name.c_str(), animationName.c_str())->getCString();
        bool exist = false;
        for (int i = 0; i < _animationNum; i ++) {
            if (animationName == _animationNames[i])
            {
                exist = true;
                break;
            }
        }
        if (exist == false)
            return;
        auto animation = AnimationCache::getInstance()->getAnimation(str);
        auto func = [&]()
        {
            this->stopAllActions();
            this->playAnimationForever("stay");
            _seq = nullptr;
        };
        auto callback = CallFunc::create(func);
        auto animate = Sequence::create(Animate::create(animation), callback,NULL);
        this->runAction(animate);
    }
    
    void Player::walkTo(Vec2 dest)
    {
        if (_seq)
            this->stopAction(_seq);
        auto curPos = this->getPosition();
        if (curPos.x > dest.x)
            this->setFlippedX(true);
        else
            this->setFlippedX(false);
        auto diff = dest - curPos;
        auto time = diff.getLength() / _speed;
        auto moveTo = MoveTo::create(time, dest);
        auto func = [&]()
        {
            this->stopAllActions();
            this->playAnimationForever("stay");
            _seq = nullptr;
        };
        auto callback = CallFunc::create(func);
        this->stopAllActions();
        this->playAnimationForever("walk");
        _seq = Sequence::create(moveTo, callback, nullptr);
    
        this->runAction(_seq);
    }
    
    void Player::getHit()
    {
        float blood = _progress->getProgress();
        if (_name == "hero")
            blood -= 3;
        else
            blood -= 5;
        _progress->setProgress(blood);
        log(String::createWithFormat("hit now blood is %f", blood)->getCString());
        if (blood <= 0)
        {
            log(String::createWithFormat("%s is dead.", _name.c_str())->getCString());
            auto func = [&]()
            {
                this->stopAllActions();
                this->playAnimation("dead");
            };
            auto callback = CallFunc::create(func);
            _seq = Sequence::create(callback, nullptr);
            this->runAction(_seq);
            this->_progress->setVisible(false);
            this->setVisible(false);
            return;
        }
    }
    
    void Player::autoDoAction(Player* hero) // just for _enemy
    {
        Vec2 dest = hero->getPosition();
        if (_seq)
            this->stopAction(_seq);
        auto curPos = this->getPosition();
        if (curPos.x > dest.x)
            this->setFlippedX(true);
        else
            this->setFlippedX(false);
        auto diff = dest - curPos;
        if (diff.x > 0) diff.x -= 90;
        else diff.x += 90;
        if (diff.y > 0) diff.y -= 20;
        else diff.y += 20;
        auto time = diff.getLength() / _speed;
        auto moveTo = MoveTo::create(time, dest);
        auto func = [&]()
        {
            this->stopAllActions();
            this->playAnimationForever("stay");
            _seq = nullptr;
        };
        auto callback = CallFunc::create(func);
        this->stopAllActions();
        this->playAnimationForever("walk");
        _seq = Sequence::create(moveTo, callback, nullptr);
    
        this->runAction(_seq);
    }
    
    void Player::autoAttack(Player* hero) // just for _enemy
    {
        float blood = _progress->getProgress();
        if (blood <= 0)
            return;
        Vec2 del = this->getPosition() - hero->getPosition();
        if (del.length() <= 100)
        {
            this->playAnimation("attack");
            hero->getHit();
        }
    }
    Player.cpp
    #ifndef __MainScene__
    #define __MainScene__
    
    #include "cocos2d.h"
    #include "Player.h"
    #include "Progress.h"
    
    USING_NS_CC;
    
    class MainScene : public cocos2d::Layer
    {
    public:
        static cocos2d::Scene* createScene();
        virtual bool init();
        void menuCloseCallback(cocos2d::Ref* pSender);
        CREATE_FUNC(MainScene);
        bool onTouchBegan(Touch* touch, Event* event);
        void attackCallback(Ref* pSender);
    private:
        Player* _hero;
        Player* _enemy;
        EventListenerTouchOneByOne* _listener_touch;
        Progress* _progress;
    };
    
    #endif
    MainScene.h
    #include "MainScene.h"
    
    Scene* MainScene::createScene()
    {
        auto scene = Scene::create();
        auto layer = MainScene::create();
        scene->addChild(layer);
        return scene;
    }
    bool MainScene::init()
    {
        if ( !Layer::init() )
        {
            return false;
        }
        Size visibleSize = Director::getInstance()->getVisibleSize();
        Vec2 origin = Director::getInstance()->getVisibleOrigin();
    
        SpriteFrameCache::getInstance()->addSpriteFramesWithFile("images/role.plist","images/role.png");
        SpriteFrameCache::getInstance()->addSpriteFramesWithFile("images/ui.plist","images/ui.pvr.ccz");
    
        Sprite* background = Sprite::create("images/background.png");
        background->setPosition(origin + visibleSize/2);
        this->addChild(background);
    
        //add player
        _hero = Player::create(Player::PlayerType::HERO);
        _hero->setPosition(origin.x + _hero->getContentSize().width/2, origin.y + visibleSize.height/2);
        this->addChild(_hero);
    
        //add enemy1
        _enemy = Player::create(Player::PlayerType::ENEMY);
        _enemy->setPosition(origin.x + visibleSize.width - _enemy->getContentSize().width/2, origin.y + visibleSize.height/2);
        this->addChild(_enemy);
    
        _hero->playAnimationForever("stay");
        _enemy->playAnimationForever("stay");
    
        _listener_touch = EventListenerTouchOneByOne::create();
        _listener_touch->onTouchBegan = CC_CALLBACK_2(MainScene::onTouchBegan,this);
        _eventDispatcher->addEventListenerWithSceneGraphPriority(_listener_touch, this);
    
        auto attackItem = MenuItemImage::create(
                                               "CloseNormal.png",
                                               "CloseSelected.png",
                                               CC_CALLBACK_1(MainScene::attackCallback, this));
    
        attackItem->setPosition(Vec2(origin.x + visibleSize.width - attackItem->getContentSize().width/2 ,
                                    origin.y + attackItem->getContentSize().height/2));
    
        // create menu, it's an autorelease object
        auto menu = Menu::create(attackItem, NULL);
        menu->setPosition(Vec2::ZERO);
        this->addChild(menu, 1);
    
        _progress = Progress::create("player-progress-bg.png","player-progress-fill.png");
        _progress->setPosition(_progress->getContentSize().width/2, this->getContentSize().height - _progress->getContentSize().height/2);
        this->addChild(_progress);
    
        return true;
    }
    void MainScene::menuCloseCallback(cocos2d::Ref* pSender)
    {
    #if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
        MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
        return;
    #endif
    
        Director::getInstance()->end();
    
    #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
        exit(0);
    #endif
    }
    
    bool MainScene::onTouchBegan(Touch* touch, Event* event)
    {
        Vec2 pos = this->convertToNodeSpace(touch->getLocation());
        _hero->walkTo(pos);
        log("MainScene::onTouchBegan");
        _enemy->autoDoAction(_hero);
        return true;
    }
    
    void MainScene::attackCallback(Ref* pSender)
    {
        _hero->stopAllActions();
        _hero->playAnimation("attack");
        Vec2 del = _hero->getPosition() - _enemy->getPosition();
        float distance = del.length();
        log(String::createWithFormat("distance == %f", distance)->getCString());
        if (distance <= 100.0) {
            _enemy->getHit();
        }
        _enemy->autoAttack(_hero);
        _progress->setProgress(_hero->getProgress()->getProgress());
    }
    MainScene.cpp

     ------------华丽的分割线------------

    最近工作上出了一点事情。可能暂时就写到这里了。希望以后有机会能够再补上接下来的内容。

    参考教程:http://www.cocos.com/doc/tutorial/lists?id=85

    项目github地址:https://github.com/moonlightpoet/HuanHero

  • 相关阅读:
    求解奖学金问题--贪心
    装饰模式(Decorator Pattern)
    组合模式(Composite Pattern)
    Java基础:容器
    DatabaseMetaData类
    Java命名规范
    MyEclipse快捷键
    工厂模式(Factory)
    单例模式详解以及需要注意的地方(Singleton)
    SpringBoot启动流程与源码
  • 原文地址:https://www.cnblogs.com/moonlightpoet/p/5561221.html
Copyright © 2011-2022 走看看