cocos2dx游戏--欢欢英雄传说--添加攻击按钮

接下来添加攻击按钮用于执行攻击动作。
同时修复了上一版移动时的bug。
修复后的Player::walkTo()函数:

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);
}

在MainScene::init()函数中添加了攻击按钮:

    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);

增加了攻击的回调函数:

void MainScene::attackCallback(Ref* pSender)
{
    _hero->stopAllActions();
    _hero->playAnimation("attack");
}

增加了Player::playAnimation()函数,执行了一次动作之后又回返回重复执行"stay"。

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);
}

效果:

#ifndef __Player__
#define __Player__
#include "cocos2d.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);
private:
    PlayerType _type;
    std::string _name;
    int _animationNum = 5;
    float _speed;
    std::vector<int> _animationFrameNums;
    std::vector<std::string> _animationNames;
    Sequence* _seq;
};

#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";
        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";
        int animationFrameNums[5] = {21, 21, 24, 30, 24};
        _animationFrameNums.assign(animationFrameNums, animationFrameNums+5);
        break;
        }
    }
    this->initWithSpriteFrameName(sfName);
    this->addAnimation();
    return true;
}
Player* Player::create(PlayerType type)
{
    Player* player = new Player();
    if (player && player->initWithPlayerType(type))
    {
        player->autorelease();
        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);
}
Player.cpp
#ifndef __MainScene__
#define __MainScene__

#include "cocos2d.h"
#include "Player.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;
};

#endif
MainScene.h
#include "MainScene.h"
#include "FSM.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");

    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);

    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");
    return true;
}

void MainScene::attackCallback(Ref* pSender)
{
    _hero->stopAllActions();
    _hero->playAnimation("attack");
}
MainScene.cpp

 

posted @ 2016-06-05 14:18  月光诗人  阅读(385)  评论(0编辑  收藏  举报