Slide In and Slide Out animation like keyboard in cocos2d - cocos2d-iphone

I want to create a toolbar (initially hidden) with items that can be dragged. If a button is tapped, the toolbar will appear buttom-up (just like the animation of keyboard). I just like to ask how to do it in cocos2d.
Thanks for the response!

I used this code for drawer open and close.
-(void)showMyCocos2DDrawer
{
CGSize s = [[CCDirector sharedDirector] winSize];
self.position = ccp(-s.width,0.0f); //do this in ur init method :)
CGPoint pos =ccp(0.0f, 0.0f );
id moveTo = [CCMoveTo actionWithDuration:0.5f position:pos];
id calFun = [CCCallFunc actionWithTarget:self selector:#selector(animDone)];
id seq = [CCSequence actions:moveTo, calFun, nil];
[self runAction:seq];
}
-(void)hideCocos2DDrawer
{
CGSize s = [[CCDirector sharedDirector] winSize];
CGPoint pos =ccp(-s.width, 0.0f);
id moveTo = [CCMoveTo actionWithDuration:0.3f position:pos];
id calFun = [CCCallFunc actionWithTarget:self selector:#selector(goBack)];
id seq = [CCSequence actions:moveTo, calFun, nil];
[self runAction:seq];
}
-(void) animDone
{
//write in code here..
}
-(void)goBack
{
//write out code here..
}

Related

Cocos2d - Alternative for CCNode userData

I am using CCNode userData property to define whether a touched sprite has had a node built upon it (using Ray Wenderlich's - Tower Defence Tutorial).
The problem I am having is that for every new sprite position I touch and build upon, the previous ones are not retained in the sense that I am unable to sell the building built on it using my sell method.
What is the best way to save data to an individual CCSprite that is selected by touch, and defined by a property through a for loop?
I have read that subclassing CCSprite is an option, or creating a struct for userData etc. I have tried to implement these strategies but have been unsuccessful getting them to work.
touch method with sprite property:
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
for(UITouch *touch in touches){
CGPoint location = [touch locationInView:[touch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
for(CCSprite *tb in self.BuildPositions){
//BuildPositions contains CCSprites from a class defining build positions and contained in a mutable array.
if(CGRectContainsPoint([tb textureRect],[tb convertToNodeSpace:location ])){
_selectedBuildPosition = tb;
[self buildMenuTapped];
}
}
}
}
build menu method:
-(void)buildMenuTapped{
[self removeChild:_buildSelectMenu cleanup:YES];
[self removeChild:_sellBuildingMenu cleanup:YES];
if (_selectedBuildPosition.userData == nil) {
CCMenuItem *buildOption = [CCMenuItemImage itemWithNormalImage:#"building.png" selectedImage:#"building.png" target:self selector: #selector(buildOption)];
buildOption.position = ccpAdd(_selectedBuildPosition.position,ccp(0,40));
_buildSelectMenu = [CCMenu menuWithItems:BuildOption, nil];
_buildSelectMenu.position = CGPointZero;
[self addChild:_buildSelectMenu z:100];
}else{
[self sellBuildingMenu];
}
}
build upon method:
-(void)buildOption{
if([self canBuyBuilding] && !_selectedBuildPosition.userData){
_playerEssence -= kBUILD_COST;
_lvl1BuildNodeInstance = [lvl1BuildNode nodeWithTheGame:self location:_selectedBuildPosition.position];
//method as seen in RW tutorial. Generates a lvl1BuildNode class node within the HelloWorldLayer.
_selectedBuildPosition.userData = (__bridge void*)(_lvl1BuildNodeInstance);
}
}
sell menu method:
-(void)sellBuildingMenu{
[self removeChild:_buildSelectMenu cleanup:YES];
[self removeChild:_sellBuildingMenu cleanup:YES];
CCMenuItem *buildingSell = [CCMenuItemImage itemWithNormalImage:#"sell.png" selectedImage:#"sell.png" target:self selector:#selector(sellBuilding)];
buildingSell.position = ccpAdd(_selectedBuildPosition.position,ccp(40,0));
_sellBuildingMenu = [CCMenu menuWithItems:buildingSell, nil];
_sellBuildingMenu.position = CGPointZero;
[self addChild:_sellBuildingMenu z:100];
}
sell method:
-(void)sellBuilding{
if (_selectedBuildPosition.userData == (__bridge void*)(_lvl1BuildNodeInstance)){
[self removeChild:_lvl1GemNodeInstance cleanup:YES];
[_buildings removeObject:_lvl1BuildNodeInstance];
_playerEssence += kBUILD_COST;
_selectedBuildPosition.userData = nil;
}else{
}
}
Thank you for your time.

How do I pause all actions while fading cclayer then resume gameplay in cocos2d?

I have this:
-(void)fadeBackground
{
ccColor4B color = {0,0,0,255};
CCLayerColor *fadeLayer = [CCLayerColor layerWithColor:color];
[self addChild:fadeLayer z:7];
fadeLayer.opacity = 0;
id fade = [CCFadeTo actionWithDuration:1.0f opacity:200];//200 for light blur
id calBlk = [CCCallBlock actionWithBlock:^{
//show pause screen buttons here
//[self showPauseMenu];
}];
id fadeBack = [CCFadeTo actionWithDuration:2.0f opacity:0];
id sequen = [CCSequence actions:fade, calBlk, fadeBack, nil];
[fadeLayer runAction:sequen];
}
How do I stop the actions while the fadein occurs and resume them when the fadeBack occurs?
[[CCDirector sharedDirector] pause]; & [[CCDirector sharedDirector] resume]; will pause and resume the schedulers and actions throughout all the Sprites/Layers or any other cocos2d Nodes.
If you want to pause/resume a particular CCLayer along with children its containing,
////for pausing
[myLayer pauseSchedulerAndActions];
for(CCNode *child in myLayer.children){
[child pauseSchedulerAndActions];
}
///for resuming
[myLayer resumeSchedulerAndActions];
for(CCNode *child in myLayer.children){
[child resumeSchedulerAndActions];
}
To pause, you can use this call, need to call same for each menu in game.
[self pauseSchedulerAndActions];
[menu pauseSchedulerAndActions];
To resume:
[self resumeSchedulerAndActions];
[menu pauseSchedulerAndActions];

Cocos2d CCTouchBegan

I'm trying to create a program where when the user touches the screen, a sprite will appear. However, if the user keeps their finger on that Sprite, the sprite will grow bigger until the user lets it go.
Now, I created this program in Cocos2d 1.x and it worked fine. However, when I attempted it in 2.x, the sprite gets created but it doesn't help the Sprite Grow.
The code is the following:
-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event{
CGPoint touchLocation = [self convertTouchToNodeSpace:touch];
redBall = [CCSprite spriteWithFile:#"Circle.png"];
redBall.position = ccp(touchLocation.x, touchLocation.y);
redBallRect = CGRectMake(redBall.anchorPoint.x, redBall.anchorPoint.y, redBall.contentSize.width, redBall.contentSize.height);
[self addChild:redBall];
if (CGRectContainsPoint(redBallRect, touchLocation )) {
NSLog(#"Hello");
growForever = [CCRepeatForever actionWithAction: [CCScaleBy actionWithDuration: .5 scale: 1.2]];
[growForever setTag:1];
[redBall runAction:growForever];
}
return YES;
}
What might be the problem and how do I solve it?
Make sure you enabled touch:
-(void)onEnter
{
[super onEnter];
self.touchEnabled = YES;
}
Use boundingBox to get rect.
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *myTouch = [touches anyObject];
CGPoint touchLocation = [myTouch locationInView:[myTouch view]];
touchLocation = [[CCDirector sharedDirector] convertToGL:touchLocation];
if(CGRectContainsPoint([redBall boundingBox], touchLocation))
{
NSLog(#"Hello");
growForever = [CCRepeatForever actionWithAction: [CCScaleBy actionWithDuration: .5 scale: 1.2]];
[growForever setTag:1];
[redBall runAction:growForever];
}
}

Adding a CCLabel ontop of openGLView - cocos2d iphone

So within a CCLayer I am adding an ImagePicker / Camera to the openGLView and then a UIButton - all good, but now I want to add a CCLabel (and in the future CCSprites) on top of those elements.
uip = [[UIImagePickerController alloc] init];
uip.sourceType = UIImagePickerControllerSourceTypeCamera;
uip.showsCameraControls = NO;
uip.toolbarHidden = YES;
uip.navigationBarHidden = YES;
uip.wantsFullScreenLayout = YES;
uip.cameraViewTransform = CGAffineTransformScale(uip.cameraViewTransform, CAMERA_TRANSFORM, CAMERA_TRANSFORM);
[[[CCDirector sharedDirector] openGLView] addSubview:uip.view];
arrowButton = [UIButton buttonWithType:UIButtonTypeCustom];
[arrowButton addTarget:self
action:#selector(arrowButtonClicked:)
forControlEvents:UIControlEventTouchUpInside];
UIImage *imgNormal = [UIImage imageNamed:#"btn_next_norm.png"];
[arrowButton setImage:imgNormal forState:UIControlStateNormal];
UIImage *imgPressed = [UIImage imageNamed:#"btn_next_pressed.png"];
[arrowButton setImage:imgPressed forState:UIControlStateHighlighted];
arrowButton.frame = CGRectMake(screenSize.width - 48.0, screenSize.height - 37.0, 48.0, 37.0);
[[[CCDirector sharedDirector] openGLView] addSubview:arrowButton];
CCLabelTTF* label = [CCLabelTTF labelWithString:#"Experience 1" fontName:#"Arial" fontSize:32];
label.color = ccc3(0, 0, 0);
CGSize size = [[CCDirector sharedDirector] winSize];
label.position = CGPointMake(size.width / 2, size.height / 2);
// [[[CCDirector sharedDirector] openGLView] addSubview:labe]; cant add to openGLView
You need to addSubview UIView components under the openGLView as the following,
[[[CCDirector sharedDirector] openGLView].superview addSubview:arrowButton];
And then, openGLView should be transparent. "Displaying an EAGLView with transparent background on a UIImageView"
EDIT:
moving the Cocos on top of the UIImagePickerController
Ok, how about the following? addSubview the cocos2d view (openGLView) on cameraOverlayView of UIImagePickerController.
[[[CCDirector sharedDirector] openGLView].superview addSubview:uip.view];
[[[[CCDirector sharedDirector] openGLView] removeFromSuperview];
uip.cameraOverlayView = [[CCDirector sharedDirector] openGLView];
Also, you need Making Cocos2d Transparent.

Rotating sprite with finger in Cocos2d

I need help figuring out the rotation of a sprite with my finger. The sprite is rotating fine but on the initial touch of my finger it somehow rotates by a few degrees by itself.
Also the rotations only work when the finger is rotated around the center of the sprite.
I am trying to simulate the bicycle wheel and have a gear sprite and a pedal sprite as a child of the gear sprite. I want the bicycle wheel to rotate as I touch the pedal and rotate it. I haven't got that far yet. Right now I am trying to figure out how to get rid of the initial shift the gear makes.
Here is the complete code
#import "BicycleScene.h"
#implementation BicycleScene
+(id) scene
{
// 'scene' is an autorelease object.
CCScene *scene = [CCScene node];
// 'layer' is an autorelease object.
BicycleScene *layer = [BicycleScene node];
// add layer as a child to scene
[scene addChild: layer];
// return the scene
return scene;
}
-(id) init
{
if ((self=[super init])) {
CGSize winSize = [[CCDirector sharedDirector] winSize];
//place the bicycle sprite
bicycleSprite = [CCSprite spriteWithFile:#"bike_gear.png"];
bicycleSprite.position = ccp(bicycleSprite.contentSize.width/2 + 100, winSize.height/2);
[self addChild:bicycleSprite z:1];
//place the pedal sprite
pedalSprite = [CCSprite spriteWithFile:#"bike_pedal.png"];
[bicycleSprite addChild:pedalSprite z:1];
pedalSprite.position = ccp(150, 15);
//enable touch
self.isTouchEnabled = YES;
[self schedule:#selector(gameLoop:) interval:.1/100];
}
return self;
}
-(void) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(#"Touch begun");
}
-(void)gameLoop:(ccTime) dt{
bicycleSprite.rotation = cocosAngle;
}
-(void) ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(#"Touch moved");
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:[touch view]];
CGPoint previousLocation = [touch previousLocationInView:[touch view]];
CGPoint touchingPoint = [[CCDirector sharedDirector] convertToGL:location];
CGPoint previousTouchingPoint = [[CCDirector sharedDirector] convertToGL:previousLocation];
CGPoint vector = ccpSub(touchingPoint, bicycleSprite.position);
CGFloat rotateAngle = -ccpToAngle(vector);
previousAngle = cocosAngle;
cocosAngle = CC_RADIANS_TO_DEGREES( rotateAngle);
//bicycleSprite.rotation = cocosAngle;
}
#end
I am slightly confused if the line:
CGPoint vector = ccpSub(touchingPoint, bicycleSprite.position);
should actually be:
CGPoint vector = ccpSub(touchingPoint, previousTouchingPoint );
I tried that as well but it didn't work.
I have also uploaded my complete xcodeproj to 4shared for anyone who wants to take a look here: http://www.4shared.com/file/5BaeW4oe/Healthy.html
#interface MainScene : CCLayer {
CCSprite *dial;
CGFloat dialRotation;
}
+ (id)scene;
#end
---------------------------------
#implementation MainScene
+ (id)scene
{
CCScene *scene = [CCScene node];
CCLayer *layer = [MainScene node];
[scene addChild:layer];
return scene;
}
- (id)init
{
if((self = [super init])) {
CCLOG(#"MainScene init");
CGSize size = [[CCDirector sharedDirector]winSize];
dial = [CCSprite spriteWithFile:#"dial.png"];
dial.position = ccp(size.width/2,dial.contentSize.height/2);
[self addChild:dial];
self.isTouchEnabled = YES;
[self scheduleUpdate];
}
return self;
}
- (void)dealloc
{
[super dealloc];
}
- (void)update:(ccTime)delta
{
dial.rotation = dialRotation;
}
- (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
}
- (void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
//acquire the previous touch location
CGPoint firstLocation = [touch previousLocationInView:[touch view]];
CGPoint location = [touch locationInView:[touch view]];
//preform all the same basic rig on both the current touch and previous touch
CGPoint touchingPoint = [[CCDirector sharedDirector] convertToGL:location];
CGPoint firstTouchingPoint = [[CCDirector sharedDirector] convertToGL:firstLocation];
CGPoint firstVector = ccpSub(firstTouchingPoint, dial.position);
CGFloat firstRotateAngle = -ccpToAngle(firstVector);
CGFloat previousTouch = CC_RADIANS_TO_DEGREES(firstRotateAngle);
CGPoint vector = ccpSub(touchingPoint, dial.position);
CGFloat rotateAngle = -ccpToAngle(vector);
CGFloat currentTouch = CC_RADIANS_TO_DEGREES(rotateAngle);
//keep adding the difference of the two angles to the dial rotation
dialRotation += currentTouch - previousTouch;
}
- (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
}
EDIT: I am sorry I can't get this to stay in code mode. But this is the solution and it should be easy to implement in your code. cheers!
In ccTouchesBegan, use the same code as what you've got in ccTouchesMoved to determine the angle, then move to that angle using CCRotateTo. You will need some handling of the user moving his finger while CCRotateTo is active, perhaps stopping the current action and kicking off another one to move to the new angle.