cocos2dをPortraitとLancscapeの両方に対応させる方法/C言語のマクロ
今週は別の仕事に集中していたため、あまり勉強は進んでいないのですが、cocos2dのサンプルアプリである[Hello World!]
内の「GameConfig.h」ファイル内に以下のようなコードが存在していて、
#ifndef __GAME_CONFIG_H #define __GAME_CONFIG_H // // Supported Autorotations: // None, // UIViewController, // CCDirector // #define kGameAutorotationNone 0 #define kGameAutorotationCCDirector 1 #define kGameAutorotationUIViewController 2 // // Define here the type of autorotation that you want for your game // #define GAME_AUTOROTATION kGameAutorotationUIViewController #endif // __GAME_CONFIG_H
#defineがでてきた時点で「??」という感じだったので、C言語の本や、ネットで調べた「マクロ」ついてまとめてみます。
マクロの基本
5人分のテスト結果を表示させるプログラム↓
#include <stdio.h> int main(void) { int test[5] = {80,60,22,50,75}; int i; for(i=0, i<5 i++) { printf("%D番目の人の点数は%dです。\n",i+test[i]); } return 0; }
↑だと、人数が変わったときに
test[5]
for文内の i<5
やらを変更しなくてはならないし、もっと大きなプログラムになると直すのが大変になってくる。
そこで、#define をを用いる↓
#include <stdio.h> #define NUM 5 int main(void) { int test[NUM] = {80,60,22,50,75}; int i; for(i=0, i<NUM i++) { printf("%D番目の人の点数は%dです。\n",i+test[i]); } return 0; }
とすることで、
#define NUM 5
の部分だけ編集すればおkになる。
デバック時にマクロを用いる
#include <stadio.h> #define DEBUG int main(void) { int i; int sum = 0; for (i=i, i<=5, i++) { #ifdef DEBUG fprint(stderr,"変数sumの値は%dとなっています。\n",sum); #endif sum = i + sum; } printf("1~5までの合計値は%dです。\n",sum); return 0; }
#define DEBUG
が定義されている場合は、
#ifdef DEBUG
以下のコードがコンパイル時にはしり、
定義されていなかった場合には、
#endif
以下の文字がはしる。
他にも以下のような種類があるみたいです。
#ifdef マクロ 文: ・・・ #endif
#if 式1 文: ・・・ #elif 式2 文: ・・・ #else 文: ・・・ #endif
cocos2dで最初に作ったサンプルアプリである[Hello World!]を、Portraitモードにも対応させる方法。
そしていよいよ本題ですが、
プロジェクト内の「GameConfig.h」ファイルを見てみると、
#ifndef __GAME_CONFIG_H #define __GAME_CONFIG_H // // Supported Autorotations: // None, // UIViewController, // CCDirector // #define kGameAutorotationNone 0 #define kGameAutorotationCCDirector 1 #define kGameAutorotationUIViewController 2 // // Define here the type of autorotation that you want for your game // #define GAME_AUTOROTATION kGameAutorotationUIViewController #endif // __GAME_CONFIG_H
となっており、
// // Define here the type of autorotation that you want for your game // #define GAME_AUTOROTATION kGameAutorotationUIViewController
の部分から推測するに、iPhoneを回転させたときに表示を変更するよう指令をだしているのは、ViewControllerクラスと予測をたててみた。
そうすると案の上、viewcontrollerファイル内に以下のメソッドを発見
// Override to allow orientations other than the default portrait orientation. - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { // // There are 2 ways to support auto-rotation: // - The OpenGL / cocos2d way // - Faster, but doesn't rotate the UIKit objects // - The ViewController way // - A bit slower, but the UiKit objects are placed in the right place // #if GAME_AUTOROTATION==kGameAutorotationNone // // EAGLView won't be autorotated // return NO; #elif GAME_AUTOROTATION==kGameAutorotationCCDirector // // EAGLView will be rotated by cocos2d // // Sample: Autorotate only in landscape mode // if( interfaceOrientation == UIInterfaceOrientationLandscapeLeft ) { [[CCDirector sharedDirector] setDeviceOrientation: kCCDeviceOrientationLandscapeRight]; } else if( interfaceOrientation == UIInterfaceOrientationLandscapeRight) { [[CCDirector sharedDirector] setDeviceOrientation: kCCDeviceOrientationLandscapeLeft]; } return NO; #elif GAME_AUTOROTATION == kGameAutorotationUIViewController // // EAGLView will be rotated by the UIViewController // // Sample: Autorotate only in landscpe mode // // return YES for the supported orientations if( interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight ) return YES; // Unsupported orientations: // UIInterfaceOrientationPortrait, UIInterfaceOrientationPortraitUpsideDown return NO; #else #error Unknown value in GAME_AUTOROTATION #endif // GAME_AUTOROTATION // Shold not happen return NO; }
このメソッドで判定しているみたい。
#define GAME_AUTOROTATION kGameAutorotationUIViewController
と「GameConfig.h」内で定義していたので、
#elif GAME_AUTOROTATION == kGameAutorotationUIViewController // // EAGLView will be rotated by the UIViewController // // Sample: Autorotate only in landscpe mode // // return YES for the supported orientations if( interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight ) return YES; // Unsupported orientations: // UIInterfaceOrientationPortrait, UIInterfaceOrientationPortraitUpsideDown return NO;
の部分のコードがコンパイル時にはしっていると予想。
そのため、↓のように変更してみた。
#elif GAME_AUTOROTATION == kGameAutorotationUIViewController // // EAGLView will be rotated by the UIViewController // // Sample: Autorotate only in landscpe mode // // return YES for the supported orientations if( interfaceOrientation == UIInterfaceOrientationLandscapeLeft || UIInterfaceOrientationLandscapeRight || UIInterfaceOrientationPortrait || UIInterfaceOrientationPortraitUpsideDown) return YES;
と変更してみると、Portrait,Landscapeの両方に対応できました♩
しかし・・・
座標がずれてしまっている。。。
AutoRotationに対応するとコードが複雑になるという噂を聞いていたのですが、こういうことだったのか。。。
おそらく、ViewControllerファイルの
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { // // Assuming that the main window has the size of the screen // BUG: This won't work if the EAGLView is not fullscreen /// CGRect screenRect = [[UIScreen mainScreen] bounds]; CGRect rect; if(toInterfaceOrientation == UIInterfaceOrientationPortrait || toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) rect = screenRect; else if(toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft || toInterfaceOrientation == UIInterfaceOrientationLandscapeRight) rect.size = CGSizeMake( screenRect.size.height, screenRect.size.width ); CCDirector *director = [CCDirector sharedDirector]; EAGLView *glView = [director openGLView]; float contentScaleFactor = [director contentScaleFactor]; if( contentScaleFactor != 1 ) { rect.size.width *= contentScaleFactor; rect.size.height *= contentScaleFactor; } glView.frame = rect; }
あたりが臭い気がするので、この辺をいじってみたいと思います。
しかし、、、今日はもう遅いのでこの編で。
C言語の
enum
typedef
とかも勉強したいので、後々時間あったらアップしますー