Cocos2D は、iPhoneのゲームアプリでよく使われています。
ゲームアプリを作るならこれを勉強しましょう!
Cocos2D iPhone
まず、これを使うとどんないいことがあるかというと、
・ページの繊維がわかりやすい
・アニメーション豊富でわかりやすく使いやすい
・OpenGLESを普通に使うなら、絶対Cocos2Dを使ったほうが簡単
・フレームアニメーションが気持ちよくできる
・インターフェースビルダーが嫌いな人にはもってこい。インターフェースビルダーは一切使いません。
などなど、他にもたくさんありますが、とりあえず、ゲームっぽい動きのあるアプリを作るならば、使ったほうがいいです。
まずCocos2Dのインストールは、Cocos2dのインストールをどうぞ。
cocos2dで新規プロジェクトを作成すると、下記のようなファイルがあります。
※バージョンは、1.0.1です。
・GameConfig.h
・AppDelegate.h
・AppDelegate.m
・RootViewController.h
・RootViewController.m
・HellowWorldLayer.h
・HellowWorldLayer.m
※あとライブラリがごっそりあります。
通常のiPhoneアプリでは、Viewという概念で、ViewControllerがViewを表示して、NavigationControllerがViewControllerたちを遷移させてページを切り替えたりなど、Viewという概念の元動いています。
この方の記事がわかりやすいと思います。
UIViewとUIVIewControllerの違いについて
しかし、Cocos2Dではノードやシーン、レイヤーという概念になります。
cocos2dの基本的な概念
では、もともとのWindowや、UIViewControllerからどのような仕組みでcocos2Dの概念になっているのでしょうか。
こんな感じです↓↓↓
下から順番に
WIndow → RootViewController → EAGLView
Ditectorというのが、Cocos2Dでベースになる部分ですが、普通にやるならば、上記のことは一切気にしなくても問題ありません。
Ditectorというのに、シーンやレイヤーが入れ替わって画面遷移したり、レイヤーを重ねたりなどというような形になります。
HellowWorldLayerからNextLayerに切り替わるときは、例えばこんな感じです。
HellowWorldLayerにてボタンを押された際などに、
id scene = [NextLayer scene];
id transition = [CCTransitionFade transitionWithDuration:1.0f scene:scene];
CCDirector *director = [CCDirector sharedDirector];
[director replaceScene: transition];
これは、Fadeアニメーションをしつつ画面遷移するという内容です。
Ditectorに載っていたHellowWorldLayerからNextLayerに切り替えます。
このような形で、簡単に遷移できます。
大体、仕組みはこのようになりますが、もし、ARアプリのようなカメラを背景にしたい場合、ちょっと厄介です。
そもそも基本的に、UIView配下でしか使用できないものだからです。
他にもActionSheetや、UITextFiledなどのもともと使用できるものを使いたくても、Cocos2Dだと、ちょっと一工夫しなければ使用することができません。
その方法は、
EAGLView Ditector の下にあるRootViewControllerに貼ることです。
使いたいLayerで、
#import AppDelegate.h
…
…
…
※例えば、UITextField *textField = [UITextField alloc]initWith………];
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
[appDelegate.viewController addSubView: textField];
という形で、AppDelegateクラスの中で、RootViewControllerを@property 宣言しておけば、上記のようにappDelegateを取得し、RootViewControllerをレイヤーから取得できます。
ですが、これらは上記で概要を説明した通り、DitectorやLayerに関係なく、もとに引いてあるRootViewControllerに貼るわけですから、シーンやレイヤーを移動しても、関係なく表示され続けますので、そのもとのViewControllerから削除剃る必要があります。
[textField remove removeFromSuperView];
で、削除できます。
では、本題のカメラ背景です!
これも上記とやはり概念は同じなので、上記と同じように、RootViewControllerへ貼ることになります。
が、Cocos2Dのlayerの背景をカメラにするわけですから、かなり厄介です。
つまりは、こうなります。
Window → RootViewController ここにカメラを載せる → EAGLView → Layerなど
このような形にするためには、まずは、上記のUITextFieldと同じように、RootViewControllerへカメラを貼ります。
※通常はRootViewに貼るのですが、カメラの場合WIndowに対してはらないと、表示さないようです。なので、Windowの上に乗っかっているRootViewControllerの背景も透明にする必要があります。
詳細はこちら
ですが貼っただけでは、背景はカメラになりません。
なぜかというと、RootViewController(ここではWIndow)の上には、EAGLViewが乗っているからです。
なので、Cocos2Dアニメーションの描画元である、EAGLViewの背景を透明にする必要があります。
<手順>
1. 背景をカメラにしたいシーンやレイヤーで、RootViewController(Windowです)にカメラを貼る
2. EAGLViewの背景を透明にする
カメラを表示するには、UIImagePickerControllerを使うの一般的ですが、重たいという噂だったので、今回は、AVCaptureSessionを使用しました。
1. 背景カメラを挿入したいLayerで
// EAGLView の色を透明宣言しとく。(これだけでは透明にならないです)
glClearColor(0,0,0,0);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// captureSession 作成
captureSession = [[AVCaptureSession alloc] init];
if ([captureSession canSetSessionPreset:AVCaptureSessionPresetMedium]) {
captureSession.sessionPreset = AVCaptureSessionPresetMedium;
}
NSError *error = nil;
AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error];
if (!input) {
NSLog(@"input error");
}
[captureSession addInput:input];
// 実際に貼るvideoLayer作成
videoPreviewLayer = [AVCaptureVideoPreviewLayer layerWithSession:captureSession];
videoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
CALayer *viewLayer = [[CCDirector sharedDirector] openGLView].layer;
//NSLog(@"viewLayer = %@", viewLayer);
videoPreviewLayer.frame = viewLayer.bounds;
// RootViewControllerへアクセス
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
// windowに対してカメラの場合、なぜかWindowじゃないと貼れません。
[appDelegate.window.layer insertSublayer:videoPreviewLayer below:appDelegate.viewController.view.layer];
// カメラをWIndowにはらなければならいので、
//その上に乗っかているRootViewControllerの背景も透明にする。
appDelegate.viewController.background = [UIColor clearColor];
[captureSession startRunning];
これで、Windowの上にカメラ映像を貼り、RootViewControllerの背景を透明にすることができました。
次にEAGLViewの背景を透明にします。
2. AppDelega.m
// 下記でEAGLViewのピクセルフォーマットをRGB565からRGBA8へ変更
EAGLView *glView = [EAGLView viewWithFrame:[window bounds]
pixelFormat:kEAGLColorFormatRGBA8 // kEAGLColorFormatRGBA8に変更
depthFormat:0
];
EAGLViewのレイヤーに対して、同じピクセルフォーマット数でプロパティの設定をする
CAEAGLLayer *layer = (CAEAGLLayer*)glView.layer;
layer.opaque = NO;
layer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES],
kEAGLDrawablePropertyRetainedBacking,
kEAGLColorFormatRGBA8, // kEAGLColorFormatRGBA8
kEAGLDrawablePropertyColorFormat, nil];
※ピクセルフォーマットをkEAGLColorFormatRGBA8にしないと、透明になりません。
しかし、kEAGLColorFormatRGBA8にすると、全体的な動作が重たくなりますのでご注意を。
これで実行すれば、背景がカメラになります。
以上です。
皆さんも是非試してみてください。
また内容がおかしかったり、もっといい方法がお分かりの方は、コメントください。
いい記事です。ありがとう。
返信削除ありがとうございます!
返信削除読んでいただいてうれしいです