想做一个关卡需求是这样的:
点击关卡按钮player会从当前关卡移动到目标按钮关卡的位置,同事背景也要移动,并且保证背景没有黑边的情况下,尽量使player位于x轴y轴的中间位置。
如果不能滚动的话,直接移动背景就好了,现在需求滑动也能选择关卡,那么久需要用scrollView并设置一下containLayer的offset了。
初始化的scrollView时候scrollView位于左上角,设置也没有作用,现在发现的只能这么做设置一下time让它有个动作移动到目的位置了。
auto innerSize = scView->getInnerContainer()->getContentSize();
auto scViewSize = scView->getContentSize();
scViewPos = Vec2(innerSize.width - scViewSize.width,scViewSize.height-innerSize.height);
ScrollView是按百分比移动的,其中百分比的目标宽度是scViewPos.x,目标高度是scViewPos.y注意目标高度是负值。因为cocos初始化的时候是在左上角的,也就是向下移动了
innerSize.height - scViewSize.height距离。
上代码:
.h
#ifndef LevelLayer_H__
#define LevelLayer_H__
#include "BasicLayer.h"
#include "Define.h"
#include "cocostudio/CocoStudio.h"
#include "ui/CocosGUI.h"
#include "Tools.h"
using namespace ui;
using namespace std;
class LevelLayer : public BasicLayer
{
public:
LevelLayer(){};
~LevelLayer(){};
static Scene* scene();
virtual bool init();
void initData();
void initView();
void btn_callBack(Ref *pSender, Widget::TouchEventType type);
void test(float dt);
CREATE_FUNC(LevelLayer);
public:
Size bgSize;
int curPageIndex;
ScrollView* scView;
Sprite* hero;
vector<Vec2> levPoints;
//当前scViewPos 也就是innerlayer多出view部分 宽度为正 高度为负
Vec2 scViewPos;
//当前scview占得百分比
Vec2 percentPos;
};
#endif
.cpp
#include "LevelLayer.h"
#include "math.h"
Scene* LevelLayer::scene()
{
auto sc = Scene::create();
auto layer = LevelLayer::create();
sc->addChild(layer);
return sc;
}
bool LevelLayer::init()
{
BasicLayer::init();
initData();
initView();
return true;
}
void LevelLayer::initData()
{
curPageIndex = 1;
}
void LevelLayer::initView()
{
Node* root = CSLoader::createNode("LevelLayer.csb");
this->addChild(root);
hero = (Sprite*)seekNodeByName(root, "hero");
auto bg = (Sprite*)seekNodeByName(root, "levelBg");
bgSize = bg->getContentSize();
scView = (ScrollView*)seekNodeByName(root, "scrollView");
auto innerSize = scView->getInnerContainer()->getContentSize();
auto scViewSize = scView->getContentSize();
scViewPos = Vec2(innerSize.width - scViewSize.width,scViewSize.height-innerSize.height);
percentPos = Vec2(0, 100);
scView->scrollToPercentBothDirection(percentPos, 4.5f, true);
for(int i=1;i<=EVERY_LEVEL_NUMES;i++)
{
const char* btName = String::createWithFormat("button_%02d",i)->getCString();
auto node = (Button*)seekNodeByName(root, btName);
node->addTouchEventListener(CC_CALLBACK_2(LevelLayer::btn_callBack, this));
auto pos = node->getPosition();
// CCLOG("i = [posX:%f posy:%f tag:%d]",pos.x,pos.y,node->getTag());
levPoints.push_back(pos);
}
this->schedule(schedule_selector(LevelLayer::test), 0.2f);
}
void LevelLayer::btn_callBack(Ref *pSender, Widget::TouchEventType type)
{
if(type == Widget::TouchEventType::ENDED)
{
CCLOG("btn_callBack");
Button* btn = (Button*)pSender;
int tag = btn->getTag();
auto curPos = hero->getPosition();
auto aimPos = levPoints[tag-1];
float dis = curPos.distance(aimPos);
CCLOG("dis:%f",dis);
float moveTime = dis * 0.01f;
auto moveTo = MoveTo::create(moveTime, aimPos);
hero->runAction(moveTo);
CCLOG("i = [posX:%f posy:%f tag:%d]",aimPos.x,aimPos.y,tag);
int x = MAX(aimPos.x, winWidth / 2);
int y = MAX(aimPos.y, winHeight/ 2);
x = MIN(x, bgSize.width - winWidth/2);
y = MIN(y, bgSize.height - winHeight/2);
auto goodPoint = Vec2(x, y);
auto centerOfScreen = winCenter;
centerOfScreen.subtract(goodPoint);
// auto bg = hero->getParent();
// auto bgMove = MoveTo::create(moveTime, centerOfScreen);
// bg->runAction(bgMove);
float perX = centerOfScreen.x/scViewPos.x*100;
float perY = centerOfScreen.y/scViewPos.y*100;
CCLOG("[center:]%f %f [%f %f]",centerOfScreen.x,centerOfScreen.y,perX,perY);
Vec2 perPos = Vec2(perX , perY);
Vec2 curPrePos = percentPos - perPos;
curPos = scView->getInnerContainer()->getPosition();
CCLOG("curpos:%f %f",curPos.x,curPos.y);
scView->scrollToPercentBothDirection(curPrePos, moveTime, true);
}
}
void LevelLayer::test(float dt)
{
auto layer = scView->getInnerContainer();
CCLOG("layer:%f %f",layer->getPositionX(),layer->getPositionY());
}
测试图片: