最近做东西遇到的小问题,之前没怎么看过,就今天特地拿出来写个demo,记住这个问题。
一、笛卡儿坐标系
OpenGl坐标系为笛卡儿右手系。x向右,y向上,z向外。
我之前开发的是android坐标系为屏幕坐标系是以屏幕左上角为坐标原点,x轴向右逐渐增大,y轴向下逐渐增大。而在cocos2d-lua中坐标系原点在屏幕的左下角,x向右,y向上,z则是指的zorder(层级)。
二、世界坐标系,本地坐标系
世界坐标系的原点固定在屏幕的左下角。
本地坐标是和节点相关的坐标系,每个节点都有独立的坐标系,是以节点左下角为原点。当节点移动或改变方向时,和该节点关联的坐标系将随之移动或者改变方向。
三、锚点
锚点Anchor Point的两个参数范围在0-1 之间,他们是乘数因子。比如(0.5,0.5)表示锚点位于节点长乘于0.5,宽*0.5的位置。
在cocos2d-lua中,Layer的锚点默认值(0,0) node的锚点默认值(0.5,0.5)
下面给个代码看看效果
local red = cc.LayerColor:create(cc.c4b(255,100,100,128))
red:setContentSize(display.width/2,display.height/2)
local green = cc.LayerColor:create(cc.c4b(100,255,100,128))
green:setContentSize(display.width/4,display.height/4)
red:addChild(green)
self:addChild(red)
可以看到位置默认是这样的,但是有一点要提醒就是Layer默认忽视锚点,所以我们要测试就要设置
red:ignoreAnchorPointForPosition(false)
local red = cc.LayerColor:create(cc.c4b(255,100,100,128))
red:setContentSize(display.width/2,display.height/2)
red:ignoreAnchorPointForPosition(false)
red:setAnchorPoint(0.5,0.5)
red:setPosition(display.width/2,display.height/2)
local green = cc.LayerColor:create(cc.c4b(100,255,100,128))
green:setContentSize(display.width/4,display.height/4)
green:ignoreAnchorPointForPosition(false)
green:setAnchorPoint(0,0)
red:addChild(green)
self:addChild(red)
这里就剩z轴没说了,但是z轴和本次讨论问题没关系就不详细介绍了。
在Quick开发的2D游戏中,z轴不影响物体在屏幕上显示的远近,它只与渲染顺序有关系,z轴值小的node最先被渲染。
4、世界坐标和本地坐标的转化
好了,前面铺垫了那么多。我们终于到了正题,世界坐标系和本地坐标系的转化。
转换主要依赖于convertToNodeSpace和convertToWorldSpaceAR这两个方法
convertToNodeSpace将世界坐标转换为本地坐标系
convertToWorldSpaceAR将本地坐标系转换为世界坐标系
先演示世界坐标转换为本地坐标
local spriteOne=CCScale9Sprite:create("extensions/leimu.jpg")
local spriteTwo=CCScale9Sprite:create("extensions/oumu.jpg")
spriteOne:setScale(0.7)
spriteTwo:setScale(0.4)
spriteOne:setPosition(ccp(400,500))
spriteOne:setAnchorPoint(1,1)
spriteTwo:setPosition(ccp(200,300))
spriteTwo:setAnchorPoint(0.5, 0.5)
spriteTwo:setAnchorPoint(0.5,0.5)
self:addChild(spriteOne)
self:addChild(spriteTwo)
--世界坐标转换为本地坐标
local x,y = spriteTwo:getPosition()
local point1 = spriteOne:convertToNodeSpace(ccp(x,y))
print('point1'..point1.x..'=='..point1.y)
红绿看腻了吧 ,咱们这次换个养眼=。=
结果
[0.4802] point1-105.71431732178==-65.714302062988
看到了吧,有负数值不用对就知道转换为相对于蕾姆的本地坐标系了
下一步演示本地坐标转换为世界坐标系
local spriteOne=CCScale9Sprite:create("extensions/leimu.jpg")
local spriteTwo=CCScale9Sprite:create("extensions/oumu.jpg")
spriteOne:setScale(0.7)
spriteTwo:setScale(0.4)
spriteOne:setAnchorPoint(0,0)
spriteOne:setPosition(ccp(300,400))
spriteTwo:setAnchorPoint(0, 0)
spriteTwo:setPosition(ccp(0,0))
spriteOne:addChild(spriteTwo)
self:addChild(spriteOne)
local x,y = spriteTwo:getPosition()
local point = spriteOne:convertToWorldSpaceAR(ccp(x,y))
print('point'..point.x..'=='..point.y)
继续展示
point300==400
从结果我们可以看出来,本地坐标系成功转换为世界坐标系
好了,今天就到此结束,(去玩游戏了( ⊙ o ⊙ )!)