カメラが自動で追尾する
cocos2dにはFollowという機能がある。
過去VerではCCFollowという名前になっているでしょう。
これは、特定のNodeに対して、画面が付いていくというActionです。
カメラがずっと追尾してくるようなものをイメージしてくれればOK。
実装はこんな感じになります。
this->runAction(Follow::create(cocos2d::Node *followedNode));
この一行で画面がfollowedNodeの動きに合わせて付いていきます。
Followのソースを見てみると
void Follow::step(float dt)
{
CC_UNUSED_PARAM(dt);
if(_boundarySet)
{
// whole map fits inside a single screen,
// no need to modify the position - unless map boundaries are increased
if(_boundaryFullyCovered)
return;
Point tempPos = _halfScreenSize - _followedNode->getPosition();
_target->setPosition(Point(clampf(tempPos.x, _leftBoundary, _rightBoundary),
clampf(tempPos.y, _bottomBoundary, _topBoundary)));
}
else
{
_target->setPosition(_halfScreenSize - _followedNode->getPosition());
}
}
このように、指定NodeがAnchorPointに来るように画面が付いていくのが分かります。
boundarySet?
Follow::createする時に引数でrectを指定することが出来ます。
これは、カメラの追尾範囲を決めることが出来るというものです。
注意としては、この追尾範囲が画面サイズより小さかった場合、
追尾する必要がないため追尾しない、という動きになります。
(_boundaryFullyCoveredに引っかかります)
ピーキー過ぎてお前には無理だよ
このFollow。"遊び"が無く、リアルタイムで追尾するため、
キャラが激しく動くアクションゲームだったりすると
上下左右に激しく揺れるため、目が回ってしまいます。
ちょっと使いにくいですね。
じゃあカスタムしちゃいましょう。
拡張してみる
CustomFollowという名前で作成。
通常の追尾機能に加えて、以下の3つの機能を加えます。
・X軸のみ追尾する
・Y軸のみ追尾する
・指定範囲外に出た時のみ追尾する
enum CustomFollowType{
kCustomFollowNone,
kCustomFollowXOnly,
kCustomFollowYOnly
};
class CustomFollow : public Follow
{
private:
CustomFollowType _type;
Rect _marginRect;
CustomFollow();
~CustomFollow();
public:
static CustomFollow* create(Node *followedNode);
static CustomFollow* create(Node *followedNode, CustomFollowType type);
static CustomFollow* create(Node *followedNode, Rect marginRect);
virtual void step(float dt) override;
};
CustomFollow::CustomFollow(){
_type = kCustomFollowNone;
_marginRect = Rect::ZERO;
}
CustomFollow::~CustomFollow(){
CC_SAFE_RELEASE(_followedNode);
}
CustomFollow* CustomFollow::create(Node* followNode){
CustomFollow *follow = new CustomFollow();
if (follow && follow->initWithTarget(followNode, Rect::ZERO))
{
follow->autorelease();
return follow;
}
CC_SAFE_DELETE(follow);
return nullptr;
}
CustomFollow* CustomFollow::create(Node* followNode, CustomFollowType type){
CustomFollow *follow = new CustomFollow();
follow->_type = type;
if (follow && follow->initWithTarget(followNode, Rect::ZERO))
{
follow->autorelease();
return follow;
}
CC_SAFE_DELETE(follow);
return nullptr;
}
CustomFollow* CustomFollow::create(Node* followNode, Rect marginRect){
CustomFollow *follow = new CustomFollow();
follow->_marginRect = marginRect;
if (follow && follow->initWithTarget(followNode, Rect::ZERO))
{
follow->autorelease();
return follow;
}
CC_SAFE_DELETE(follow);
return nullptr;
}
void CustomFollow::step(float dt)
{
CC_UNUSED_PARAM(dt);
if(_boundarySet)
{
if(_boundaryFullyCovered)
return;
Point tempPos = _halfScreenSize - _followedNode->getPosition();
float x = clampf(tempPos.x, _leftBoundary, _rightBoundary);
float y = clampf(tempPos.y, _bottomBoundary, _topBoundary);
if(_type == kCustomFollowXOnly){
y = _target->getPositionY();
}
else if (_type == kCustomFollowYOnly){
x = _target->getPositionX();
}
_target->setPosition(Point(x , y));
}
else
{
Point calcPos = _target->convertToWorldSpace(_followedNode->getPosition());
if(_marginRect.containsPoint(calcPos)){
return;
}
float x = _halfScreenSize.x - _followedNode->getPositionX();
float y = _halfScreenSize.y - _followedNode->getPositionY();
if(_type == kCustomFollowXOnly){
y = _target->getPositionY();
}
else if (_type == kCustomFollowYOnly){
x = _target->getPositionX();
}
_target->setPosition(Point(x , y));
}
}
こんな感じ。
使ってみる
静止画では伝わりませんね、はい。
X軸のみ、Y軸のみはイメージしやすいと思いますが、
指定範囲外に出ると追尾する、というのをちょっと説明。
画面外に出ると追尾するようにしてみる
指定はこんな感じ。
this->runAction(CustomFollow::create(player , Rect(x, y, visibleSize.width - x , visibleSize.height - y)));
これで、画面外に出た時のみカメラが追尾します。
あとがき
Follow機能については、まだまだ拡張出来る事が多いと思います。
ゼルダの伝説やロックマンのようにMoveしつつ追いかける。
追いかけた後、画面逆側が出るようにする。
などなど
色々と広がる機能なんですが、そのままではちょっと使いにくい…。
じゃあ拡張しちゃえ!と条件反射でやってみた事を書いてみました。
簡単でしたが、以上。Followのお話でしたー。