对cocos2d iphone的朝向处理的改进

我用cocos2d iphone作为我的iPhone/iPad游戏已经有一阵子了。cocos2d iphone是个经过考验的、方便使用的引擎,而且让你几乎可以很快地进行gameplay方面的开发。最近它加入了iPad的支持。然而,Apple对于iPad游戏的审批似乎比iPhone更严格了一些。因为iPad Human Interface Guideline中对于朝向敏感方面,对开发者做出了更高的要求。

鉴于以上原因,我准备让我的游戏变得对朝向改变更友好一点。在cocos2d iphone中,朝向的改变可以用注册UIDeviceOrientationDidChangeNotification事件后,再调用一些CCDirector的方法予以解决: 

 

代码
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
        
// Enable orientation detection
    [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
    
// Register orientation detection
    [[NSNotificationCenter defaultCenter]
     addObserver:self selector:@selector(orientationDidChanged:) name:
@"UIDeviceOrientationDidChangeNotification" object:nil];
         ......
}
-(void) orientationDidChanged:(NSNotification*)notification
{
    UIDeviceOrientation orientation 
= [[UIDevice currentDevice] orientation];
    [[CCDirector sharedDirector] setDeviceOrientation:(ccDeviceOrientation)orientation];
}

 然而,这个朝向的改变是很生硬的,没有任何切换动画。在做了一些功课之后,我决定自己写点代码搞定它。其实cocos2d中的朝向处理代码也没做什么事,无非就是调了一些必要的OS函数和坐标系转换。

所以我是这么做的:把CCDirector.applyLandscape里的所有gl调用都替换为CGAffineTransform的调用,而CGAffineTransform是可以根据时间插值的。最后把CGAffineTransform的矩阵转换为gl的矩阵:

代码
CGAffineTransform CGAffineTransformInterpolate(const CGAffineTransform *t0, const CGAffineTransform *t1, float factor)
{
    
// clamp factor to [0, 1]
    if ( factor > 1 )
        factor 
= 1;
    
if ( factor < 0 )
        factor 
= 0;

    
return CGAffineTransformMake(t0->a*(1-factor) + t1->a*factor,
                                 t0
->b*(1-factor) + t1->b*factor,
                                 t0
->c*(1-factor) + t1->c*factor,
                                 t0
->d*(1-factor) + t1->d*factor,
                                 t0
->tx*(1-factor) + t1->tx*factor,
                                 t0
->ty*(1-factor) + t1->ty*factor);
}

// in your CCDirector.m:

- (void) setDeviceOrientation:(ccDeviceOrientation) orientation
{
    
if( deviceOrientation_ != orientation ) {
        deviceOrientation_ 
= orientation;
        targetTransform_ 
= CGAffineTransformIdentity;
        elapsedSinceLastOrientationChange_ 
= 0;

        CGSize s 
= [openGLView_ frame].size;
        
float w = s.width / 2;
        
float h = s.height / 2;

        
switch( deviceOrientation_) {
            
case CCDeviceOrientationPortrait:
                [[UIApplication sharedApplication] setStatusBarOrientation: UIInterfaceOrientationPortrait animated:NO];
                
break;
            
case CCDeviceOrientationPortraitUpsideDown:
                [[UIApplication sharedApplication] setStatusBarOrientation: UIInterfaceOrientationPortraitUpsideDown animated:NO];

                targetTransform_ 
= CGAffineTransformTranslate(targetTransform_, w, h);
                targetTransform_ 
= CGAffineTransformRotate(targetTransform_, CC_DEGREES_TO_RADIANS(180));
                targetTransform_ 
= CGAffineTransformTranslate(targetTransform_, -w, -h);
                
break;
            
case CCDeviceOrientationLandscapeLeft:
                [[UIApplication sharedApplication] setStatusBarOrientation: UIInterfaceOrientationLandscapeRight animated:NO];

                targetTransform_ 
= CGAffineTransformTranslate(targetTransform_, w, h);
                targetTransform_ 
= CGAffineTransformRotate(targetTransform_, -CC_DEGREES_TO_RADIANS(90));
                targetTransform_ 
= CGAffineTransformTranslate(targetTransform_, -h, -w);
                
break;
            
case CCDeviceOrientationLandscapeRight:
                [[UIApplication sharedApplication] setStatusBarOrientation: UIInterfaceOrientationLandscapeLeft animated:NO];

                targetTransform_ 
= CGAffineTransformTranslate(targetTransform_, w, h);
                targetTransform_ 
= CGAffineTransformRotate(targetTransform_, CC_DEGREES_TO_RADIANS(90));
                targetTransform_ 
= CGAffineTransformTranslate(targetTransform_, -h, -w);
                
break;
            
default:
                NSLog(
@"Director: Unknown device orientation");
                
break;
        }
    }
}

-(void) applyLandscape
{
    
static float m[16];

    
if ( elapsedSinceLastOrientationChange_ < 0.25f )
    {
        currentTransform_ 
= CGAffineTransformInterpolate(&currentTransform_, &targetTransform_,
                                                         elapsedSinceLastOrientationChange_ 
/ 0.25f);
        elapsedSinceLastOrientationChange_ 
+= dt;
    }
    
else
    {
        currentTransform_ 
= targetTransform_;
    }

    CGAffineToGL(
&currentTransform_, m);
    glMultMatrixf(m);
}

 

 现在,cocos2d的朝向处理就可以有漂亮的切换动画了。我把patch文件上传了,如果有兴趣的话可以下载看看。我是基于cocos2d iphone 0.99.0的代码做的。

 

posted @ 2010-05-04 00:27  eygneph  阅读(556)  评论(0编辑  收藏  举报