예제 #1
0
void FloorMapLayer::confirm_attack_impl(const npc_t& npc)
{
    auto life = get_tile_prop(npc.gid, "life").asInt();
    auto hun = get_tile_prop(npc.gid, "hun").asInt();
    auto gold = get_tile_prop(npc.gid, "gold").asInt();
    auto defence = get_tile_prop(npc.gid, "defence").asInt();
    auto attack = get_tile_prop(npc.gid, "attack").asInt();

    auto player_info = Player::GetInstance()->get_player_info();
    auto attack_damage = std::max(0, player_info.attack - defence);
    auto damage = std::max(0, attack - player_info.defence);
    if (attack_damage == 0 || (life + attack_damage - 1) / attack_damage * damage >= player_info.hp) // 只要攻击不够无论防御多高都打不过
    {
        auto dict = FileUtils::getInstance()->getValueMapFromFile("chinese.xml");
        auto text = dict["txt7_2"].asString();
        PromptDialog::show(text);
        stop_and_clear();
        return;
    }

    auto blood = (life + attack_damage - 1) / attack_damage * damage;

    auto target_pos = this->convertToNodeSpace(_info_panel->get_node_position_in_world(WarriorInfoPanel::hun));
    target_pos -= Vec2(26.0f, 0);
    pick_up_item_impl(npc, target_pos, [blood, gold, hun]() {
        PlayerDelegate::add_hp(-blood);
        PlayerDelegate::add_gold_hun(gold, hun);
    });

    auto end_pos = Vec2((npc.x + 0.5f) * 75.0f - 50.0f, (npc.y + 0.5f) * 75.0f - 50.0f);
    _warrior->move_to(end_pos, CC_CALLBACK_0(FloorMapLayer::step, this));
    _paths.erase(_paths.begin());
}
예제 #2
0
void FloorMapLayer::confirm_open(OKCancelDialog::RETURN_TYPE type, const npc_t& npc)
{
    if (type == OKCancelDialog::CANCEL)
    {
        stop_and_clear();
    }
    else
    {
        _warrior->stand_auto();
        auto npc_layer = _tiled_map->getLayer("npc");
        auto door = npc_layer->getTileAt(Vec2(npc.x, 11 - npc.y));
        npc_layer->setupTileSprite(door, Vec2(npc.x, 11 - npc.y), npc.gid);
        door->runAction(CCSequence::create(FadeOut::create(0.5f), RemoveSelf::create(),
            CCCallFunc::create(std::bind(&FloorMapLayer::confirm_open_impl, this, npc)), nullptr));

        // 如果是竖门需要将其上方的附加节点一并去除
        auto uplink = get_tile_prop(npc.gid, "uplink").asInt();
        if (1 == uplink)
        {
            auto npc_iter = find(_npcs.begin(), _npcs.end(), npc_t(npc.x, npc.y + 1, 0));
            if (npc_iter != _npcs.end())
            {
                const auto& npc_up = *npc_iter;
                auto door_up = npc_layer->getTileAt(Vec2(npc_up.x, 11 - npc_up.y));
                npc_layer->setupTileSprite(door_up, Vec2(npc_up.x, 11 - npc_up.y), npc_up.gid);
                door_up->runAction(CCSequence::create(FadeOut::create(0.5f), RemoveSelf::create(), nullptr));
            }
        }
    }
}
예제 #3
0
void FloorMapLayer::confirm_open(OKCancelDialog::RETURN_TYPE type, const Floor::npc_t& npc)
{
    if (type == OKCancelDialog::CANCEL)
    {
        stop_and_clear();
    }
    else
    {
        _warrior->stand_auto();
        _warrior->set_lock(true);   // 设置等待开门的过程中不可重新寻路,以免出现计算混乱
        auto npc_layer = _tiled_map->getLayer("npc");
        auto door = npc_layer->getTileAt(Vec2(npc.pos.x, 11 - npc.pos.y));
        npc_layer->setupTileSprite(door, Vec2(npc.pos.x, 11 - npc.pos.y), npc.gid);
        const float OPEN_DURATION = 0.5f;
        door->runAction(CCSequence::create(FadeOut::create(OPEN_DURATION), RemoveSelf::create(),
            CCCallFunc::create(std::bind(&FloorMapLayer::confirm_open_impl, this, npc)), nullptr));

        // 如果是竖门需要将其上方的附加节点一并去除
        auto uplink = get_tile_prop(npc.gid, "uplink").asInt();
        if (1 == uplink)
        {
            auto npc_up = Floor::GetInstance()->get_floor_info(_floor).find_npc_by_pos(Floor::position_t(npc.pos.x, npc.pos.y + 1));
            if (nullptr != npc_up)
            {
                auto door_up = npc_layer->getTileAt(Vec2(npc_up->pos.x, 11 - npc_up->pos.y));
                npc_layer->setupTileSprite(door_up, Vec2(npc_up->pos.x, 11 - npc_up->pos.y), npc_up->gid);
                door_up->runAction(CCSequence::create(FadeOut::create(OPEN_DURATION), RemoveSelf::create(), nullptr));
            }
        }
    }
}
예제 #4
0
void FloorMapLayer::confirm_open_impl(const npc_t& npc)
{
    auto color = get_tile_prop(npc.gid, "color").asInt();
    PlayerDelegate::add_key(1 == color ? -1 : 0, 2 == color ? -1 : 0, 3 == color ? -1 : 0);

    auto end_pos = Vec2((npc.x + 0.5f) * 75.0f - 50.0f, (npc.y + 0.5f) * 75.0f - 50.0f);
    _warrior->move_to(end_pos, CC_CALLBACK_0(FloorMapLayer::step, this));
    _paths.erase(_paths.begin());
}
예제 #5
0
bool FloorMapLayer::interact_item(const npc_t& npc)
{
    bool walk_pause = false;
    auto style = get_tile_prop(npc.gid, "style").asInt();
    switch (style)
    {
    case 1: // 怪物
    {
        walk_pause = true;
        auto end_pos = Vec2((npc.x + 0.5f) * 75.0f - 50.0f, (npc.y + 0.5f) * 75.0f - 50.0f);
        _warrior->turn_to(end_pos);

        if (_paths.size() > 2) // 怪物为行走路径的最后一个节点,不提示对话框,直接开打
        {
            auto dict = FileUtils::getInstance()->getValueMapFromFile("chinese.xml");
            auto text = dict["isAttack"].asString();
            auto name = dict[get_tile_prop(npc.gid, "name").asString()].asString();
            auto info = text + " " + name;
            auto dialog = OKCancelDialog::create("", info);
            dialog->setCallback(std::bind(&FloorMapLayer::confirm_attack, this, std::placeholders::_1, npc));
            ModalDialogManager::GetInstance()->pushDialog(dialog);
        }
        else
        {
            assert(_paths.size() == 2); // 和npc交互时路径肯定还有至少两个节点,一个自己的,一个对方的
            if (_paths.size() == 2)
                confirm_attack(OKCancelDialog::OK, npc);
        }
    }
    break;
    case 3: // 门
        {
            walk_pause = true;
            auto end_pos = Vec2((npc.x + 0.5f) * 75.0f - 50.0f, (npc.y + 0.5f) * 75.0f - 50.0f);
            _warrior->turn_to(end_pos);

            auto color = get_tile_prop(npc.gid, "color").asInt();
            const auto& player = Player::GetInstance()->get_player_info();
            if (1 == color && player.key_red < 1 || 2 == color && player.key_blue < 1 || 3 == color && player.key_yellow < 1)
            {
                auto dict = FileUtils::getInstance()->getValueMapFromFile("chinese.xml");
                auto text = dict["buyKeyTip"].asString();
                PromptDialog::show(text);
                stop_and_clear();
                break;
            }

            auto dict = FileUtils::getInstance()->getValueMapFromFile("chinese.xml");
            auto prefix = dict["open_msg1"].asString();
            auto sufix = dict["open_msg2"].asString();
            auto textkey = 1 == color ? "rKey" : (2 == color ? "bKey" : "yKey");
            auto info = prefix + dict[textkey].asString() + sufix;
            auto dialog = OKCancelDialog::create("", info);
            dialog->setCallback(std::bind(&FloorMapLayer::confirm_open, this, std::placeholders::_1, npc));
            ModalDialogManager::GetInstance()->pushDialog(dialog);
        }
        break;
    case 6: // 楼梯
    {
        walk_pause = false; // 无需停下来,直接切换楼层,切换场景的持续时间的一半让勇士正好走入下一个楼梯格子
        auto next_scene = PromptLayer::scene(_floor == 1 ? 2 : 1);
        auto transition = TransitionFade::create(0.5f, next_scene);
        Director::getInstance()->replaceScene(transition);
    }
    break;
    default:
        break;
    }

    return walk_pause;
}
예제 #6
0
void FloorMapLayer::pick_up_item(const npc_t& npc)
{
    std::function<void()> callback;
    WarriorInfoPanel::node_type type;

    bool need_pick = true;
    auto style = get_tile_prop(npc.gid, "style").asInt();
    switch (style)
    {
    case 2: // 钥匙
        {
            auto color = get_tile_prop(npc.gid, "color").asInt();
            if (0 == color) // 钥匙串
            {
                type = WarriorInfoPanel::key_blue;
                callback = std::bind(&PlayerDelegate::add_key, 1, 1, 1);
            }
            else if (1 == color) // 红钥匙
            {
                type = WarriorInfoPanel::key_red;
                callback = std::bind(&PlayerDelegate::add_key, 1, 0, 0);
            }
            else if (2 == color) // 蓝钥匙
            {
                type = WarriorInfoPanel::key_blue;
                callback = std::bind(&PlayerDelegate::add_key, 0, 1, 0);
            }
            else if (3 == color) // 黄钥匙
            {
                type = WarriorInfoPanel::key_yellow;
                callback = std::bind(&PlayerDelegate::add_key, 0, 0, 1);
            }
        }
        break;
    case 4: // 宝石
        {
            auto color = get_tile_prop(npc.gid, "color").asInt();
            auto value = get_tile_prop(npc.gid, "value").asInt();
            if (1 == color) // 红宝石,攻击
            {
                type = WarriorInfoPanel::attack;
                callback = std::bind(&PlayerDelegate::add_attack, value);
            }
            else if (2 == color) // 蓝宝石,防御
            {
                type = WarriorInfoPanel::defend;
                callback = std::bind(&PlayerDelegate::add_defence, value);
            }
        }
        break;
    case 5: // 血瓶
        {
            auto value = get_tile_prop(npc.gid, "value").asInt();
            type = WarriorInfoPanel::hp;
            callback = std::bind(&PlayerDelegate::add_hp, value);
        }
        break;
    default:
        need_pick = false;
        break;
    }

    if (need_pick)
    {
        auto target_pos = this->convertToNodeSpace(_info_panel->get_node_position_in_world(type));
        target_pos -= Vec2(26.0f, 0);
        pick_up_item_impl(npc, target_pos, callback);
    }
}
예제 #7
0
void FloorMapLayer::onTouchEnded(Touch *touch, Event *e)
{
    // bugfix: 如果对话框已弹出,就不再执行以下代码,这种情况是在对话框弹出前,touchbegan就已经触发的情况下发生
    // 重现方法: 控制勇士经过怪物,然后鼠标按下等待勇士到达怪物处,弹出提示对话框后,松开鼠标继续弹出
    if (ModalDialogManager::GetInstance()->isShown())
    {
        return;
    }

    // 正在战斗中则不允许重新走动,以免计算混乱
    if (_warrior->is_fighting())
    {
        return;
    }

    // 获取起始点
    auto end_vec2 = _tiled_map->convertTouchToNodeSpace(touch) / 75.0f;
    auto end_pt = node_t(end_vec2.x, end_vec2.y);
    if (!_paths.empty() && _paths.back() == end_pt)
    {
        return;
    }
    
    auto start_vec2 = _tiled_map->convertToNodeSpace(_warrior->getPosition()) / 75.0f;
    auto start_pt = node_t(start_vec2.x, start_vec2.y);
    if (start_pt == end_pt)
    {
        return;
    }


    // 获取阻碍点
    auto wall_layer = _tiled_map->getLayer("wall");
    auto wall_layer_size = wall_layer->getLayerSize();
    auto pos = touch->getLocation();
    auto tiles = wall_layer->getTiles();
    std::vector<node_t> blocks;
    for (uint32_t i = 0; i < (uint32_t)(wall_layer_size.height); ++i)
    {
        for (uint32_t j = 0; j < (uint32_t)(wall_layer_size.width); ++j)
        {
            if (tiles[i * (uint32_t)(wall_layer_size.width) + j] != 0)
            {
                blocks.push_back(node_t(j, (uint32_t)(wall_layer_size.height) - 1 - i));
            }
        }
    }

    if (std::find(blocks.begin(), blocks.end(), end_pt) != blocks.end() || end_pt.x >= 10 || end_pt.y >= 12)
    {
        return;
    }
    
    // npc列表
    npc_t stair_up, stair_down;
    auto npc_layer = _tiled_map->getLayer("npc");
    auto npc_layer_size = npc_layer->getLayerSize();
    auto npc_tiles = npc_layer->getTiles();
    _npcs.clear();
    for (uint32_t i = 0; i < (uint32_t)(npc_layer_size.height); ++i)
    {
        for (uint32_t j = 0; j < (uint32_t)(npc_layer_size.width); ++j)
        {
            int32_t gid = (int32_t)(npc_tiles[i * (uint32_t)(npc_layer_size.width) + j]);
            if (gid != 0)
            {
                _npcs.push_back(npc_t(j, npc_layer_size.height - 1 - i, gid));
                if (get_tile_prop(gid, "style").asInt() == 6)
                {
                    if (get_tile_prop(gid, "type").asInt() == 1)
                        stair_up = _npcs.back();
                    else
                        stair_down = _npcs.back();
                }
            }
        }
    }

    // A星路径
    AStar astar(10, 12);
    astar.set_start_and_end(start_pt, end_pt);
    astar.set_blocks(blocks);
    _paths = astar.get_path();
    auto iter = std::find_if(_paths.begin(), _paths.end(), [&](node_t node) {
        // 找到除了首节点的第一个楼梯节点
        return (node.x != start_pt.x || node.y != start_pt.y) &&
            (node.x == stair_up.x && node.y == stair_up.y || node.x == stair_down.x && node.y == stair_down.y);
    });

    if (iter != _paths.end())
        _paths.erase(++iter, _paths.end());

    // 箭头
    _arrow_node->setVisible(true);
    _arrow_node->setPosition(Vec2((end_pt.x + 0.5f) * 75.0f - 50.0f, (end_pt.y + 0.5f) * 75.0f - 50.0f));

    // 路线
    uint32_t index = 0;
    _road_node->removeAllChildren();
    for (auto node : _paths)
    {
        if (index == _paths.size() - 1)
            break;
        auto pos = Vec2((node.x + 0.5f) * 75.0f - 50.0f, (node.y + 0.5f) * 75.0f - 50.0f);
        auto res = "Images/diban" + String::createWithFormat("%d", index % 22)->_string + ".png";
        auto sprite = Sprite::create(res);
        sprite->setPosition(pos);
        _road_node->addChild(sprite);
        ++index;
    }

    // 勇士
    _warrior->stopAllActions();
    step();
}
예제 #8
0
bool FloorMapLayer::init(int floor, bool up)
{
    _floor = floor;
    // 由于直接继承自node,需要做一些处理,现在layer的功能全被废弃了,无意义
    setContentSize(Director::getInstance()->getWinSize());

    auto listener = EventListenerTouchOneByOne::create();
    listener->setSwallowTouches(true);
    listener->onTouchBegan = CC_CALLBACK_2(FloorMapLayer::onTouchBegan, this);
    listener->onTouchEnded = CC_CALLBACK_2(FloorMapLayer::onTouchEnded, this);
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);

    // 加载地图编辑器文件
    auto res = "TileMaps/floor00" + String::createWithFormat("%d", floor)->_string + ".tmx";
    _tiled_map = cocos2d::experimental::TMXTiledMap::create(res);
    if (nullptr != _tiled_map)
    {
        _tiled_map->setPosition(Vec2(-50.0f, -50.0f));
        this->addChild(_tiled_map);
    }

    auto npc_layer = _tiled_map->getLayer("npc");
    auto npc_layer_size = npc_layer->getLayerSize();
    auto npc_tiles = npc_layer->getTiles();
    std::vector<Floor::npc_t> npcs;
    for (uint32_t i = 0; i < (uint32_t)(npc_layer_size.height); ++i)
    {
        for (uint32_t j = 0; j < (uint32_t)(npc_layer_size.width); ++j)
        {
            int32_t gid = (int32_t)(npc_tiles[i * (uint32_t)(npc_layer_size.width) + j]);
            if (gid != 0)
            {
                const Floor::floor_t& floor = Floor::GetInstance()->get_floor_info(_floor);
                Floor::npc_t npc(j, npc_layer_size.height - 1 - i, gid);
                if (floor.is_valid())
                {
                    auto iter = std::find(floor.npcs.begin(), floor.npcs.end(), npc);
                    if (iter == floor.npcs.end())
                    {
                        npc_layer->setTileGID(999, Vec2(j, i));
                    }
                }
                npcs.push_back(npc);
                if (get_tile_prop(gid, "style").asInt() == 6)
                {
                    if (get_tile_prop(gid, "type").asInt() == 2)
                        _stair_up = npcs.back();
                    else
                        _stair_down = npcs.back();
                }
            }
        }
    }

    Floor::GetInstance()->auto_init_floor(_floor, npcs);

    // 路径节点
    _road_node = Node::create();
    if (nullptr != _road_node)
    {
        _road_node->setPosition(Vec2::ZERO);
        this->addChild(_road_node);
    }

    // 勇士骨骼动画节点
    _warrior = WarriorNode::create();
    /*cocostudio::CCBone* bone = _warrior->getBone("sheild1");
    int index = bone->getDisplayManager()->getCurrentDisplayIndex();
    bone->removeDisplay(1);
    bone->changeDisplayByIndex(-1, true);
    cocostudio::CCBone* bone2 = _warrior->getBone("sheild2");
    index = bone2->getDisplayManager()->getCurrentDisplayIndex();
    bone2->removeDisplay(1);
    bone2->changeDisplayByIndex(-1, true);*/
    Floor::position_t pos = up ? _stair_down.pos : _stair_up.pos;
    _warrior->setPosition(Vec2((pos.x + 0.5f) * 75.0f - 50.0f, (pos.y + 0.5f) * 75.0f - 50.0f));
    this->addChild(_warrior);

    // 上方背景
    auto inside_bg = Sprite::create("Images/bg_top2.png");
    auto outside_bg = Sprite::create("Images/bg_top_1.png");
    if (nullptr != outside_bg && nullptr != inside_bg)
    {
        auto win_size = Director::getInstance()->getWinSize();
        outside_bg->setScale(inside_bg->getContentSize().width / outside_bg->getContentSize().width);
        outside_bg->setPosition(Vec2(win_size.width / 2, 1092.0f));
        this->addChild(outside_bg);

        inside_bg->setPosition(Vec2(win_size.width / 2, 1076.0f));
        this->addChild(inside_bg);
    }

    // 点击箭头节点
    _arrow_node = ArrowNode::create();
    if (nullptr != _arrow_node)
    {
        _arrow_node->setPosition(Vec2::ZERO);
        _arrow_node->setVisible(false);
        this->addChild(_arrow_node);
    }

    // 勇士属性面板
    _info_panel = WarriorInfoPanel::create();
    if (nullptr != _info_panel)
    {
        _info_panel->setPosition(Vec2(-10.0f, 825.0f));
        this->addChild(_info_panel);
    }
    
    return true;
}