I wrote a little Cocos2d-iPhone test app and committed the project to GitHub. (Like every dutiful hacker should.) You’re welcome to download the project and fool around with the code.
My goal was to figure out how to create a composite sprite, make sure it could respond to touches, and rotate and move it round the screen. With a little trial and error I got it working. Here’s how I did the hard parts:
I created a sprite from an PNG file and got it’s dimensions:
CCSprite * cocos2dGuy = [CCSprite spriteWithFile:@"avatar_n1_tang.png"]; CGSize spriteSize = cocos2dGuy.textureRect.size;
Then I created a CCNode to be the parent of my sprite sandwich. (I originally tried to use my cocos2dGuy CCSprite as the parent but Cocos2d stacks added on top of partent nodes and I wanted the particle effect under the cocos2dGuy not on top of him.) I set the size of the CCNode to the dimensions of the cocos2dGuy so that when you touch the CCNode it responds as if you’re touching the image. Then I add the CCNode to the layer. It’s also important to set the CCNode’s anchorPoint to the center (0.5, 0.5) as it’s default is bottom-left. CCSprite default to center anchorPoints and I want my CCNode to act like a proper sprite.
CCNode * composite = [CCNode node]; composite.anchorPoint = ccp(0.5,0.5); composite.contentSize = spriteSize; composite.position = centerPt; [self addChild:composite z:0 tag:kCompositeTag];
Next I added the cocos2dGuy sprite to the center of the composite CCNode. These two entities are now both the same size and stacked on top of each other. (It’s probably not necessary for me to set the cocos2dGuy’s anchorPoint and so I’ll remove that line of code down the road.)
cocos2dGuy.anchorPoint = ccp(0.5, 0.5); CGSize compositeSize = composite.contentSize; CGPoint compositeCenterPt = ccp(compositeSize.width/2,compositeSize.height/2); cocos2dGuy.position = compositeCenterPt; [composite addChild:cocos2dGuy z:1 tag:1];
Finally I created the custom CCParticleSystem from a Particle Designer file and added it to the composite CCNode but at a lower Z value show it shows up under the cocos2dGuy sprite. See how I had to set the position and the anchorPoint to ensure everything lined up.
CCParticleSystem * fx = [ARCH_OPTIMAL_PARTICLE_SYSTEM particleWithFile:@"fireball_small_fast_green.plist"]; fx.anchorPoint = ccp(0.5, 0.5); fx.position = compositeCenterPt; fx.duration = kCCParticleDurationInfinity; fx.scale = 2.0f; fx.autoRemoveOnFinish = YES; [composite addChild:fx z:0 tag:1];
Movement and animation are easy in the world of Cocos2d. I really like the visual effect of CCEaseExponentialInOut. It has a nice punch.
Handling touches are bit harder. I had to remember to set self.isTouchEnabled = YES in my init method and override both registerWithTouchDispatcher and ccTouchBegan. The key bit of code for responding to a touch is isTouchForMe:
bool hit = false; for(CCNode * node in [self children]) { if(node.tag == kCompositeTag) { hit = CGRectContainsPoint([node boundingBox], touchLocation); if (hit) { [self hiliteSprite:(CCSprite *)node]; } else { [self turnSprite:(CCSprite *)node andAttackPoint:touchLocation]; } } }
The main thing here is to give each touchable node a unique tag and test each node in the layer for that tag. If you touch the sprite he inflates for a moment. If you touch an empty part of the screen the sprite turns and launches himself at your finger. Ouch!
Comments
One response to “Sprite Playground”
Your using a fixed PNG image for the avatar, which means the look is generally static except for the Particle Designer animations. So one of my first thoughts was: can you replace the cocos2dGuy static assignment with an object handle of some sort that would allow animation of the sprite as well. For example, shifting its eyes in the direction of the finger it is about to crash into.