void Unit::changeState
class Unit :
	public Sprite
{
public:
	bool			init();
	CREATE_FUNC(Unit);
	virtual void		update(float delta);

	void				changeState(UnitState* state);

	CC_SYNTHESIZE(UnitState*, _state, State);
private:
};

유닛 구조를 대충 잡고

class Swordman :
    public Unit
{
public:
    bool    init();
    CREATE_FUNC(Swordman);
};

유닛 종류를 하나 만들어 주었다.

bool Swordman::init()
{
    if (!Unit::init())
        return false;
    _attackSpeed = 1.f;
    _moveSpeed = 30.0;
    
    this->setUnitName("swordman");
    this->initWithFile("SpriteSource/swordman/swordman_walk_1.png");
    AnimationManager::getInstance()->addAnimation(_unitName, "walk", 0.1f,{
        "SpriteSource/swordman/swordman_walk_1.png",
        "SpriteSource/swordman/swordman_walk_2.png",
        "SpriteSource/swordman/swordman_walk_3.png",
        "SpriteSource/swordman/swordman_walk_4.png",
        "SpriteSource/swordman/swordman_walk_5.png",
        "SpriteSource/swordman/swordman_walk_6.png"});
    this->changeState(UnitState_Walk::create());
    return true;
}

추가한 유닛 종류에 대해 셋팅도 해주고
(AnimationManager 클래스도 구현했는데, addAnimation클래스는 이미 있는지 검사해서 없으면 검사하는 클래스. 게임 시작할 때 한 번만 호출되게 바꿀 예정)


class UnitState : public Node
{
public:
    virtual void StartState(Unit* unit) = 0;
    virtual void RunState(Unit* unit) = 0;
    virtual void EndState(Unit* unit) = 0;
};

상태에 대한 인터페이스도 정해주었다.

class UnitState_Walk : public UnitState
{
public:
    CREATE_FUNC(UnitState_Walk);
    bool init() { return true; }
    void StartState(Unit* unit);
    void RunState(Unit* unit);
    void EndState(Unit* unit);
};

void UnitState_Walk::StartState(Unit* unit)
{
    auto animation = AnimationManager::getInstance()->getAnimation(unit->getUnitName(), "walk");
    auto animate = Animate::create(animation);
    unit->runAction(RepeatForever::create(animate));

    auto moveAction = MoveBy::create(1.f, Vec2(-unit->getMoveSpeed()*3, 0));
    unit->runAction(RepeatForever::create(moveAction));
}

void UnitState_Walk::RunState(Unit* unit)
{
    if (unit->getPositionX() < 10)
    {
        unit->removeFromParentAndCleanup(true);
    }
}

void UnitState_Walk::EndState(Unit* unit)
{

}

state 인터페이스를 상속받아 걷는 상태를 구현하였다. 


bool BattleScene::onSprTouchBegan(Touch* touch, Event* event)
{
    auto target = event->getCurrentTarget();
    Point pos = target->convertToNodeSpace(touch->getLocation());
    Rect rect = Rect(0, 100, target->getContentSize().width, 320);
    if (rect.containsPoint(pos))
    {
        auto swordman = Swordman::create();
        swordman->setPosition(pos);
        this->addChild(swordman,2);
        swordman->scheduleUpdate();
    }
    return false;
}

그 다음 클릭할 때마다 생성되게 해놓으면

autorelease pool도 잘 작동하고 있는 것을 볼 수 있다.

처음에는 std::unordered_map으로 짰다가 바로 버그를 여러개 만들었는데, cocos2d::Map으로 바꿔서 간단하게 해결하였다.

역시 엔진에서 정해놓은 대로 쓰는 것이 맘 편한 듯..


상태 머신을 처음으로 구현해본데다, 그냥 느낌 가는대로 만들어서 이렇게 만들어도 되는 것인지 잘 모르겠다.

기능 하나씩 추가하다 보면 분명 문제가 생기지 않을까?

그러면 그때 또 해결하는 것이 공부가 되겠지~

Posted by RPG만들기XP
,