2016年5月4日 星期三

0504 cocos2dx[3.2](16)——坐標系統

重點在於後面的座標觸碰偵測
    bool HelloWorld::onTouchBegan(Touch *touch, Event *unused_event)
    {
        //將觸點坐標, 轉換為相對節點sp的, 相對坐標
        Vec2 point = sp->convertTouchToNodeSpace(touch);
        //構造sp的尺寸矩形
        Size size = sp->getContentSize();
        Rect rect = Rect(0, 0, size.width, size.height);
        //判斷觸點是否觸摸到sp內部
        if (rect.containsPoint(point)) {
            CCLog("點中");
            return true;
        }
        return false;
    }
//

    //不可以用getBoundingBox 縮放會有問題
//    Rect boxRect2=m_IconBox->getBoundingBox();
//    boxRect2.origin=Vec2::ZERO;

http://shahdza.blog.51cto.com/2410787/1548486
cocos2dx[3.2](16)——坐標系統














【嘮叨】
    後半部分摘自  http://shahdza.blog.51cto.com/2410787/1550288

【小知識】
    Vec2:cocos2dx中的二維向量坐標類。



一、坐標系
    你可能在學校的幾何學上已經知道笛卡爾坐標系。
    如果你忘記了,下面的圖片可以讓你回憶一下:
wKiom1QHD7ih12uXAACFtUODbEo714.jpg

    有3種類型的坐標系在遊戲開發中你會用的到。
    (1)UI坐標系:              一般用於Android、IOS中:原點(x=0,y=0)在左上角。
                                (X方向從左側向右側遞增,Y方向從屏幕頂部向底部遞增)
    (2)Direct3D坐標系        DirectX,用左手笛卡爾坐標系。
    (3)OpenGL和cocos2dx坐標系:cocos2dx和OpenGL一樣,用右手坐標系。
 wKiom1QwNU2gEdpCAABJ4xvFGlw302.jpg        wKiom1QHEEjBvYkOAAApNrcbpIc124.jpg

    原點在屏幕的左下角,意味著屏幕在右手坐標系的第一象限中。
    X軸從屏幕左側向右側延伸,Y軸從屏幕底部向頂部延伸。
    底下有張圖片可以幫你理解cocos2dx坐標系:
wKioL1QHEKfx1U20AAC4dPxWKJI724.jpg

二、父類和子類
    每一個繼承自Node的類都有一個錨點屬性。當決定如何繪製對象(Sprite,Layer等等)的時候,cocos2dx將會考慮位置信息以及錨點信息。並且,當旋轉一個物體的時候,cocos2dx也會繞著錨點旋轉。
    我們創建一個藍色的Sprite圖像作為父對象,創建一個棕色的Sprite作為子對象。設置父對象的位置為Vec2(100,100),錨點Vec2(0,0);子對象的位置在Vec2(0,0),錨點Vec2(0.5,0.5)。
1
2
3
4
5
6
7
8
9
10
11
12
//
    Sprite* parent = Sprite::create("parent.png");
    parent->setAnchorPoint(Vec2(0, 0)); //錨點
    parent->setPosition(Vec2(100, 100));
    this->addChild(parent);
   
    //create child
    Sprite* child = Sprite::create("child.png");
    child->setAnchorPoint(Vec2(0.5, 0.5)); //錨點
    child->setPosition(Vec2(0, 0));
    parent->addChild(child); //添加子精靈到父精靈中
//

    我們設置了子對象的位置在Vec2(0,0),父對象的位置在Vec2(100,100)。
    因此,子對象顯示在如圖所示位置:
wKioL1QHEMCD3XvwAAEQ49QimA8160.jpg

三、錨點
    錨點被用於位置和旋轉物體。錨點是相對坐標(也就是一個百分比),經常被用來對應一個物體內的點。例如:錨點是Vec2(0.5,0.5),(表示x方向在物體50%的位置,y方向50%的位置)對應物體的中心。當設置物體位置的時候,調用setPositon時,錨點信息也會在坐標系中展示。相同的,當轉動物體,物體將會隨錨點轉動。
    例如:如下精靈有一個錨點Vec2(0,0),並且位置在Vec2(0,0)。
wKiom1QHENShGOjPAAASugHSI0w488.jpg
    因此,精靈被放置在屏幕左下角。
1
2
3
4
5
6
7
//
    //創建精靈
    Sprite* sprite = Sprite::create("bottomleft.png");
    sprite->setAnchorPoint(Vec2(0, 0)); //錨點
    sprite->setPosition(Vec2(0,0));
    this->addChild(sprite);
//

    在如下的例子中,展示了錨點坐標的相對性,錨點被賦值為Vec2(0.5,0.5),位於精靈的中心。
wKiom1QHEO2SPgtYAAATyWAX9OY107.jpg
1
2
3
4
5
6
7
//
    //創建精靈  
    Sprite* sprite = Sprite::create("center.png");
    sprite->setAnchorPoint(Vec2(0.5, 0.5)); //Anchor Point
    sprite->setPosition(Vec2(0,0));
    this->addChild(sprite);
//

    正如你所看到的的,精靈的中心位置被放置在了坐標原點(0,0)。這也就是說錨點不是一個像素值。錨點的X和Y值是相對於該節點的大小。
    你也可以設置錨點為Vec2(0.3,0.3),物體左下角錨點是(0,0),右上角是(1,1),因此Vec2(0.3,0.3)表示在X方向上30%位置,Y方向上30%位置。
