顯示具有 scale 標籤的文章。 顯示所有文章
顯示具有 scale 標籤的文章。 顯示所有文章

2016年6月2日 星期四

0602 cocos2d-x的anchorPoint錨點和scale縮放之間的配合方式

如果你有一個Node在一個盒子裡,盒子的錨點在左下角,這個Node一開始的時候是這個樣:position=(0, 0), anchorPoint=(0, 0), scale=1
然後更改它的scale讓它撐滿整個區域:position=(0, 0), anchorPoint=(0, 0), scale=1.09
這個時候重新設置它的錨點為右上角(1, 1),你認為會發生什麼?按照我的理解,我以為應該是這樣:position=(0, 0), anchorPoint=(1, 1), scale=1.09
但事實上,它卻是這樣!!!:position=(0, 0), anchorPoint=(1, 1), scale=1.09
原因在於,一個Node被設置了scale縮放後,其本身的錨點位置並沒有變,真實的錨點位置還是相對於原大小的位置,所以你注意我上圖中畫紅點的位置,那就是setAnchorPoint(1, 1)之後真實的錨點位置,然後cocos2d-x以新的錨點位置重新執行了scale(1.09)操作,就變成了上圖那個樣。
而左邊超出盒子的部分,其大小就是縮放比例1.09減去1之後乘以Node的原大小,也即
(node:getScale() - 1) * node:getContentSize().width
理解了這個,以後就不會踩坑了。
附一個設置錨點也不改變Node位置的方法:
-- 安全地設置錨點,用於錨點改變後node對象即便設置了scale縮放,其位置也不發生變化
function setSafeAnchor(node, anchorX, anchorY)
  local diffX = anchorX * node:getContentSize().width  * (node:getScaleX() - 1)
  local diffY = anchorY * node:getContentSize().height * (node:getScaleY() - 1)

  node:setAnchorPoint(anchorX, anchorY)
  node:setPositionX(node:getPositionX() + diffX)
  node:setPositionY(node:getPositionY() + diffY)
end

2016年4月20日 星期三

0419 Cocos2dx 小技巧 ScrollView實現縮放效果

Cocos2dx 小技巧(十四)ScrollView實現縮放效果

http://blog.csdn.net/star530/article/details/25658725

前天有個網友問我一些關於scrollView的用法,由於在QQ上實在講不清,所以就利用晚上的時間寫這篇博客出來了。
本篇要實現的功能是用scrollView 拖動對象時,對象移動到某個固定範圍會有放大、縮小的效果。下面開始。


