Porting my game from Cocos2d v2 to v3 I don't know when the sprites go out of screen.
In v2 my solution was:
-(void) update:(ccTime) delta
{
// Should use a fixed size step based on the animation interval.
int steps = 2;
CGFloat dt = [[CCDirector sharedDirector] animationInterval]/(CGFloat)steps;
for(int i=0; i<steps; i++){
cpSpaceStep(space_, dt);
}
if (mySprite.getPhysicsBody->p.y > 500)
[mySprite resetPosition];
}
now with Cocos2d v3 mySprite.physicsNode.position doesn't change through the time.
Any idea or link with some example?
Thanks.
physicsNode.position doesn't change with time because it uses its parent sprite coordinate space, not the global coordinate space.
You can get the global position of any node, considering the Anchor Point, using this:
CGPoint worldPos = [node convertToWorldSpaceAR:CGPointZero];
After that you can easily convert it to any other node space if necessary (like your level, maybe) using:
CGPoint position = [_levelNode convertToNodeSpaceAR:worldPos];
But beware that you shouldn't hardcode the screen size on your code, as it varies for each device. You can use instead:
CGSize viewSize = [[CCDirector sharedDirector] viewSize];
Related
I am using the following code to make the camera follow my character as he falls down the screen:
[self runAction:[CCFollow actionWithTarget:charSprite worldBoundary:[levelLoader gameWorldSize]/*CGRectMake(0,0,320,3000)*/]];
What happens is this: the code runs as you would expect, and follows the character as he falls from the top of the screen. However: when he reaches the middle of the screen the camera stops following him.
I have tried both the code above as well as replacing the [levelLoader gameWorldSize] with the commented out CGRectMake(0,0,320,3000) - both yield the same results. As a last resort I tried to use some code I found on www.raywenderlich.com that has worked for me before (see below) (it worked on the x-axis in another game I wrote), but the same problem occurred.
-(void)setViewpointCenter:(CGPoint) position
{
CGSize winSize = [[CCDirector sharedDirector] winSize];
CGRect worldRect = [levelLoader gameWorldSize];
int x = MAX(position.x, worldRect.origin.x + winSize.width / 2);
int y = MAX(position.y, worldRect.origin.y + winSize.height / 2);
x = MIN(x, (worldRect.origin.x + worldRect.size.width) - winSize.width / 2);
y = MIN(y, (worldRect.origin.y + worldRect.size.height) - winSize.height/2);
CGPoint actualPosition = ccp(x, y);
CGPoint centerOfView = ccp(winSize.width/2, winSize.height/2);
CGPoint viewPoint = ccpSub(centerOfView, actualPosition);
self.position = viewPoint;
}
My world is created in Portrait mode using LevelHelper.
Any help would be greatly appreciated!
CCFollow follows the node within the world boundary, minus half the screen width/height. If your sprite starts falling at y = 320 then CCFollow will follow it until y = 160.
You can either position the sprite to your world boundary's top (y = 3000) or make the world boundary negative (y = -3000). Either way, when the sprite reaches the world boundary, scrolling will stop half a screen width/height before the world boundary.
I have been trying to implement a standard pinch/zoom on a CCLayer in cocos2d (using the Kobold2D gesture recognisers) but with only partial success.
Below is my code which does make pinch/zoom work, so long as the pinch point doesn't move. However if I zoom in over one point on the layer and then lift off and move my fingers to zoom in further over another point, there is an instantaneous jump of the layer. It jumps to where the layer would have been if I'd been zooming in over the second point from the start, instead of simply zooming smoothly from where it was.
Can you see what I'm doing wrong or have I missed an existing simple pinch/zoom algorithm that does this job for CCLayers?
NB: I've left the default (YES) value for ignoreAnchorInPosition. Also, at the start self.scalePrePinch = 1.0f
-(void) update:(ccTime)delta
{
KKInput* input = [KKInput sharedInput];
if (input.gesturePinchBegan) {
CGSize scr = [[CCDirector sharedDirector] screenSize];
CGPoint pinchLocation = [self convertToNodeSpace:input.gesturePinchLocation];
CGPoint anchor = ccp(pinchLocation.x/scr.width, pinchLocation.y/scr.height);
CGFloat newScale = input.gesturePinchScale * self.scalePrePinch;
self.anchorPoint = ccp(self.anchorPoint.x + self.scale / newScale * (anchor.x - self.anchorPoint.x),
self.anchorPoint.y + self.scale / newScale * (anchor.y - self.anchorPoint.y));
self.scale = newScale;
}
else
self.scalePrePinch = self.scale;
}
I want to build a platform game with cocos2d/Box2D. I use CCFollow to follow the player sprite but CCFollow constantly puts it in the center of the screen. I want CCFollow to follow more naturally, like a human turning a camcorder with an acceptable lag, a small overshoot ...etc.
Here is a method of mine that didn't work: I attached (via a distance joint) a small physics body to the player that doesn't collide with anything, represented by a transparent sprite. I CCFollow'ed the transparent sprite. I was hoping this ghost body would act like a balloon attached to the player, hence a smooth shift in view. The problem is distance joint breaks with too heavy - too light objects. The balloon moves around randomly, and of course, it pulls the player back a little no matter how light it is.
What is a better way of following a moving sprite smoothly?
Try add this to CCActions in cocos2d libs.
-(void) step:(ccTime) dt
{
#define CLAMP(x,y,z) MIN(MAX(x,y),z)
CGPoint pos;
if(boundarySet)
{
// whole map fits inside a single screen, no need to modify the position - unless map boundaries are increased
if(boundaryFullyCovered) return;
CGPoint tempPos = ccpSub(halfScreenSize, followedNode_.position);
pos = ccp(CLAMP(tempPos.x,leftBoundary,rightBoundary), CLAMP(tempPos.y,bottomBoundary,topBoundary));
}
else {
// pos = ccpSub( halfScreenSize, followedNode_.position );
CCNode *n = (CCNode*)target_;
float s = n.scale;
pos = ccpSub( halfScreenSize, followedNode_.position );
pos.x *= s;
pos.y *= s;
}
CGPoint moveVect;
CGPoint oldPos = [target_ position];
double dist = ccpDistance(pos, oldPos);
if (dist > 1){
moveVect = ccpMult(ccpSub(pos,oldPos),0.05); //0.05 is the smooth constant.
oldPos = ccpAdd(oldPos, moveVect);
[target_ setPosition:oldPos];
}
#undef CLAMP
}
i get this from cocos2d forums.
Perhaps this http://www.cocos2d-iphone.org/wiki/doku.php/prog_guide:actions_ease can help you get an "acceleration" effect with CCFollow.
Now I met a new question. How to modify every particle's angle to make it toward the center. Just like the images:
Image 1: normal particles effecing:
Image 2: which I need:
Image 2: which I need http://tinypic.com/images/404.gif
How about this code? You need to override CCParticleSystemQuad update: or updateQuadWithParticle:newPosition: method for specify the rotation of the particles. CCParticleSystemPoint can't rotate particles.
#interface MyParticleSystem : CCParticleSystemQuad
#end
#implementation MyParticleSystem
- (void)updateQuadWithParticle:(tCCParticle*)particle newPosition:(CGPoint)pos
{
particle->rotation = ccpToAngle(particle->pos) * 180.0f / M_PI;
[super updateQuadWithParticle:particle newPosition:pos];
}
#end
In order to turn particles towards their direction of movement (in your case: towards the center), you can do the following:
Add the oldPos property to the particle tCCParticle struct in CCParticleSystem.h
Initialize the oldPos property with the initial particle position in initParticle: in CCParticleSystem.m
Update the oldPos property with the current particle position in update: in CCParticleSystem.m before the new position is computed. I do this in line 512 immediately after checking whether the particle is still alive.
Override CCParticleSystemQuad as suggested by Kazuki:
- (void)updateQuadWithParticle:(tCCParticle *)particle
newPosition:(CGPoint)pos
{
CGPoint direction = ccpSub(particle->pos, particle->oldPos);
CGPoint n = ccpNormalize(direction);
CGFloat a = -CC_RADIANS_TO_DEGREES(ccpToAngle(n) - M_PI_2);
particle->rotation = a;
[super updateQuadWithParticle:particle newPosition:pos];
}
When i move my layer that's contain all sprits by scrolling, sprits location does't change.i want's to change my sprits location with scrolling. please give me some solution for this.
Thanks in Advance......
// simple position update
CGPoint a = [[CCDirector sharedDirector] convertToGL:[touch previousLocationInView:touch.view]];
CGPoint b = [[CCDirector sharedDirector] convertToGL:[touch locationInView:touch.view]];
CGPoint nowPosition = scrollLayer.position;
nowPosition.y += ( b.y - a.y );
nowPosition.y = MAX( 0, nowPosition.y );
nowPosition.y = MIN(20, nowPosition.y);
scrollLayer.position = nowPosition;
My scrollLayer contain all the sprits. This is the code by which my layer moves to a new location. All sprits also move with the layer but their position does not change with respect to the layer moving. When i touch on that possition the sprits move. But I want to touch on sprits for moving them.
if you move a layer without moving its child sprites, the sprite.position will return the same value even after moving the layer because its returning it relative to node space (layer). To get the position of the sprite according to the world or your scene you need to convert it to world space:
CGPoint worldPosition = [self convertToWorldSpace:sprite.position];
i hope this answers your question because it wasnt very clear.