wKioL1QHESWig7AvAACxLif71iE069.jpg



【渲染順序】
    在2.x中是使用Zorder來控制節點渲染的先後順序的。而在3.x中渲染的順序則是由兩個因素決定。
        > 全局Z順序:GlobalZOrder。所有節點之間對比。
        > 局部Z順序:LocalZOrder。 兄弟節點之間對比。
    且Z順序越小,最先渲染。

1、全局Z順序
    > 定義渲染節點的順序,擁有全局Z順序越小的節點,最先渲染。
    > 假設:兩個或者更多的節點擁有相同的全局Z順序,那麼渲染順序無法保證。唯一的例外是如果節點的全局Z順序為零,那麼場景圖順序是可以使用的。
    > 默認的,所有的節點全局Z順序都是零。這就是說,默認使用場景圖順序來渲染節點。
    > 全局Z順序是非常有用的當你需要渲染節點按照不同的順序而不是場景圖順序。
    > 侷限性: 全局Z順序不能夠被擁有繼承「SpriteBatchNode」的節點使用。
1
2
3
4
//
    virtual void setGlobalZOrder(float globalZOrder);
    virtual float getGlobalZOrder() const;
//

2、局部Z順序
    > LocalZOrder是「key」(關鍵)來分辨節點和它兄弟節點的相關性。
    > 父節點將會通過LocalZOrder的值來分辨所有的子節點。如果兩個節點有同樣的LocalZOrder,那麼先加入子節點數組的節點將會比後加入的節點先得到渲染,那麼先加入的節點會被後加入的節點遮蓋[update 20140927]。
    > 同樣的,場景圖使用「In-Order(按順序)」遍曆數算法來遍歷。並且擁有小於0的LocalZOrder的值的節點是「left」子樹(左子樹) 所以擁有大於0的LocalZOrder的值得節點是「right」子樹(右子樹)。
1
2
3
4
5
//
    //設置這個節點的局部Z順序((相對於兄弟節點))
    virtual void setLocalZOrder(int localZOrder);
    virtual int getLocalZOrder() const;
//



【坐標轉換】

1、坐標轉換函數
    坐標分為兩種坐標:
        > 世界坐標:就是相對節點的世界坐標。
        > 局部坐標:就是相對節點的坐標。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//
/**
 * 坐標轉換convertTo
 *     WorldSpace :   世界坐標
 *     NodeSpace  :  局部坐標
 *
 */
    //把世界坐標, 轉換到當前節點的本地坐標系中
    //基於Anchor Point, 把基於當前節點的本地坐標系下的坐標, 轉換到世界坐標系中
    Vec2 convertToNodeSpace(const Vec2& worldPoint) const;
    Vec2 convertToNodeSpaceAR(const Vec2& worldPoint) const;
    //把基於當前節點的本地坐標系下的坐標, 轉換到世界坐標系中
    //基於Anchor Point. 把世界坐標, 轉換到當前節點的本地坐標系中
    Vec2 convertToWorldSpace(const Vec2& nodePoint) const;
    Vec2 convertToWorldSpaceAR(const Vec2& nodePoint) const;
     
     
    //把觸點坐標, 轉換到當前節點的本地坐標系中
    Vec2 convertTouchToNodeSpace(Touch * touch) const;
    Vec2 convertTouchToNodeSpaceAR(Touch * touch) const;
//

2、舉例
wKioL1QXGdfRT4CEAABEcihIj24366.jpg        wKioL1QXGdeTLzlIAAA90sXMFdY199.jpg
    > node1坐標為:(20,40), 錨點(0,0)。
    > node2坐標為:(-5,-20),錨點(1,1)。
    > Vec2 point1 = node1->convertToNodeSpace(node2->getPosition());
        結果為:(-25,-60)。(即:相對node1節點坐標位置,的,相對坐標)
        分析  :node2相對node1節點的坐標為:(-5,-20) - (20,40) 。
                也就是說:node2相對node1的坐標位置。
    > Vec2 point2 = node1->convertToWorldSpace(node2->getPosition());
        結果為:(15,20)。(即:相對node1的世界坐標系統下,的,世界坐標)
        分析  :將node1作為參照,轉換到世界坐標為:(20,40) + (-5,-20) 。
                也就是說:node2的坐標現在被看做是相對node1的坐標位置,然後轉換到世界坐標。

3、在屏幕觸控中的應用 
    判斷觸摸點是否觸摸到某個精靈圖片sp的內部區域。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//
    bool HelloWorld::onTouchBegan(Touch *touch, Event *unused_event)
    {
        //將觸點坐標, 轉換為相對節點sp的, 相對坐標
        Vec2 point = sp->convertTouchToNodeSpace(touch);
        //構造sp的尺寸矩形
        Size size = sp->getContentSize();
        Rect rect = Rect(0, 0, size.width, size.height);
        //判斷觸點是否觸摸到sp內部
        if (rect.containsPoint(point)) {
            CCLog("點中");
            return true;
        }
        return false;
    }
//

沒有留言:

張貼留言

cocos2dx-lua 建立滑鼠監聽

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