Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I've done my moving actions which consists of sequences of CCBezierBy. However I would like the sprite to rotate by following the direction of the movement (like an airplane). How sould I do this with cocos2d?

I've done the following to test this out.

    CCSprite *green = [CCSprite spriteWithFile:@"enemy_green.png"];
    [green setPosition:ccp(50, 160)];
    [self addChild:green];

    ccBezierConfig bezier;
    bezier.controlPoint_1 = ccp(100, 200);
    bezier.controlPoint_2 = ccp(400, 200);
    bezier.endPosition = ccp(300,160);

    [green runAction:[CCAutoBezier actionWithDuration:4.0 bezier:bezier]];

In my subclass:

@interface CCAutoBezier : CCBezierBy

@end

@implementation CCAutoBezier

- (id)init
{
    self = [super init];
    if (self) {
        // Initialization code here.
    }

    return self;
}

-(void) update:(ccTime) t
{
    CGPoint oldpos=[self.target position];
    [super update:t];
    CGPoint newpos=[self.target position];

    float angle = atan2(newpos.y - oldpos.y, newpos.x - oldpos.x);
    [self.target setRotation: angle];
}

@end

However it rotating, but not following the path...

share|improve this question
add comment

2 Answers 2

up vote 2 down vote accepted

I'm not sure if there is a class dedicated to this purpose or not but you can simply implement your own. just inherit your class from CCBezierBy class and then in update function after applying what CCBezierBy by does change direction of airplane based on movement generated bu CCBezierBy.

there might be some errors in this code(i'll be glad if you fix them), but this is showing how easy you can implement it!

-(void) update: (ccTime) t
{
    CGPoint oldpos=[target position];
    [super update:t];
    CCPoint newpos=[target position];

    float angle = atan2(-newpos.y + oldpos.y, newpos.x - oldpos.x) * 180 / M_PI;
    [target setRotation: angle];
}

I'm not sure if this will help you but here is my code (though in c++ using cocos2d-x)

class mybezier : public CCBezierBy
{
public:
    static CCBezierBy* actionWithDuration(float t,ccBezierConfig k)
    {
        mybezier* b = new mybezier;
        b->CCBezierBy::initWithDuration(t,k);
        return b;
    }

    virtual void update(ccTime t)
    {
        CCPoint oldpos = getTarget()->getPosition();
        CCBezierBy::update(t);
        CCPoint newpos = getTarget()->getPosition();
        float angle = atan2(-newpos.y + oldpos.y, newpos.x - oldpos.x) * 180 / M_PI;
        getTarget()->setRotation(angle);//*  180);
    }
};

and I'm calling this class using this lines:

ccBezierConfig x;
x.controlPoint_1 = CCPoint(CCDirector::sharedDirector()->getWinSize().width / 2,0);
x.controlPoint_2 = CCPoint(0, CCDirector::sharedDirector()->getWinSize().height / 2);
x.endPosition = CCPoint(0,0);
pSprite->runAction(CCRepeatForever::actionWithAction(mybezier::actionWithDuration(10,x)));
share|improve this answer
    
That update method, where do you call it? Or is it called automatically? I really don't like the idea of having to call update from its parent. It would be good if I just simply CCAction:[BezierSubclass ...] and this autorotates the sprite. –  marcg11 Dec 3 '11 at 18:21
    
it's called automatically, you just have to change every CCBezier word in your game to CCBezierSubclass and everything will work as expected. –  Ali.S Dec 3 '11 at 19:12
    
Hmm, its not even rotating the sprite. –  marcg11 Dec 3 '11 at 20:11
    
did you also override init and alloc methods? I think the main problem is by calling [CCBezierSubclass alloc] you are getting a reference to CCBezier class since alloc is not override in inherited class. –  Ali.S Dec 3 '11 at 20:19
    
What should I put in init and alloc method? –  marcg11 Dec 3 '11 at 20:22
show 5 more comments

This works great, here it is in Objective-C for Cocos2d on iOS. Just use CCTBezierRotateTo instead of CCBezierTo. Same thing should work for CCBezierBy. My sprites rotate to follow the path given by bezierForward.

I call it like this:

id bezierForward = [CCTBezierRotateTo actionWithDuration:10.0 bezier:bezier];
[missileSprite runAction:bezierForward];

Here is the .h:

#import "CCActionInterval.h"
@interface CCTBezierRotateTo : CCBezierTo
@end

Here is the class:

@implementation CCTBezierRotateTo

-(CCBezierBy*) actionWithDuration :(float)t :(ccBezierConfig) k {
    CCTBezierRotateTo* r = [CCTBezierRotateTo actionWithDuration:t];
    return r;
}

-(void) update:(ccTime)time {
    CGPoint oldpos = [[self target] position];
    [super update:time];
    CGPoint newpos = [[self target] position];
    float angle = atan2(-newpos.y + oldpos.y, newpos.x - oldpos.x) * 180 / M_PI;
    angle += 90; // my sprites start pointing up
    [[self target] setRotation:angle];
    NSLog(@"oldpos %f,%f newpos %f,%f angle %f", oldpos.x, oldpos.y, newpos.x, newpos.y,  angle);
}
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.