Swift/Metalで3週間で3Dアクションゲームを作った


3Dアクションゲームを作った

2019年7月から3Dアクションゲームを作り始めました。
自分のスペックは10年前にDEAというゲーム専門学校でゲーム開発を学び、1年間現場でゲームプログラマをしていました。
その後は趣味でAndroid向けゲームを2本公開しています。
直近では2DパズルゲームをSwiftで作成し公開しています。

まずは何か表示させてみようという所から始めました。

  • まずは立方体を表示。
  • 次に、ポイントスプライトを表示。
  • MetalのViewの中にUILabelを表示する仕方が分からなかったので、ポイントスプライトを使って8×8ピクセルのアルファベットのフォントを作成。
  • 立方体の角を取ったベベルキューブを作成。
  • イラストから3Dにキャラクターを起こして、ゲーム画面に表示

パズルゲームを作ろうかと思っていました。

キャラクターが登場するパズルゲームを作ろうと思っていたのですが、ゲーム的に面白くならなさそうだと思い、アクションゲームに変更しました。

Metalのシェーダー

[[point_size]] というのをシェーダーに追加してポイントスプライトの大きさ変更に使っていました。
あと、ポイントスプライト用にOriginalPosition という引数を追加してポイントスプライトの位置を変更していました。

struct InOut2 {
    float4 position [[position]];
    float pointSize [[point_size]];
    float4 color;
    float3 normal;
    float3 light;
};

vertex InOut2 vertex_func(constant InOut *vertices [[buffer(0)]],
                          uint vid [[vertex_id]],
                          constant Uniforms & uniforms [[ buffer(1) ]],
                          constant OriginalPositions & origins [[ buffer(2) ]]
                          ) {
    InOut2 out;
    out.position = uniforms.projectionMatrix * uniforms.modelViewMatrix * (vertices[vid].position + float4(origins.position, 1.0));
    out.color = vertices[vid].color;
    out.normal = ( uniforms.projectionMatrix * uniforms.modelViewMatrix * float4(vertices[vid].normal, 1.0) ).xyz;
    out.light = uniforms.lightPosition;
    out.pointSize = 8.0;
    return out;
}

ShaderType.h

typedef NS_ENUM(NSInteger, BufferIndex)
{
    BufferIndexMeshPositions = 0,
    //    BufferIndexMeshGenerics  = 1,
    BufferIndexUniforms      = 1,

    BufferIndexOriginalPositions = 2,//今回これを追加
};

// 下記も追加
typedef struct
{
    vector_float3 position;
} OriginalPositions;

最終的にポイントスプライトは使いませんでしたが、自分のはこんなシェーダーになりました。

シーン遷移

プロジェクトを新規作成した時点でRendererクラスが用意されており、そのRendererでシェーダーの呼び出しまで描画が出来るようになっています。
そのRenedererの中でにシーン(画面)を切り替えるクラスを作ります。
MTKViewにUIを登録してボタンなどを表示するのですが、シーン切替ごとにボタンの登録削除、新規登録を行います。
BaseSceneを作り、このクラスを継承する各シーンクラスがステージ1、ステージ2などになります。

エディタを作った

ステージやキャラクターを作るためのエディタを作りました。
最終的に使いませんでした。

キャラクタを作った

キャラクタはポイントスプライトで8×8ピクセルのアルファベットを作った要領でボクセルキャラクターをポチポチと作っていきました。
しかし、この作り方はキャラクタを量産させるには不便なやり方だと感じたので、今後はエディタを作り直してエディタを使ってキャラ作成しようと思います。

当たり判定

今回はy方向ジャンプとz方向ジャンプがあるアクションゲームだったので難しい当たり判定になるかなと思っていましたが、y方向ジャンプだけのゲームと作り方は変わりませんでした。

課題

  • スクリーンサイズとUI表示位置を合わせる。
  • 汎用的な当たり判定クラスを作っておく。

まとめ

2019年7月26日にリリースする目標で最終調整していきます。

1本アクションゲームを作れたので完成させるノウハウが少し身に付きました。
キャラクタやステージをバリエーション豊富にさせることができるのは優秀なエディタだと思います。
今回使わなかったけど、エディタ大事
大事な事なのでもう1度、エディタ大事