Make CCSprite follow another CCSprite when touched? - ios

What I want to accomplish is to make my CCSprite follow another CCSprite when it is touching it. Now what I mean by follow is, lets say there is an animation of another CCSprite moving up the screen. So if this sprite hits my main sprite, my main sprite should move up the screen with it. This other sprite will be a platform, so technically in the end I would want the sprite to be on top of the other sprite but it would be moving along the top of the platform CCSprite as if the platform was carrying the main sprite.
Now I know how to do the collision detection part and make the other sprite animate but how would I just make my platform 'carry' my main CCSprite also kind of like how an elevator works?

I think you can place flag to check the condition "when to follow" in update: method you can reposition the second sprite according to position of first Sprite.
-(void)update:(CCTime)delta
{
if(condition == YES)
{
secondSprite.position = ccp ( firstSprite.position.x + xOffSet , firstSprite.position.y + yOffSet);
}
}
Try this according to your code.. Basic logic is here..

You can use the CCFollow action to have any node follow any other node.

You can move the first sprite without using action, by manually updating his position in a nextFrame:(ccTime) dt kinda function, doing so would be easy to update another sprite position based on your sprite position plus an offset to position it on top.
Another solution could be removing the follower sprite from its parent and adding as a child of the moving node, i think this can be done without flickering and performance loss.
edit:
another solution (maybe the best one)
a good approach, that works great with Actions so you dont need to manually schedule movements
You can add a property to the moving sprite (you need to subclass from CCSprite, if you havent already done so), to keep a reference to the follower
#property (readwrite, nonatomic, assign) CCSprite *follower;
#property (readwrite, nonatomic) BOOL followerActive;
then in your game inits, you can create both sprites, and add them as childs of your main layer, then you add the weak reference from your object to the follower
platform.follower = followerSprite;
and when you need to enable the follow platform.followerActive = YES;
at this point in the moving sprite, you can override the setPosition property
-(void) setPosition:(CGPoint)position {
if(self.followerActive) {
self.follower.position = ccpAdd(position, offset);
}
[super setPosition:position];
}

Related

cocos2d collision not detected in if((self=[super init]))

