想做一个关卡需求是这样的:
点击关卡按钮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()); }
测试图片: