はじめに
前回は、Xcodeのプロジェクトを作成して、OpenGLの基本的な設定を行うところまでの手順を解説しました。
今回は、アプリのウィンドウがリサイズされた時の動作を調整します。
ゲームでは基本的にウィンドウがリサイズできるようにはしませんが、フルスクリーンで表示したいということはしばしばあります(その方が画面リソースが専有できるので処理が多少高速化されるメリットもあります)。そこで、通常の状態ではウィンドウのサイズを固定して、フルスクリーン表示への切り替えは許容するようにします。
1. WindowControllerクラスを追加する
ウィンドウのリサイズを制御するためには、ウィンドウがリサイズされたことを通知してもらう必要があります。Storyboardの環境下では、この通知を受け取るもっとも簡単な方法は、独自のWindowControllerクラスを用意して使うことです。
StoryboardではなくXIBを使用している場合は、AppDelegateクラスにNSWindowDelegateプロトコルを追加して、AppDelegateクラスのインスタンスをウィンドウのデリゲートに指定することで受け取れます。
そこでまず、新しいクラスを作成しましょう。プロジェクト・ナビゲータからMyGLGameフォルダを選択して右クリックし、[New File…]を選択します。
表示されたウィンドウで「macOS」の「Cocoa Class」を選択して、「Next」ボタンを押します。
次の画面で「Subclass of」の項目に「NSWindowController」と入力し、「Class」の項目に「WindowController」と入力して「Next」ボタンを押し、次の画面では何も変更せずに「Create」ボタンを押して、クラスの作成を完了します。
クラスが作成できたら、WindowController.hとWindowController.mの2つのファイルが追加されます。
2. ヘッダファイルを編集する
WindowController.hを編集して、「NSWindowDelegate」プロトコルの宣言を追加します。
#import <Cocoa/Cocoa.h>
@interface WindowController : NSWindowController<NSWindowDelegate>
@end
3. 実装ファイルを編集する
WindowController.mを編集して、自分をウィンドウ関係のデリゲートとして登録するコードと、リサイズされる時に調整を行うコードを、次のように追加します。
#import "WindowController.h"
@interface WindowController ()
@end
@implementation WindowController
- (void)windowDidLoad {
[super windowDidLoad];
self.window.delegate = self;
self.window.frameAutosaveName = @"Main Window";
[self.window setContentSize:NSMakeSize(640, 480)];
}
- (NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)frameSize
{
if ([self.window styleMask] & NSWindowStyleMaskFullScreen) {
return frameSize;
} else {
NSRect rect = NSMakeRect(0, 0, 640, 480);
rect = [self.window frameRectForContentRect:rect];
return rect.size;
}
}
@end
まず「self.window.delegate = self;」で、自分をウィンドウ関係のデリゲートとして登録します。
frameAutosaveNameプロパティに任意の文字列を設定しておくと、ウィンドウ位置が保存されるようになります。ユーザにとっても利便性が高いですし、プログラマとしても、開発中のアプリの画面を左上や左下などに固定しておくと開発効率が高くなるでしょう。
次に [self.window setContentSize:NSMakeSize(640, 480)];
というコードで、ウィンドウの(内部ビューの)初期サイズを(640, 480)に設定します。
ウィンドウがリサイズされるタイミングでwindowWillResize:toSize:
メソッドが呼ばれますので、ここでフルスクリーンかどうかをチェックして、フルスクリーンでなければ(640, 480)のサイズをリターンして要求サイズを上書きします。なお、(640, 480)のサイズでウィンドウの中身が表示されるようにするためには、ウィンドウのタイトルバーなどを含んだサイズをリターンしなければいけませんので、ここでは -[NSWindow frameRectForContentRect:]
メソッドを呼び出して、そのための変換を行っています。
こうすることで、ウィンドウモードでは(640, 480)のサイズに固定しながら、フルスクリーンボタンやメニューの[View]-[Enter Full Screen]に対応してフルスクリーンにすることができます。
4. Storyboardの編集
最後に、上記の手順で作成したWindowControllerクラスを、Storyboardで使用されるように設定しましょう。
ウィンドウ左端のプロジェクト・ナビゲータで「Main.storyboard」を選択し、「Window Controller Scene」の中の「Window Controller」を選択して、インスペクタの左から3つ目のタブにある「Identity Inspector」で「Custom Class」の「Class」に「WindowController」と入力します。
これで自作のWindowControllerクラスが読み込まれて使用されるようになり、内容のサイズが640x480ピクセルに固定され、フルスクリーン実行にも対応できるようになります。実行して確認してみましょう。
5. まとめ
今回は、ウィンドウのリサイズに対応し、フルスクリーンモードへの変化を許容しながら、ウィンドウモードではリサイズを禁止するようにしました。
なお、ゲームにおいてはフルスクリーンモードに対応することに意味があります。それは、フルスクリーンモードにおいては、他のアプリや他のウィンドウなどの操作に対応しなければいけない可能性が減るので、その処理のためのCPU利用率を減らせるということです。フルスクリーンモードでは、他のアプリをまったく気にせずに、フルに効率的な処理が行われるようにチューニングすれば良いということになります。
ここまでのプロジェクト:MyGLGame_step1-2.zip