cocos基礎教程(6)坐標與錨點講解


坐標系詳解

Cocos2d-x坐標系和OpenGL坐標系相同,都是起源於笛卡爾坐標系。原點為屏幕左下角,x向右,y向上。

世界坐標系(World Coordinate) VS 本地坐標系(Node Local)

世界坐標系也叫做絕對坐標系,本地坐標系也叫相對坐標系,是和節點相關聯的坐標系。每個節點都有獨立的坐標系,當節點移動或改變方向時,和該節點關聯的坐標系將隨之移動或改變方向。我們通過Node的setPosition設定元素的位置使用的是相對與其父節點的本地坐標系而非世界坐標系。最后在繪制屏幕的時候cocos2d會把這些元素的本地坐標映射成世界坐標系坐標。

錨點(Anchor Point)

錨點是子節點相對於父節點設置位置時候的,一個基准參考點。設置這個參考點對應父節點上的位置。

  • Anchor Point的兩個參數都在0~1之間。它們表示相對百分比位置。(0.5, 0.5)表示Anchor Point位於節點長度乘0.5和寬度乘0.5的地方,即節點的中心
  • 在Cocos2d-x中Layer的Anchor Point為默認值(0, 0),其他Node的默認值為(0.5, 0.5)。
  • 因為Layer比較特殊,它默認忽略錨點,所以要調用ignoreAnchorPointForPosition()接口來改變錨點,關於ignoreAnchorPointForPosition()接口的使用說明,請看一下示例。
auto red = LayerColor::create(Color4B(255, 100, 100, 128), visibleSize.width/2, visibleSize.height/2);
red->ignoreAnchorPointForPosition(false);
red->setAnchorPoint(Point(0.5, 0.5));
red->setPosition(Point(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));

auto green = LayerColor::create(Color4B(100, 255, 100, 128), visibleSize.width/4, visibleSize.height/4);
green->ignoreAnchorPointForPosition(false);
green->setAnchorPoint(Point(1, 1));
red->addChild(green);

this->addChild(red, 0);

gnore Anchor Point全稱是ignoreAnchorPointForPosition,開啟錨點自由定位的方法。

  • 如果設置其值為true,則圖片資源的Anchor Pont固定為左下角,否則即為所設置的位置。
  • 如果設置其值為false,則可以通過setAnchorPoint重新設置錨點的位置。

VertexZ,PositionZ和zOrder

  • VerextZ是OpenGL坐標系中的Z值
  • PositionZ是Cocos2d-x坐標系中Z值
  • zOrder是Cocos2d-x本地坐標系中Z值

在實際開發中我們只需關注zOrder,可以通過setPositionZ接口來設置PositionZ。

  • PositionZ是全局渲染順序即在根節點上的渲染順序。
  • zOrder則是局部渲染順序,即該節點在其父節點上的渲染順序,與Node的層級有關。

實例代碼:

   auto red = LayerColor::create(Color4B(255, 100, 100, 255), visibleSize.width/2, visibleSize.height/2);
    red->ignoreAnchorPointForPosition(false);
    red->setPosition(Point(visibleSize.width / 2, visibleSize.height / 2));

    auto green = LayerColor::create(Color4B(100, 255, 100, 255), visibleSize.width/4, visibleSize.height/4);
    green->ignoreAnchorPointForPosition(false);
    green->setPosition(Point(visibleSize.width / 2, visibleSize.height / 2 - 100));
    red->setPositionZ(1);
    green->setPositionZ(0);
    this->addChild(red, 0);
    this->addChild(green, 1);

雖然green的zOrder大於red的zOder,但是因為red的PositionZ較大,所以red還是在green上面顯示。

觸摸點(Touch position)

處理觸摸事件時需要用重寫以下四個函數:

virtual bool onTouchBegan(Touch *touch, Event * event);
virtual void onTouchEnded(Touch *touch, Event * event);
virtual void onTouchCancelled(Touch *touch, Event * event);
virtual void onTouchMoved(Touch *touch, Event * event);

在函數中獲取到touch,我們在設計游戲邏輯時需要用到觸摸點在Cocos2d坐標系中的位置,就需要將touch的坐標轉換成OpenGL坐標系中的點坐標。

Touch position是屏幕坐標系中的點,OpenGL position是Cocos2d-x用到的OpenGL坐標系上的點坐標。通常我們在開發中會使用兩個接口getLocation()getLocationInView()來進行相應坐標轉換工作。

此外,關於世界坐標系和本地坐標系的相互轉換,在Node中定義了以下四個常用的坐標變換的相關方法。

    // 把世界坐標轉換到當前節點的本地坐標系中
    Point convertToNodeSpace(const Point& worldPoint) const;

    // 把基於當前節點的本地坐標系下的坐標轉換到世界坐標系中
    Point convertToWorldSpace(const Point& nodePoint) const;

    // 基於Anchor Point把基於當前節點的本地坐標系下的坐標轉換到世界坐標系中
    Point convertToNodeSpaceAR(const Point& worldPoint) const;

    // 基於Anchor Point把世界坐標轉換到當前節點的本地坐標系中
    Point convertToWorldSpaceAR(const Point& nodePoint) const;

下面通過一個例子來說明這四個方法的理解和作用:

    auto *sprite1 = Sprite::create("HelloWorld.png");
    sprite1->setPosition(ccp(20,40));
    sprite1->setAnchorPoint(ccp(0,0));
    this->addChild(sprite1);  //此時添加到的是世界坐標系,也就是OpenGL坐標系

    auto *sprite2 = Sprite::create("HelloWorld.png");
    sprite2->setPosition(ccp(-5,-20));
    sprite2->setAnchorPoint(ccp(1,1));
    this->addChild(sprite2); //此時添加到的是世界坐標系,也就是OpenGL坐標系

    //將 sprite2 這個節點的坐標ccp(-5,-20) 轉換為 sprite1節點 下的本地(節點)坐標系統的 位置坐標
    Point point1 = sprite1->convertToNodeSpace(sprite2->getPosition());

    //將 sprite2 這個節點的坐標ccp(-5,-20) 轉換為 sprite1節點 下的世界坐標系統的 位置坐標
    Point point2 = sprite1->convertToWorldSpace(sprite2->getPosition());

    log("position = (%f,%f)",point1.x,point1.y);
    log("position = (%f,%f)",point2.x,point2.y);
運行結果:

Cocos2d: position = (-25.000000,-60.000000)
Cocos2d: position = (15.000000,20.000000)

其中:Point point1 = sprite1->convertToNodeSpace(sprite2->getPosition());

相當於sprite2 這個節點添加到了sprite1這個節點上(實際並沒有),sprite2在世界坐標系中位置不變的,以sprite1作為假象父節點,來算出sprite2錨點相對於sprite1的本地坐標。

其中:Point point2 = sprite1->convertToWorldSpace(sprite2->getPosition());

相當於sprite2 這個節點添加到了sprite1這個節點上(實際並沒有),把sprite2目前的世界坐標作為相當於sprite1的本地坐標值后,這個時候sprite2的實際位置將會發生變化,算出sprite2變化后的世界坐標。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM