【コラム】

実践! iPhoneアプリ開発

20 タワーディフェンスゲームの作り方 (3) - 背景の描画

    木下誠  [2009/10/30]

    前回はOpenGL環境のセットアップまで行った。これでようやく絵を描く準備が整ったことになる。今回は、いよいよ実際に画面に絵を表示させてみよう。まずはゲームの背景画像を描いてみる。

    テクスチャの作成

    OpenGLを使って絵を描く場合は、画像ファイルを読み込んで、これをテクスチャとして利用することになる。画像ファイルを読み込むところまではCocoaやCore GraphicsのAPIを使い、テクスチャを作成するところはOpenGLの関数を使うことになるだろう。

    早速だが、そのような動作を行うソースコードを紹介しよう。loadTextureName:texture:と名付けたメソッドだ。このメソッドは、引き数を2つとる。第1引き数は、読み込む画像ファイルの名前だ。これは、プロジェクトに直で追加されていることを想定している。第2引き数は、作成されたテクスチャの名前となる。GLuintのポインタで渡すので、メソッドからの出力値として使われることになる。

    List 1.

    - (void)loadTextureName:(NSString*)imageName texture:(GLuint*)texture
    {
        // CGImageを取得する
        CGImageRef  cgImage;
        cgImage = [UIImage imageNamed:imageName].CGImage;
    
        // データプロバイダを取得する
        CGDataProviderRef   dataProvider;
        dataProvider = CGImageGetDataProvider(cgImage);
    
        // ビットマップデータを取得する
        CFDataRef   cfData;
        GLubyte*    data;
        cfData = CGDataProviderCopyData(dataProvider);
        data = (GLubyte*)CFDataGetBytePtr(cfData);
    
        // テクスチャを作成する
        glGenTextures(1, texture);
    
        // テクスチャをバインドする
        glBindTexture(GL_TEXTURE_2D, *texture);
    
        // ビットマップ画像を設定する
        glTexImage2D(
                GL_TEXTURE_2D, 0, GL_RGBA, 
                CGImageGetWidth(cgImage), CGImageGetHeight(cgImage), 
                0, GL_RGBA, GL_UNSIGNED_BYTE, data);
        CFRelease(cfData);
    
        // テクスチャの設定を行う
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glEnable(GL_TEXTURE_2D);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glEnable(GL_BLEND);
    }
    

    このメソッドでの処理は、大きく分けると2つに分かれる。画像ファイルを読み込んでビットマップを取り出すまでと、そこからテクスチャを作成するところだ。

    画像ファイルからのビットマップ取り出しは、主にCore GraphicsのAPIを使っている。詳しいことは、本連載の第4回『カメラアプリの作り方 (4) - 写真にエフェクトをかける』を参考にしてほしい。

    テクスチャの作成には、OpenGLの関数を使う。まず、glGenTextruesを使ってテクスチャを作成する。次に、glBindTextureを使ってそのテクスチャをバインドし、glTextImage2Dでビットマップ画像を設定するのだ。あとは、いくつか必要な設定を行っている。

    glTexImage2Dを呼び出すときは、その引き数に注意してほしい。ビットマップデータのフォーマットやデータ形式を指定するのだが、今回は決めうちで行っている。本来は、読み込んだ画像ファイルのフォーマットに従って、変更できるようにすべきだろう。今回は画像ファイルのフォーマットが、Big EndianのTIFFかそれと同等のものになる、という前提にあわせて設定している。

    また、画像の大きさも重要だ。OpenGL ES 1.0では、テクスチャの縦、横の大きさが、2のべき乗でなくてはいけない、という制限がある。読み込む画像ファイルは、この制限に適合するように気をつけて作成しよう(この制限は、OpenGL ES 2.0で緩和される)。

    たとえば、ゲームの背景画像を読み込ませることを考えよう。iPhoneのスクリーンサイズは320 x 480なので、この大きさの画像を用意することになる。だが、この縦横の値は、2のべき乗ではない。そこで、これらの値より大きい2のべき乗の値になるサイズにしなくてはいけない。つまり、512 x 512の画像になるのだ。

    具体的には、次のような画像を用意すればいい(本稿の最下部からダウンロードできるサンプルソースコードに512 x 512のTIFF画像を含めてある)。

    余分なところは黒で塗りつぶしてしまおう。または、この領域に別の画像を埋め込んでしまうこともできる。これについては、次回以降で説明しよう。

    ポリゴンの作成とテクスチャの表示

    テクスチャを作成したら、それを画面上に表示しよう。OpenGLで表示するので、ポリゴンを作ることになる。そこにテクスチャを貼付けてやればいいのだ。

    ゲームの背景画像を表示するためのメソッドを紹介しよう。drawBackgroundだ。

    List 2.

    - (void)drawBackground
    {
        // 頂点を作成する
        GLfloat vertices[] = {
            -1.0f, -1.5f, 
            1.0f, -1.5f, 
            -1.0f, 1.5f, 
            1.0f, 1.5f
        };
        glVertexPointer(2, GL_FLOAT, 0, vertices);
    
        // 色を設定する
        GLubyte colors[] = {
            255, 255, 255, 255, 
            255, 255, 255, 255, 
            255, 255, 255, 255, 
            255, 255, 255, 255, 
        };
        glColorPointer(4, GL_UNSIGNED_BYTE, 0, colors);
    
        // テクスチャの設定をする
        GLfloat coord[] = {
            0, 0.9375, 
            0.625, 0.9375, 
            0, 0, 
            0.625, 0, 
        };
        glTexCoordPointer(2, GL_FLOAT, 0, coord);
    
        // 描画を行なう
        glBindTexture(GL_TEXTURE_2D, backTexture);
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
        glBindTexture(GL_TEXTURE_2D, 0);
    }
    

    このメソッドでの処理は、頂点の配列を用意してポリゴンの作成、色の配列を用意して頂点カラーの設定、テクスチャ座標の配列を用意して頂点への設定、そしてテクスチャをバインドしてポリゴンの描画、という流れになる。

    順に見ていこう。まず、頂点配列を用意する。今回はスクリーンいっぱいに表示するポリゴンとなるので、それにあわせた頂点を用意している。スクリーン左下が(-1.0, -1.5)、右下が(1.0, -1.5)、左上が(-1.0, 1.5)、右上が(1.0, 1.5)となる。この座標系の値については、前回の記事を参考にしてほしい。この頂点配列をglVertexPointerに渡すことで、ポリゴンが作成される。

    ポリゴンを作成するときに、glBeginおよびglEndと、glVertexを使っていないことに注意してほしい。なぜこれらの関数を使わないのかというと、OpenGL ESではこれらはサポートされていないからだ。ポリゴンを作成するときは、頂点配列を用意してglVertexPointerを使うことになる。この関数を使うときはglEnableClientStateで、GL_VERTEX_ARRAYを有効化しておかないといけないのだが、これは前回紹介したrenderメソッドの中で行っている。

    次に、頂点カラーを設定する。これにはglColorPointerを使う。頂点カラーとして半透明色を指定すれば、テクスチャが半透明で描画されるだろう。

    続いては、テクスチャ座標系の設定だ。それぞれの頂点に、テクスチャのどの座標を表示するかを指定する。ここで気をつけてほしいのが、テクスチャのサイズと表示したい領域が違っていることだ。テクスチャサイズは512 x 512だが、背景として使いたいのはその中の320 x 480の領域である。そこで、その座標を比率として計算して、テクスチャ座標の配列を作る必要があるのだ。

    最後に描画を行う。glBindTextureで目的のテクスチャをバインドし、glDrawArraysを呼ぶことで画面に描画できる。

    これが、OpenGLを使った2次元描画となる。

    ここまでのソースコード: Defense-1.zip

    関連したタグ

    新着記事

    特設サイトの情報

      人気記事

      一覧

        イチオシ記事

        新着記事

        特別企画

        マイナビニュースマガジン