在進入正題前我先簡短的介紹下scrollView應該怎麼用吧(想必大家也都會用~~):
1、記得在頭文件裡包含 「../extensions/cocos-ext.h",順便聲明下作用域:USING_NS_CC_EXT;
2、在類的繼承裡 加上ScrollViewDelegate,如下:
[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. class HelloWorld : public cocos2d::Layer,public ScrollViewDelegate  
3、在類的聲明中,加上三個scrollView的委託函數,如下:
[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. void scrollViewDidScroll(ScrollView* view);  
  2. void scrollViewDidZoom(ScrollView* view);  
  3. void scrollViewMoveOver(ScrollView* view);  
4、實在不想繼續說廢話了,直接看實例吧。

先看頭文件:
[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. #ifndef __HELLOWORLD_SCENE_H__  
  2. #define __HELLOWORLD_SCENE_H__  
  3.   
  4. #include "cocos2d.h"  
  5. #include "../extensions/cocos-ext.h"  
  6.   
  7. USING_NS_CC;  
  8. USING_NS_CC_EXT;  
  9.   
  10. class HelloWorld : public cocos2d::Layer,public ScrollViewDelegate  
  11. {  
  12. public:  
  13.     static cocos2d::Scene* createScene();//獲取歡迎畫面的Scene  
  14.     virtual bool init();    
  15.   
  16.     void menuCloseCallback(Ref* pSender);  
  17.       
  18.     CREATE_FUNC(HelloWorld);  
  19.   
  20.     //scroll 委託  
  21.     void scrollViewDidScroll(ScrollView* view);  
  22.     void scrollViewDidZoom(ScrollView* view);  
  23.     void scrollViewMoveOver(ScrollView* view);  
  24.   
  25. private:  
  26.     Vector<Sprite*> sp_vec;//聲明一個容器  
  27. };  
  28. #endif // __HELLOWORLD_SCENE_H__  

下面看定義
[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. bool HelloWorld::init()  
  2. {     
  3.     //首先創建scrollView  
  4.     auto scroll_layer = Layer::create();//創建scrollView中的容器層  
  5.     scroll_layer->setPosition(Point::ZERO);  
  6.     scroll_layer->setAnchorPoint(Point::ZERO);  
  7.     scroll_layer->setContentSize(Size(600,300));//設置容器層大小為(600,300)  
  8.   
  9.     auto scrollView = ScrollView::create(Size(400,300),scroll_layer);//創建scrollView,顯示窗口大小為(400,300)  
  10.     scrollView->setDelegate(this);//設置委託  
  11.     scrollView->setDirection(ScrollView::Direction::HORIZONTAL);//設置滾動方向為水平  
  12.     scrollView->setPosition(Point(300,200));  
  13.     this->addChild(scrollView,2);  
  14.   
  15.     //創建三個對象  
  16.     auto boy = Sprite::create("boy.png");//沒錯,主角又是我們熟悉的那仨。多麼溫馨。  
  17.     boy->setPosition(Point(150,100));  
  18.     scroll_layer->addChild(boy,2);  
  19.   
  20.     auto girl = Sprite::create("girl_1.png");  
  21.     girl->setPosition(Point(300,100));  
  22.     scroll_layer->addChild(girl,2);   
  23.   
  24.     auto girl3 = Sprite::create("girl_3.png");  
  25.     girl3->setPosition(Point(450,100));  
  26.     scroll_layer->addChild(girl3,2);   
  27.    
  28.     sp_vec.pushBack(boy);//將三個對象放入容器中  
  29.     sp_vec.pushBack(girl);  
  30.     sp_vec.pushBack(girl3);  
  31.   
  32.        return true;  
  33. }  

接下來看下scrollView的委託函數,這裡只要看scrollViewDidScroll 就好了。實現效果是對象在某個坐標範圍內移動時會有縮放效果。
[cpp] view plain copy
 在CODE上查看代碼片派生到我的代碼片
  1. void HelloWorld::scrollViewDidScroll(ScrollView* view)  
  2. {  
  3.     //在scrollView拖動時響應該函數  
  4.   
  5.     auto offsetPosX = (view->getContentOffset()).x;//獲得偏移X坐標(向右移動,偏移量為正數,向左則為負數)  
  6. //  CCLOG("offset pos is %f , %f",offsetPos.x,offsetPos.y);  
  7.   
  8.     //for 循環遍歷容器中的每個精靈  
  9.     for( auto e : sp_vec )  
  10.     {  
  11.         auto pointX = e->getPositionX();//獲得當前對象的X坐標(不管怎麼滾動,這個坐標都是不變的)  
  12.         float endPosX = pointX + offsetPosX;//將精靈的 X坐標 + 偏移X坐標  
  13.   
  14.         //當endPosX在 150~250 範圍,則對象的大小從左向右遞增  
  15.         if( endPosX > 150 && endPosX < 250 )  
  16.         {  
  17.             float x = endPosX / 150;//放大倍數為 endPosX / 150;  
  18.             e->setScale(x);  
  19.             CCLOG("x = %f",x);  
  20.         }  
  21.         //當endPosX在 250~350 範圍,則對象的大小從左向右遞減  
  22.         else if( endPosX > 250 && endPosX < 350 )   
  23.         {  
  24.             //下面這個公式不好解釋,我就這麼說吧:  
  25.             //假設 endPosX = 200,那麼放大倍數應該是 200 / 150 = 1.33左右,那麼當endPosX = 300時,出於對稱的原理,我們以250為對稱中心,那麼  
  26.             //300 的放大倍數也應該是 1.33。這就是下面的公式由來  
  27.             float a = endPosX - 250;  
  28.             float b = 250 - a;  
  29.   
  30.             float x = b / 150;  
  31.             e->setScale(x);  
  32.         }  
  33.         else   
  34.         {  
  35.             //不是在上面的範圍,則設置為正常大小  
  36.             e->setScale(1.0f);  
  37.         }  
  38.     }     
  39. }  
  40. void HelloWorld::scrollViewDidZoom(ScrollView* view)  
  41. {  
  42.     //do something  
  43. }  
  44. void HelloWorld::scrollViewMoveOver(ScrollView* view)  
  45. {  
  46.     //do something  
  47. }  

恩,註釋寫的很清楚啦,但我還是要稍微補充一些東東:我們應該知道,對象放到滾動層上(如scroll_layer->addChild(boy)),那麼不管對象在scrollView上如何移動,它獲得的坐標都是不會變的(如boy->getPosition()是不變的數值),這種情況下,如果我們想實現對象在某個坐標範圍內會有縮放效果,那麼只是去獲取對象的坐標肯定是行不通的,所以肯定要找一個時刻在變化的」參照物」來利用下,該找什麼呢?沒錯,就是scrollView的偏移坐標(scrollView->getContentOffset())!只要scrollView移動一下,那麼它的 偏移量也隨之改變。我這裡就是利用對象的坐標與scrollView的偏移坐標之間不可告人的秘密,從而實現當前的目的。
下面看下運行效果。

cocos2dx-lua 建立滑鼠監聽

重要關鍵字  EVENT_MOUSE_SCROLL addEventListenerWithSceneGraphPriority      if IsPc() then --建立滑鼠監聽         local listener = cc.EventListenerMouse...