Coordinate System

Posted on 2013-09-14 10:59  Flex/AS Programmer  阅读(580)  评论(0编辑  收藏  举报

 

Introduction of Different Coordinate Systems

Cartesian Coordinate System

You probably have known "Cartesian Coordinate System" from school where it's heavily used in geometry lessons. If you have forgotten, these image will remind you quickly:

There're 3 types of coordinate system that you will meet in mobile games development.

UI Coordinate System

In common UI Coordinates on iOS/Android/Windows SDK:

  • The origin (x=0, y=0) is at the top-left corner.
  • X axis starts at the left side of the screen and increase to the right;
  • Y coordinates start at the top of the screen and increase downward,

looks like this

Direct3D Coordinate System

DirectX uses Left-handed Cartesian Coordinate.

OpenGL and Cocos2d Coordinate System

Cocos2d-x/-html5/-iphone uses the same coordinate system as OpenGL, which is so called "Right-handed Cartesian Coordinate System".

We only use x-axis & y-axis in 2D world. So in your cocos2d games:

  • The origin (x=0, y=0) is in the bottom-left corner of screen, which means the screen is in the first quartile of right-handed cartesian coordinate system,
  • X axis starts at the left side of the screen and increase to the right;
  • Y axis starts at the bottom of the screen and increase upwards.

And here’s a picture that helps illustrate Cocos2d-x Coordinates a bit better:

Note that it's different from common UI coordinate systems and DirectX coordinate systems.

Parent and Childrens

Every class derived from CCNode (Ultimate cocos2d-x class) will have a anchorPoint property.
When determining where to draw the object (sprite, layer, whatever), cocos2d-x will combine both properties position and anchorPoint. Also, when rotating an object, cocos2d-x will rotate it around its anchorPoint.

We create a sprite as a gray parent and another sprite as blue child.Set parent's position to ccp(100,100),child's anchor point in the center of circle .

 1    CCSprite* parent = CCSprite::create("parent.png");
 2    parent->setAnchorPoint(ccp(0, 0));// Anchor Point
 3    parent->setPosition(ccp(100, 100));
 4    parent->setAnchorPoint(ccp(0, 0));
 5    addChild(parent);
 6
 7    //create child 
 8    CCSprite* child = CCSprite::create("child.png");
 9    child->setAnchorPoint(ccp(0.5, 0.5));
10    child->setPosition(ccp(0, 0));
11    parent->addChild(child);//add child sprite into parent sprite.


Although we set child's position of ccp(0,0),parent's position is ccp(100,100).Therefore,child's position is :

Anchor Point

The anchor point is used for both positioning and rotating an object. The anchor point coordinates are relative coordinates which usually correspond to a point within an object. For example, the anchor point ccp(0.5, 0.5) corresponds to the center of the object. When setting the position of the object, the object is positioned such that the anchor point will be at the coordinates specified in the setPosition() call. Similarly, when rotating the object, it is rotated about the anchor point.

For example, this sprite has an anchorPoint of ccp(0,0) and a position of ccp(0,0):

As a result, the sprite is positioned such that its anchor point (which is located at the bottom-left corner) is placed at the bottom left corner of its parent layer.

1// create sprite
2CCSprite* sprite = CCSprite::create("bottomleft.png");
3sprite->setAnchorPoint(ccp(0, 0));// Anchor Point
4sprite->setPosition(ccp(0,0));
5addChild(sprite);


In the following example, the relative nature of the anchor co-ordinates is demonstrated. The anchor point is assigned to be ccp(0.5, 0.5), which corresponds to the center of the sprite.

1// create sprite
2CCSprite* sprite = CCSprite::create("center.png");
3sprite->setAnchorPoint(ccp(0.5, 0.5));// Anchor Point
4sprite->setPosition(ccp(0,0));
5addChild(sprite);


As you can see, the center of the sprite is positioned at ccp(0,0). It can also be seen that the anchor point is not a pixel value. The X and Y values of the anchor point are relative to the size of the node.

getVisibleSize, getVisibleOrigin vs getWinSize

VisibleSize returns visible size of the OpenGL view in points.The value is equal to getWinSize if don't invoke CCEGLView::setDesignResolutionSize().
getVisibleOrigin returns visible origin of the OpenGL view in points. Please refer to Multi resolution support for more details

How to convert co-ordinates

convertToNodeSpace:

convertToNodeSpace will be used in, for example, tile-based games, where you have a big map. convertToNodeSpace will convert your openGL touch co-ordinates to the co-ordinates of the .tmx map or anything similar.

Example:

The following picture shows that we have node1 with anchor point (0,0) and node2 with anchor point (1,1).

We invoke CCPoint point = node1->convertToNodeSpace(node2->getPosition()); convert node2's SCREEN coords to node1's local.As the result,node2 with the position of (-25,-60).

convertToWorldSpace:

convertToWorldSpace(const CCPoint& nodePoint) converts on-node coords to SCREEN coordinates.convertToWorldSpace will always return SCREEN position of our sprite, might be very useful if you want to capture taps on your sprite but need to move/scale your layer.
Generally, the parent node call this method with the child node position, return the world's postion of child's as a result. It seems make no sense calling this method if the caller isn't the parent...

Example:

1CCPoint point = node1->convertToWorldSpace(node2->getPosition()); 

the above code will convert the node2‘s coordinates to the coordinates on the screen.

For example if the position of node2 is (0, 0) which will be the bottom left corner of the node1, but not necessarily on the screen. This will convert (0, 0) of the node2 to the position of the screen(in this case is (15,20)). The result shows in the following picture:

convertToWorldSpaceAR,

convertToWorldSpaceAR will return the position relatevely to anchor point: so if our scene - root layer has Anchor Point of ccp(0.5f, 0.5f) - default, convertToWorldSpaceAR should return position relatively to screen center.

convertToNodeSpaceAR - the same logic as for .convertToWorldSpaceAR

Sample code:
 1
 2CCSprite *sprite1 = CCSprite::create("CloseNormal.png");
 3
 4sprite1->setPosition(ccp(20,40));
 5
 6sprite1->setAnchorPoint(ccp(0,0));
 7
 8this->addChild(sprite1);
 9
10CCSprite *sprite2 = CCSprite::create("CloseNormal.png");
11
12sprite2->setPosition(ccp(-5,-20));
13
14sprite2->setAnchorPoint(ccp(1,1));
15
16this->addChild(sprite2);
17
18CCPoint point1 = sprite1->convertToNodeSpace(sprite2->getPosition());
19
20CCPoint point2 = sprite1->convertToWorldSpace(sprite2->getPosition());
21
22CCPoint point3 = sprite1->convertToNodeSpaceAR(sprite2->getPosition());
23
24CCPoint point4 = sprite1->convertToWorldSpaceAR(sprite2->getPosition());
25
26CCLog("position = (%f,%f)",point1.x,point1.y);
27
28CCLog("position = (%f,%f)",point2.x,point2.y);
29
30CCLog("position = (%f,%f)",point3.x,point3.y);
31
32CCLog("position = (%f,%f)",point4.x,point4.y);
33

Result:

 1
 2position = (-25.000000,-60.000000)
 3
 4position = (15.000000,20.000000)
 5
 6position = (-25.000000,-60.000000)
 7
 8position = (15.000000,20.000000)
 9

References

Copyright © 2024 Flex/AS Programmer
Powered by .NET 9.0 on Kubernetes