2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

cocos2d-x 対象のキャラを移動させても常に画面に表示させる方法

Posted at

cocos2d-xでキャラが移動しても常に画面に表示させるにはFollowアクションを使う

3Dや2Dのゲームでは通常カメラという概念で表示を固定化させるが、
cocos2d-xではFollowアクションを使うことでカメラの代用をすることができる。
むしろFollowを使うのが普通なのかも

HelloWorldScene.cpp
//Rectはスクロール範囲 普通はマップの大きさ
Follow *follow = Follow::create(player, Rect(0, 0, 2000, 1334));
//これをLayerにアクションとして実行させる
this->runAction(follow);
2016-12-23.png

おまけ
これでは常に中央に表示される。
問題なのは横スクロールだけの場合とか縦スクロールだけとかの場合に
中央にキャラが表示されてはプレイしづらい。
オフセットの概念がFollowにはまだ実装されていないのでcocos2d-xのソースコードを修正する必要がある。
すでに修正した人がGitHubに公開しているのでそこへのURLを張ります。

コードそのもの:
https://github.com/AlwynC/cocos2d-x/blob/d22dca636182ac48f4d7f38bf33d251e427f6f10/cocos/2d/CCAction.cpp

公開しているサイト:
https://github.com/cocos2d/cocos2d-x/pull/15194/files

2016-12-23 (1).png
CCAction.h
//追加
public:
 static Follow* createWithOffset(Node* followedNode, float xOffset, float yOffset, const Rect& rect = Rect::ZERO);
 bool initWithTargetAndOffset(Node *followedNode, float xOffset, float yOffset, const Rect& rect);

//修正
 Follow()
    : _followedNode(nullptr)
    , _boundarySet(false)
    , _boundaryFullyCovered(false)
    , _leftBoundary(0.0)
    , _rightBoundary(0.0)
    , _topBoundary(0.0)
    , _bottomBoundary(0.0)
	, _offsetX(0) //これを追加
	, _offsetY(0) //これを追加
    , _worldRect(Rect::ZERO)
    {}

protected:
 float _offsetX; //追加
 float _offsetY; //追加
CCAction.cpp
//追加
Follow* Follow::createWithOffset(Node* followedNode, float xOffset, float yOffset, const Rect& rect/*= Rect::ZERO*/)
{
	Follow *follow = new (std::nothrow) Follow();
	bool valid;
	valid = follow->initWithTargetAndOffset(followedNode, xOffset, yOffset, rect);

	if (follow && valid)
	{
		follow->autorelease();
		return follow;
	}
	delete follow;

	return nullptr;
}

//追加
bool Follow::initWithTargetAndOffset(Node *followedNode, float xOffset, float yOffset, const Rect& rect)
{
	CCASSERT(followedNode != nullptr, "FollowedNode can't be NULL");
	if (followedNode == nullptr)
	{
		log("Follow::initWithTarget error: followedNode is nullptr!");
		return false;
	}

	followedNode->retain();
	_followedNode = followedNode;
	_worldRect = rect;
	_boundarySet = !rect.equals(Rect::ZERO);
	_boundaryFullyCovered = false;


	Size winSize = Director::getInstance()->getWinSize();
	_fullScreenSize.set(winSize.width, winSize.height);
	_halfScreenSize = _fullScreenSize * 0.5f;
	_offsetX = xOffset;
	_offsetY = yOffset;
	_halfScreenSize.x += _offsetX;
	_halfScreenSize.y += _offsetY;

	if (_boundarySet)
	{
		_leftBoundary = -((rect.origin.x + rect.size.width) - _fullScreenSize.x);
		_rightBoundary = -rect.origin.x;
		_topBoundary = -rect.origin.y;
		_bottomBoundary = -((rect.origin.y + rect.size.height) - _fullScreenSize.y);

		if (_rightBoundary < _leftBoundary)
		{
			// screen width is larger than world's boundary width
			//set both in the middle of the world
			_rightBoundary = _leftBoundary = (_leftBoundary + _rightBoundary) / 2;

		}
		if (_topBoundary < _bottomBoundary)
		{
			// screen width is larger than world's boundary width
			//set both in the middle of the world
			_topBoundary = _bottomBoundary = (_topBoundary + _bottomBoundary) / 2;
		}

		if ((_topBoundary == _bottomBoundary) && (_leftBoundary == _rightBoundary))
		{
			_boundaryFullyCovered = true;
		}
	}

	return true;
}


//修正
Follow* Follow::clone() const
{
    // no copy constructor
	return Follow::createWithOffset(_followedNode, _offsetX, _offsetY, _worldRect);
	/*
    auto a = new (std::nothrow) Follow();
    a->initWithTarget(_followedNode, _worldRect);
    a->autorelease();
    return a;
	*/
}

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?