openGL & UI坐标体系
OpenGL坐标系:该坐标原点在屏幕左下角,x轴向右,y轴向上。这也就是cocos2dx中用到的坐标系。
屏幕坐标系:该坐标系的原点在屏幕左上角,x轴向右,y轴向下,其实和OpenGL坐标系的差别也就是y轴的方向。假设游戏场景的分辨率为(500,500),其中一个点坐标为(200,200),那么它在OpenGL坐标系中的坐标还是(200,200),在屏幕坐标系中则倒过来,则为(200,500-200)。其实也就是6和9的差别。
图: UI坐标系
图: GL坐标系
2 转化函数
CCDirector::sharedDirector()->convertToUI();
CCDirector::sharedDirector()->convertToGL();
节点坐标系:又名相对坐标系,本地坐标,和OpenGL坐标系方向一致,不同的是原点的父节点左下角。
世界坐标系:又名绝对坐标系,世界即指游戏世界,我们只要知道世界坐标系和OpenGL坐标系方向一致,原点在屏幕左下角,x轴向右,y轴向上。
节点坐标与世界坐标转化
几乎所有的游戏引擎都会使用本地坐标系而非世界坐标系来指定元素
的位置,这样做的好处是当计算物体运动的时候使用同一本地坐标系的元素
可以作为一个子系统独立计算,最后再加上坐标系的运动即可,这是物理研
究中常用的思路。例如一个在行驶的车厢内上下跳动的人,我们只需要在每
帧绘制的时候计算他在车厢坐标系中的位置,然后加上车的位置就可以计算
出人在世界坐标系中的位置,如果使用单一的世界坐标系,人的运动轨迹就
变复杂了。
3 关于坐标体系的案例:
Coordinate.h
#ifndef __COORDINATE_H__
#define __COORDINATE_H__
#include "cocos2d.h"
USING_NS_CC;
//坐标体系
class Coordinate :public CCLayer
{
public:
static CCScene * scene();
CREATE_FUNC(Coordinate);
bool init();
//触摸事件开始的一个事件,第二个参数只是为了做苹果的兼容才保留的
virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
};
#endif
Coordinate.cpp
#include "Coordinate.h"
#include "AppMacros.h"
CCScene * Coordinate::scene() {
CCScene * scene = CCScene::create();
Coordinate * layer = Coordinate::create();
scene->addChild(layer);
return scene;
}
bool Coordinate::init()
{
CCLayer::init();
//打开触摸开关
setTouchEnabled(true);
//下面的kCCTouchesOneByOne是一个枚举:
//typedef enum {
// kCCTouchesAllAtOnce,
// kCCTouchesOneByOne,
//} ccTouchesMode;
setTouchMode(kCCTouchesOneByOne);
//创建一个精灵
CCSprite *big = CCSprite::create();
big->setColor(ccRED);
//设置锚点
big->setAnchorPoint(ccp(0, 0));
//表示的是一个矩形,CCRectMake是一个宏
big->setTextureRect(CCRectMake(0,0,150,150));
big->setPosition(ccp(100,100));
addChild(big);
CCSprite *little = CCSprite::create();
little->setColor(ccYELLOW);
little->setAnchorPoint(ccp(0,0));
little->setTextureRect(CCRectMake(0, 0, 50, 50));
little->setPosition(ccp(100,100));
//从下面可以知道一个精灵中可以添加另外一个精灵
big->addChild(little);
CCLog("little x = %f,y = %f", little->getPositionX(), little->getPositionY());
CCPoint toWorld = big->convertToWorldSpace(little->getPosition());
CCLog("toWorld x = %f,y=%f", toWorld.x, toWorld.y);
CCSprite *little2 = CCSprite::create();
little2->setColor(ccGREEN);
little2->setAnchorPoint(ccp(0, 0));
little2->setTextureRect(CCRectMake(0,0,50,50));
little2->setPosition(ccp(0,0));
addChild(little2);
CCPoint toNode = big->convertToNodeSpace(little2->getPosition());
CCLog("little2 x = %f,y = %f", little2->getPositionX(), little2->getPositionY());
CCLog("toNode x = %f,y = %f", toNode.x, toNode.y);
CCMoveBy *by = CCMoveBy::create(2,ccp(200,0));
CCMoveBy *by2 = (CCMoveBy *)by->reverse();
//最后一个NULL是一个哨兵
CCSequence *seq = CCSequence::create(by, by2, NULL);
big->runAction(CCRepeatForever::create(seq));
//第一个参数是:duration
//第二个参数是:移动位置.表示上下移动
CCMoveBy *lby = CCMoveBy::create(2, ccp(0, -100));
CCMoveBy *lby2 = (CCMoveBy *)lby->reverse();
CCSequence *lseq = CCSequence::create(lby, lby2, NULL);
little->runAction(CCRepeatForever::create(lseq));
return true;
}
//触摸事件开始
bool Coordinate::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)
{
CCLog("ccTouchBegan");
//基于OpenGL的世界坐标
CCPoint pGl = pTouch->getLocation();
CCLog("GL:x = %f,y = %f", pGl.x, pGl);
//基于UI屏幕的坐标
CCPoint pUi = pTouch->getLocationInView();
CCLog("UI:x = %f,y = %f", pUi.x, pUi.y);
//将基于GL的坐标转换成为UI的屏幕坐标
CCPoint toUi = CCDirector::sharedDirector()->convertToUI(pGl);
CCLog("ToUix = %f ,y = %f", toUi.x, toUi.y);
//将屏幕坐标的转换成为本地坐标
CCPoint toGL = CCDirector::sharedDirector()->convertToGL(pUi);
CCLog("ToGLx = %f,y=%f", toGL.x, toGL.y);
//转换成节点坐标
CCPoint node = this->convertToNodeSpace(pGl);
CCLog("Node:x = %f,y = %f", node.x, node.y);
return false;
}
运行结果: