对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的代码做的。

 

你可能感兴趣的:(cocos2d)