無論是開發(fā)二維或三維游戲,我們都必須首先了解坐標(biāo)系的概念,在cocos 2d-x中,我們需要了解OpenGL坐標(biāo)系、世界坐標(biāo)系和節(jié)點坐標(biāo)系等等,下面是武林技術(shù)頻道小編詳解iOS游戲開發(fā)中Cocos2D的坐標(biāo)位置的關(guān)系,一起來看看吧!
接觸Cocos2D有段時間了,今天特意研究了下Cocos2D坐標(biāo)系中各種位置關(guān)系,anchor屬性,CCNode坐標(biāo)和地圖坐標(biāo)轉(zhuǎn)換。
??? 先看一段代碼:
?
-(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、地圖格子數(shù):
?
?
?
gameWorld.mapSize (10,10)????
?
4、地圖格子大小:
?
gameWorld.tileSize??? (20,20)
?
5、整個地圖大小:
?
???? gameWorld.mapSize * gameWorld.tileSize;
???? 當(dāng)然這里所說的是地圖格子是個正方形,非正方形也容易啦。
6、anchor屬性
?
???? 1) 添加一個精靈,這個精靈是個像素為1*1的紅色圖片,設(shè)置坐標(biāo)為20,20,即在地圖的第一個格子的右上角,設(shè)置anchorPoint為(0.5, 0.5)
???? 2) 再添加一個精靈,這個精靈是個像素為20*20的藍(lán)色圖片,設(shè)置坐標(biāo)為20,20,即在地圖的第一個格子的右上角,同樣設(shè)置anchorPoint為(0.5, 0.5)
???????? 運行效果是矩形精靈的中心和在點精靈的位置,即矩形精靈的錨點為第一個格子的右上角(20,20)坐標(biāo) 處
???? 去掉兩個精靈的anchorPoint屬性
????????? 運行效果和上面相同
???? 設(shè)置rectSprite的anchorPoint為ccp(0,0)
????????? 運行效果是矩形精靈的左下角與點精靈重合。
???? 設(shè)置rectSprite的anchorPoint為ccp(1,1)
????????? 運行效果是矩形精靈的右上角與點精靈重合。
???? 同理設(shè)置ccp(0.5, 1) , ccp(1, 0.5)等
???? 由上面可以得出:
???????? 1)anchorPoint屬性默認(rèn)為ccp(0.5, 0.5)
???????? 2)當(dāng)設(shè)置(0,0)時是以左下角為錨點
???????? 3)當(dāng)設(shè)置(1, 1)時是以右上角角為錨點
???????? 4)由此可以自己推論到底該把錨點設(shè)置在哪里
??? Cocos2D使用的是OpenGL坐標(biāo)系
??? OpenGL坐標(biāo)系:原點在左下角, X軸向右,Y軸向上
??? IPhone屏幕坐標(biāo)系:原點在左上角,X軸向右,Y軸向下
?? 很簡單的判斷方法:由于Cocos2D的坐標(biāo)系的原點在左下角。所以精靈內(nèi)部坐標(biāo)原點也是左下角,即當(dāng)anchorPoint為(0, 0)時即以左下角為錨點,為(1,1)時就以右上角為錨點,當(dāng)然(0.5, 0.5)就是以精靈中心為錨點了。由此可以推算出-2,-3....??? 2, 3....?? 等值時精靈錨點坐標(biāo)。
7、坐標(biāo)轉(zhuǎn)換
?
-(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采用不同的坐標(biāo)系,所以我們需要進(jìn)行坐標(biāo)轉(zhuǎn)換。
?
???? 1)首先獲取屏幕坐標(biāo)
???? 2)將屏幕坐標(biāo)轉(zhuǎn)換為OpenGL的坐標(biāo)
???? 3)將OpenGL的坐標(biāo)轉(zhuǎn)換為Cocos2D的坐標(biāo)。
???? 從運行結(jié)果可以看出Node1和Node2打印出的坐標(biāo)相同。因為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坐標(biāo)轉(zhuǎn)換為屏幕即quartz坐標(biāo)。
?? 4) convertTouchToNodeSpaceAR是將觸摸點轉(zhuǎn)換為相對于rectSprite的坐標(biāo)
?
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;?
}?
通過武林技術(shù)頻道小編介紹的詳解iOS游戲開發(fā)中Cocos2D的坐標(biāo)位置的關(guān)系,相信大家都有了一定的了解,如需了解更多的相關(guān)資訊,請繼續(xù)關(guān)注武林技術(shù)頻道吧!