Cocos2d-x에서 Rx.cpp를 사용하는 라이브러리 CocosRx

14118 단어 RxFRPcocos2d-x
Cocos2d-x와 Rx.cpp에서 리액티브 프로그래밍을 시작하기 위해 CocosRx 라이브러리를 만들었습니다.

소개



Rx.cpp 라는 C++용 리액티브 프로그래밍 라이브러리가 있습니다.

Cocos2d-x에서 사용하려면 적어도 이벤트를 Observable로 처리할 수 없으면 시작되지 않습니다. 확실히 터치 이벤트와 프레임 업데이트 이벤트를 Observable로 하는 라이브러리를 만들어 보았습니다. 이것만으로도 약간 놀 수 있다고 생각합니다.

그러나 Cocos2d-x에서 (또는 c++로) 리액티브 프로그래밍을하는 것이 의미가 있는지는 모릅니다. 어쩌면 너무 불모한 일을 하고 있을지도 모르지만 w

도입 방법



Cocos2d-x 프로젝트와 함께/Classes 아래의 cpp를 컴파일하십시오.
물론 Rx.cpp도 필요합니다. Rx.cpp의/Rx/v2/src/rxcpp를 포함 경로로 설정합시다.

터치 이벤트 처리



CCRxTouchEvent.h의 CCRx::touchEventObservable을 사용하면 터치 이벤트를 Observable로 처리할 수 있습니다.
내부에서는 cocos::EventDispatcher::addEventListenerWithSceneGraphPriority에서 터치 이벤트를 등록하고 있습니다.
namespace CCRx {

    typedef rxcpp::observable<cocos2d::Touch*> TouchEventObservable;

    rxcpp::observable<std::tuple<cocos2d::Touch*, TouchEventObservable>>
        touchEventObservable(
            cocos2d::Node* targetNode,
            std::function<bool(cocos2d::Touch*)> isBegan = nullptr,
            bool isSwallow = false);
}

반환되는 Observable은 터치가 시작된 위치의 터치 정보 클래스와 TouchEventObservable의 tuple의 Observable입니다.
TouchEventObservable은 한 번의 터치/드래그 시작부터 끝까지 제공하는 Observable입니다.

다음과 같이 사용하면 드래그(플릭) 조작에 따라 좌우 방향으로 캐릭터를 움직일 수 있습니다.

#include "CCRxTouchEvent.h"

...

    auto player = Sprite::create("player.png");
    addChild(player);

    auto touchObservableObservable = CCRx::touchEventObservable(this, nullptr, false);

    // move player sprite according to touch and move
    auto shared_player = RefPtr<Sprite>(player);

    touchObservableObservable.subscribe(rxu::apply_to([=](Touch *t, CCRx::TouchEventObservable o) {

        auto touchPointOrigin = this->getParent()->convertToNodeSpace(t->getLocation());
        auto playerOrigin = shared_player->getPosition();

        o.subscribe(
                    [=](Touch* t){

                        auto touchPoint = this->getParent()->convertToNodeSpace(t->getLocation());
                        auto newPosition = playerOrigin + (touchPoint - touchPointOrigin);
                        shared_player->setPosition(
                            std::max(
                                std::min(newPosition.x, visibleSize.width), 0.0f), playerOrigin.y);

                    });
    }));

프레임 업데이트 이벤트



CCRx::interval을 사용하면 타이머 처리와 같은 것을 할 수 있습니다. interval을 0으로 취급하면 매 프레임이라 불리므로 애니메이션 처리에 사용할 수 있습니다.
내부에서 cocos::Scheduler::schedule을 사용하고 있습니다.
namespace CCRx {
    rxcpp::observable<float> interval(cocos2d::Node* targetNode, float interval);
}

다음 예에서는 3초에 한 번 적 캐릭터를 배치하여 무작위로 날아가고 있습니다.
#include "CCRxScheduler.h"

...

    auto rnd = std::make_shared<std::mt19937>();

    CCRx::interval(this, 3)
    .start_with(0)
    .as_dynamic()
    .subscribe([=](float) {
        std::uniform_real_distribution<float> xDist(0.0 ,visibleSize.width);
        const auto fromX = xDist(*rnd);
        const auto toX = xDist(*rnd);
        const auto startPosition = Vec2{fromX, visibleSize.height};
        const float speed = 100.0;
        const auto vector = (Vec2{toX, 0} - startPosition).getNormalized() * speed;

        auto enemy = RefPtr<Sprite>(Sprite::create("enemy.png"));
        addChild(enemy.get());

        enemy->setPosition(startPosition);

        CCRx::interval(enemy.get(), 0)
        .scan(0.0f, [](float sum, float b) { return sum + b; })
        .as_dynamic()
        .subscribe([=](float delta) {
            enemy->setPosition(startPosition + vector * delta);

            if (enemy->getPosition().y < 0) {
                enemy->removeFromParent();
            }
        });

    });


추가 샘플



github의 리포지토리에는, 슈팅 게임 같은 샘플의 프로젝트도 들어가 있으므로, 좀 더 실례를 원하시는 분은 봐 주세요.

좋은 웹페이지 즐겨찾기