I used a CGRectIntersectsRect to detect the collision of a moving image (anvil) and an image (guy).
The "anvil" moves constantly in a CCRepeatForever and the "guy" moves in a ccTouchesBegan method by the control of the user.
Here it is, very simple:
if (CGRectIntersectsRect(guy.boundingBox, anvil1.boundingBox))
{
pancake = [CCSprite spriteWithFile:#"pancake.png"];
pancake.position = ccp(200,200);
[self addChild:pancake];
}
The problem is that the above lines of code do not work in the if((self=[super init])) and only in the ccTouchesBegan, where I have all of the actions for "guy." I do not want to have the image "pancake" appear only if the user taps exactly when the two images collide...if the images EVER collide, regardless of touch events, "pancake" should appear.
Any advice? Thanks in advance!
Not to criticize but your code doesn't make a lot of sense. Why would you be testing for interestion in an init method for two objects that are constantly in motion throughout your scene? Even if you wanted to show the pancake whenever the two intersected, why don't you load the pancake and make it invisible, then switch it to visible whenever the two objects intersect. This could be done simply by putting the condition in an update method and setting pancake's visible property to true if they intersect or false otherwise.
But to answer the question of "why" that code doesn't work in init is simply because at the point of calling this either one or both of your objects doesn't exist, they simply don't intersect, or their bounding box properties have not been set. I bet they simply don't intersect yet. But that doesn't matter much since there is no reason I can see to check for interestion in an init method. Schedule the update method, create the update method, and place this condition inside of it but rather than create the pancake sprite, you'd be setting the already existing pancake sprite's visibility to TRUE.

Preventing a sprite from rotating

I am doing this spritekit game.
I have this object that I want to move up and down when the user touches it. It is an object that has to slide in a rail, up and down or in another case left and right.
So, when the user touches the object I do something like this
CGVector force = CGVectorMake(0.0f, 5000.0f);
[object.physicsBody applyForce:force];
it is a vertical force applied up.
but when the object collide with others it rotates. Is there a way to prevent the object from rotating?
Try object.physicsBody.allowsRotation = NO. This ignores all angular impulses and forces that would make the body rotate.

Cocos2d scaling sprite causes artifact

I am on the master branch so that it will work with ARC.
I have implemented a method whereby the sprite will scale by a factor of 1.1 when a user touches the sprite. Multiple touches will queue up multiple scaling actions, built on top of each other. Every now and then I get a strange artifact where the smaller version of the sprite shows up on top of the scaled version.
Here's a screenshot:
More background: I'm using a texture atlas so I use:
sprite = [super spriteWithSpriteFrameName:anObject.filename];
to initialize the sprite. Is this a bug in openGL/cocos2d? Any advice on how to stop this artifact?
EDIT:
I am subclassing CCSprite but as far as I can tell there is only one instance of the sprite (the call to super was in a class method). Basically the user will define a list of actions that the sprite will do. The action list can also be interrupted using:
[self stopAllActions]
I've had actions using subclasses of CCMoveBy and CCRotateBy with no issues. It's only the most recent subclass of CCScaleBy that is causing this artifact. In the subclasses of these actions I'm not changing anything in the actions, just tracking certain variables so that I can properly resume the action after the interrupt.
Are you perhaps subclassing CCSprite, and in your subclass did you add a CCSprite instance variable as well?
In that case you'll be showing two sprites. The super class sprite and the instance variable sprite. If the other sprite shows up only sometimes this may depend on the order of adding sprites as childs, or the zOrder property.

Creating a scrollview

Here's my current situation:
I created a CCScene named StoreScene.
Within that scene, I've initialized a CCLayer and just named it Store layer.
Now, I want a scrollable layer that contains content which the user can touch.
To do this, I created another CCLayer named Store Container.
I create an instance of this layer and add it as a child to StoreScene.
In StoreContainer, I've added multiple sprites, each with a unique tag.
The scrolling is done within the StoreScene and touches will move the entire Storecontainer layer up or down.
I have added 4 sprites to my scrolling layer (store container)
Initially,
sprite 1 is located at 0,10
sprite 2 is located at 0,20
sprite 3 is located at 0,30
sprite 4 is located at 0,40
Obviously, as the entire storecontainer layer shifts, the sprite positions shift as well.
However,
when I do this in the TouchesEnded method:
if (CGRectContainsPoint(sprite1.boundingBox, touchpoint)){
NSLog(#"TouchedSprite1");
}
... and so on for each sprite
The touch locations of each sprite remain in the same place!!!
Visually, the sprites are moving up and down nicely.
but their locations when receiving touches stay constant..
is there a reason for this?
Any other way for approaching a scrolling layer?
I've already looked at the UIKit's scrollview and I've looked at CCScrollLayer and both aren't good enough for me.
My way may be simpler but it doesn't work as planned.
Thanks in advance! ^_^
I'm guessing you've implemented touchesEnded in your StoreContainer. In that case the touches' coordinates will be relative to that layer, which explains why their coordinate system is following the layer around the screen. You could implement touchesEnded in the scene instead, or put the StoreContainer instance inside a new and immobile layer whose purpose is only to handle touches.
Alternatively you could keep your current setup and use your answer to this question to get the touch coordinates in the world... :)
Check out CCKit, there is a nice CCScrollLayer implementation included.

Cocos2D for First Game - Advice for Beginner

I never developed in Cocos2D. However, this animated app is not easy to make with regular UIView animation and CAAnimation.
I want a number of UIImageView's (from 1 to 30) to float around the screen with the certain path and I want them to be responsive for touch (they would do some animation when touched). I also need them to go back and forth the screen (new path would be calculated) when they are touched or reach the edge of screen. It's important to retrieve X and Y position of each element whenever needed.
Question is: what Cocos2D classes are best looking at (for a beginner) to make that happen? I've tried UIView animation and CAAnimation but I came across some difficulties so I have a feeling Cocos2D may bring better results. Thank you.
Yes, cocos2d makes it much easier. You want to create a CCSprite with the initWithFile: method. Example:
CCSprite *mySprite = [CCSprite initWithFile:#"fire.png"];
[self addChild:mySprite];
Where fire.png has been added to the project and self is the scene instance.

Resources