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으로 바꿔서 간단하게 해결하였다.
역시 엔진에서 정해놓은 대로 쓰는 것이 맘 편한 듯..
상태 머신을 처음으로 구현해본데다, 그냥 느낌 가는대로 만들어서 이렇게 만들어도 되는 것인지 잘 모르겠다.
기능 하나씩 추가하다 보면 분명 문제가 생기지 않을까?
그러면 그때 또 해결하는 것이 공부가 되겠지~