I have been using cocos2d iphone as my iPhone/iPad game for a while. Cocos2d iphone is a tested and easy-to-use engine that allows you to develop gameplay almost quickly. Recently, it has added support for iPad. However, Apple's approval for iPad games seems to be more rigorous than the iPhone. This is because the iPad Human Interface Guideline imposes higher requirements on developers for orientation sensitivity.
For the above reasons, I am going to make my game more friendly to orientation changes. In the cocos2d iphone, orientation changes can be solved by registering the UIDeviceOrientationDidChangeNotification event and then calling some CCDirector methods:
Code -(BOOL) application :( UIApplication *) application didfinishlaunchingwitexceptions :( NSDictionary *) launchOptions
{
// Enable orientation detection
[[UIDevice currentDevice] begingeneratingdeviceorientationconfigurations];
// Register orientation detection
[[Nsicationicationcenter defacenter center]
AddObserver: self selector: @ selector (orientationDidChanged :) name: @ "UIDeviceOrientationDidChangeNotification" object: nil];
......
}
-(Void) orientationDidChanged :( NSNotification *) notification
{
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
[[CCDirector sharedDirector] setDeviceOrientation :( ccDeviceOrientation) orientation];
}
However, this orientation change is very stiff and there is no switching animation. After doing some homework, I decided to write some code to fix it myself. In fact, cocos2d has nothing to do with code orientation. It is nothing more than calling some necessary OS functions and coordinate system conversions.
So I did this: replace all gl calls in CCDirector. applyLandscape with CGAffineTransform, and CGAffineTransform can be interpolated by time. Finally, convert the CGAffineTransform matrix to the gl matrix:
Code 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 );
}
Now, cocos2d's orientation processing can have beautiful switching animations. I uploaded the patch file. If you are interested, you can download it. I made the code based on cocos2d iphone 0.99.0.