种妖记,智障康复训练,撒莲儿
接触cocos2d有段时间了,今天特意研究了下cocos2d坐标系中各种位置关系,anchor属性,ccnode坐标和地图坐标转换。
先看一段代码:
-(id) init
{
// always call "super" init
// apple recommends to re-assign "self" with the "super" return value
if( (self=[super init])) {
cctmxtiledmap *gameworld = [cctmxtiledmap tiledmapwithtmxfile:@"positiontext.tmx"];
[self addchild:gameworld];
cgsize winsize = [[ccdirector shareddirector] winsize];
cclog(@"gameworld.mapsize.width:%.2f gameworld.mapsize.height:%.2f",gameworld.mapsize.width, gameworld.mapsize.height);
cclog(@"gameworld.tilesize.width: %.2f gameworld.tilesize.height:%.2f", gameworld.tilesize.width, gameworld.tilesize.height);
cclog(@"winsize.width:%.2f winsize.height:%.2f", winsize.width, winsize.height);
ccsprite *pointsprite = [ccsprite spritewithfile:@"point.png"];
[gameworld addchild:pointsprite z:2 tag:1];
pointsprite.position = ccp(20,20);
pointsprite.anchorpoint = ccp(0.5, 0.5);
ccsprite *rectsprite = [ccsprite spritewithfile:@"myrect.png"];
[gameworld addchild:rectsprite z:1 tag:1];
rectsprite.position = ccp(20,20);
rectsprite.anchorpoint = ccp(0.5, 0.5);
}
return self;
}
1、加载地图:
cctmxtiledmap *gameworld = [cctmxtiledmap tiledmapwithtmxfile:@"positiontext.tmx"];
2、获取手机屏幕大小
cgsize winsize = [[ccdirector shareddirector] winsize];
3、地图格子数:
gameworld.mapsize (10,10)
4、地图格子大小:
gameworld.tilesize (20,20)
5、整个地图大小:
gameworld.mapsize * gameworld.tilesize;
当然这里所说的是地图格子是个正方形,非正方形也容易啦。
6、anchor属性
1) 添加一个精灵,这个精灵是个像素为1*1的红色图片,设置坐标为20,20,即在地图的第一个格子的右上角,设置anchorpoint为(0.5, 0.5)
2) 再添加一个精灵,这个精灵是个像素为20*20的蓝色图片,设置坐标为20,20,即在地图的第一个格子的右上角,同样设置anchorpoint为(0.5, 0.5)
运行效果是矩形精灵的中心和在点精灵的位置,即矩形精灵的锚点为第一个格子的右上角(20,20)坐标 处
去掉两个精灵的anchorpoint属性
运行效果和上面相同
设置rectsprite的anchorpoint为ccp(0,0)
运行效果是矩形精灵的左下角与点精灵重合。
设置rectsprite的anchorpoint为ccp(1,1)
运行效果是矩形精灵的右上角与点精灵重合。
同理设置ccp(0.5, 1) , ccp(1, 0.5)等
由上面可以得出:
1)anchorpoint属性默认为ccp(0.5, 0.5)
2)当设置(0,0)时是以左下角为锚点
3)当设置(1, 1)时是以右上角角为锚点
4)由此可以自己推论到底该把锚点设置在哪里
cocos2d使用的是opengl坐标系
opengl坐标系:原点在左下角, x轴向右,y轴向上
iphone屏幕坐标系:原点在左上角,x轴向右,y轴向下
很简单的判断方法:由于cocos2d的坐标系的原点在左下角。所以精灵内部坐标原点也是左下角,即当anchorpoint为(0, 0)时即以左下角为锚点,为(1,1)时就以右上角为锚点,当然(0.5, 0.5)就是以精灵中心为锚点了。由此可以推算出-2,-3.... 2, 3.... 等值时精灵锚点坐标。
7、坐标转换
-(id) init
{
// always call "super" init
// apple recommends to re-assign "self" with the "super" return value
if( (self=[super init])) {
cctmxtiledmap *gameworld = [cctmxtiledmap tiledmapwithtmxfile:@"positiontext.tmx"];
[self addchild:gameworld];
cgsize winsize = [[ccdirector shareddirector] winsize];
cclog(@"gameworld.mapsize.width:%.2f gameworld.mapsize.height:%.2f",gameworld.mapsize.width, gameworld.mapsize.height);
cclog(@"gameworld.tilesize.width: %.2f gameworld.tilesize.height:%.2f", gameworld.tilesize.width, gameworld.tilesize.height);
cclog(@"winsize.width:%.2f winsize.height:%.2f", winsize.width, winsize.height);
ccsprite *pointsprite = [ccsprite spritewithfile:@"point.png"];
[gameworld addchild:pointsprite z:2 tag:1];
pointsprite.position = ccp(20,20);
//pointsprite.anchorpoint = ccp(0.5, 0.5);
ccsprite *rectsprite = [ccsprite spritewithfile:@"myrect.png"];
[gameworld addchild:rectsprite z:1 tag:1];
rectsprite.position = ccp(40,40);
rectsprite.anchorpoint = ccp(2, 2);
[self setistouchenabled:yes];
}
return self;
}
- (void) registerwithtouchdispatcher {
[[cctouchdispatcher shareddispatcher] addtargeteddelegate:self priority:int_min + 1 swallowstouches:yes];
}
- (bool) cctouchbegan:(uitouch *)touch withevent:(uievent *)event {
cgpoint point = [touch locationinview: [touch view]];
cclog(@"screen coordx: %.2f coordy: %.2f", point.x, point.y);
point = [[ccdirector shareddirector] converttogl: point];
cclog(@"opengl coordx: %.2f coordy: %.2f", point.x, point.y);
point = [self converttonodespace: point];
cclog(@"ccnode1 coordx: %.2f coordy: %.2f", point.x, point.y);
point = [self converttouchtonodespace: touch];
cclog(@"ccnode2 coordx: %.2f coordy: %.2f", point.x, point.y);
point = [[ccdirector shareddirector] converttoui:point];
cclog(@"uiview coordx: %.2f coordy: %.2f", point.x, point.y);
point = [rectsprite converttouchtonodespacear:touch];
cclog(@"touchar coordx: %.2f coordy: %.2f", point.x, point.y);
return yes; ccnode
}
- (void) cctouchmoved:(uitouch *)touch withevent:(uievent*)event {
}
- (void) cctouchended:(uitouch *)touch withevent:(uievent*)event {
}
上面的代码添加了uiview的事件处理。由于屏幕和cocos2d采用不同的坐标系,所以我们需要进行坐标转换。
1)首先获取屏幕坐标
2)将屏幕坐标转换为opengl的坐标
3)将opengl的坐标转换为cocos2d的坐标。
从运行结果可以看出node1和node2打印出的坐标相同。因为cocos2d给我们写了coverttouchtonodespace方法,可以看看它的源码:
- (cgpoint)converttouchtonodespace:(uitouch *)touch
{
cgpoint point = [touch locationinview: [touch view]];
point = [[ccdirector shareddirector] converttogl: point];
return [self converttonodespace:point];
}
至于为什么opengl和node1输出既然相同,为什么还要使用converttonodespace,由于能力有限,希望大牛们能给告诉我答案。
uiview输出的是将cocos2d坐标转换为屏幕即quartz坐标。
4) converttouchtonodespacear是将触摸点转换为相对于rectsprite的坐标
8、判断触摸点是否在制定的精灵上
- (bool) cctouchbegan:(uitouch *)touch withevent:(uievent *)event {
cgpoint point = [touch locationinview: [touch view]];
cclog(@"screen coordx: %.2f coordy: %.2f", point.x, point.y);
point = [[ccdirector shareddirector] converttogl: point];
cclog(@"opengl coordx: %.2f coordy: %.2f", point.x, point.y);
point = [self converttonodespace: point];
cclog(@"ccnode1 coordx: %.2f coordy: %.2f", point.x, point.y);
point = [self converttouchtonodespace: touch];
cclog(@"ccnode2 coordx: %.2f coordy: %.2f", point.x, point.y);
//point = [[ccdirector shareddirector] converttoui:point];
//cclog(@"uiview coordx: %.2f coordy: %.2f", point.x, point.y);
cclog(@"%d", rectsprite.texturerect.size.width);
cgrect rect = [rectsprite texturerect];
rect = cgrectmake(0, 0, rect.size.width, rect.size.height);
cclog(@"orgx: %.2f orgy: %.2f width:%.2f height: %.2f",rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
point = [rectsprite converttouchtonodespacear:touch];
cclog(@"touchar coordx: %.2f coordy: %.2f", point.x, point.y);
if(cgrectcontainspoint(rect, point)) {
cclog(@"you touched in the rectsprite");
}
return yes;
}
9、获取触摸的是哪个tile,并改变该tile.
ccsprite *rectsprite;
cctmxtiledmap *gameworld;
int speed = 10;
-(id) init
{
// always call "super" init
// apple recommends to re-assign "self" with the "super" return value
if( (self=[super init])) {
gameworld = [cctmxtiledmap tiledmapwithtmxfile:@"positiontext.tmx"];
[self addchild:gameworld];
cgsize winsize = [[ccdirector shareddirector] winsize];
cclog(@"gameworld.mapsize.width:%.2f gameworld.mapsize.height:%.2f",gameworld.mapsize.width, gameworld.mapsize.height);
cclog(@"gameworld.tilesize.width: %.2f gameworld.tilesize.height:%.2f", gameworld.tilesize.width, gameworld.tilesize.height);
cclog(@"winsize.width:%.2f winsize.height:%.2f", winsize.width, winsize.height);
ccsprite *pointsprite = [ccsprite spritewithfile:@"point.png"];
[gameworld addchild:pointsprite z:2 tag:1];
pointsprite.position = ccp(20,20);
pointsprite.anchorpoint = ccp(0.5, 0.5);
rectsprite = [ccsprite spritewithfile:@"myrect.png"];
[gameworld addchild:rectsprite z:0 tag: 3];
rectsprite.position = ccp(40, 40);
rectsprite.anchorpoint = ccp(0, 0);
[self setistouchenabled:yes];
}
return self;
}
- (void) registerwithtouchdispatcher {
[[cctouchdispatcher shareddispatcher] addtargeteddelegate:self priority:int_min + 1 swallowstouches:yes];
}
- (bool) cctouchbegan:(uitouch *)touch withevent:(uievent *)event {
cgpoint point = [touch locationinview: [touch view]];
point = [self converttouchtonodespace: touch];
cclog(@"ccnode2 coordx: %.2f coordy: %.2f", point.x, point.y);
cgpoint tilepos = [self tileposition:point];
if(tilepos.x == -1 || tilepos.y == -1) return no;
cctmxlayer *ly = [gameworld layernamed:@"layer 0"];
if([ly tilegidat:tilepos] != 3) {
[ly settilegid:0 at: tilepos];
}
return yes;
}
- (void) cctouchmoved:(uitouch *)touch withevent:(uievent*)event {
}
- (void) cctouchended:(uitouch *)touch withevent:(uievent*)event {
}
- (cgpoint) tileposition:(cgpoint)pos {
cgpoint point;
cctmxlayer *ly = [gameworld layernamed:@"layer 0"];
if(ly== nil) {
cclog(@"error: layer not found!");
return ccp(-1, -1);
}
cgsize layersize = [ly layersize];
cgsize tilesize = [gameworld tilesize];
int x = pos.x / tilesize.width;
int y = layersize.height - pos.y / tilesize.height;
if((x >= 0) && (x < layersize.width) && (y >= 0) && (y < layersize.height)) {
point = ccp(x, y);
} else {
point = ccp(-1, -1);
}
if(point.x < 0) return ccp(-1, -1);
if(point.y < 0) return ccp(-1, -1);
if(point.x >= layersize.width) return ccp(-1, -1);
if(point.y >= layersize.height) return ccp(-1, -1);
cclog(@"%d, %d", x, y);
return point;
}
如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!!
点击进行留言回复
网友评论