Perl Hackers Hub

第48回 Perlでの今風のゲームサーバ開発とテスト(3)

この記事を読むのに必要な時間:およそ 3.5 分

(1)こちら⁠2)こちらから。

マスタデータのテスト

ゲーム運営において必要になってくるのがアイテム定義などを含むマスタデータの管理です。ここでは,マスタデータの管理やテストの手法について述べていきます。

マスタデータはゲームサーバにおいて,ゲームの挙動を決める要素の一つです。プログラムコードと違い,プログラマー以外が入力できる形式で書かれる場合があり,ときには専用の入力ツールや,Unityエディタなどのゲーム開発環境に統合された内製ツールが入力に用いられることがあります。

マスタデータの例

筆者のプロジェクトでは,マスタデータはCSVComma-Separated Valuesカンマ区切り)の形式で記述され,そのままMySQLのテーブルにレコードとして挿入できる形で表現されます。以下に,ゲーム内アイテムを表現するマスタデータの例を示します。

id,name,effect_type,effect_parameter
1,小さい体力回復ドリンク,1,{"energy": 30}
2,ふつうの体力回復ドリンク,1,{"energy": 50}
3,大きい体力回復ドリンク,1,{"energy":100}

このアイテムテーブルはidnameeffect_type,effect_parameterで構成されています。idは,アイテムを区別するサロゲートキーです。nameはアイテム名です。

アイテムの種類や挙動を決めるのに,effect_typeカラムとeffect_parameterカラムを用意しています。effect_typeはプログラム内で列挙型として定義され,1は体力回復アイテムを指します。effect_parameterは,アイテムをeffect_typeに沿って適用するときの引数で,JSON形式で書かれています。SQLアンチパターンで言われているものの一つではありますが,アイテムごとに発揮する効果が違い,設定される値の数や意味も違うため,このようになっています。この場合,小さい体力回復ドリンクは体力を30回復しますが,大きい体力回復ドリンクは体力を100回復します。

ほかにもアイテムのマスタデータには,売却する際にゲーム内通貨としていくらで売れるかなどが定義されます。

実際に使用するときには,上記に示したCSVをitemsテーブルに格納します。このitemsテーブルに対応するユーザーデータのテーブルをuser_itemsとします。user_itemsテーブルは,サロゲートキーidアイテムを所持しているユーザーを示すuser_id所持しているアイテムを示すitem_id所持数を示すhaving_numカラムで構成されています。

マスタデータを用いたコード

では,上記のマスタデータを用いて,どのようにゲームの挙動を変化させるかを見ていきます。

回復アイテムの消費と効果をユーザーに適用する関数の例

アイテム消費APIから呼ばれる,アイテム消費関数を考えます。関数は次の処理に分解できます。

txn_begin; # トランザクションを開始する
# アイテムの行があればそれに対して行ロックをかける
$user_item->lock;
# アイテムを所持しているかをチェックする
$user_item->try_having_by_num($num);
# 1つずつアイテムを消費して効果を発揮させる
my $result =
    $user_item->consume_and_effect(num => $num);
txn_commit; # トランザクションを終了してコミットする
実際にアイテム消費と効果適用を行う関数

アイテムを消費して効果を発揮させるconsume_and_effectメソッドの中身を次に示します。

# アイテムを消費する
# UPDATE user_items
#   SET having_num = having_num - $num
#   WHERE user_id = $user_id
#   AND item_id = $item_id;
$self->consume(num => $num);

# アイテムマスタの効果に対応するeffectorクラスを
# インスタンス化する
my $effector = $self->_effector;
# 保持しているMyApp::Model::Userに対して
# アイテム効果を適用させる
my $result = $effector->effect(
    user => $self->user,
    num => $num,
);
return $result;
マスタデータによる効果適用処理の切り替え

前項のコードで示したとおり,効果に応じたクラスをeffect_typeの値に応じて取り出します。この機構についての具体的な実装を示します。

my %effect_type_map = (
    # 1: 体力を回復
    1 => 'MyApp::Model::ItemEffect::RecoverEnergy',
    # そのほかのtypeに応じたpackageのマッピングを羅列する
);
sub _effector {
    my $self = shift;
    return $effect_type_map{$self->effect_type}->new;
}

Perlであれば,上記のようにハッシュにeffect_typeに対応するクラス名を保持しておき,クラス名を取り出してインスタンス化するのが,記述量やわかりやすさの面でバランスが良いです。ほかのプログラミング言語ではswitchやパターンマッチなどの記法を用いると思います。

回復アイテムの効果適用の処理例

さらに,MyApp::Model::ItemEffect::RecoverEnergy内の,実際に体力回復を適用する処理を示します。

sub effect {
    my ($self, %args) = @_;
    my $user = $args{user};
    my $parameter = $args{parameter};
    my $num = $args{num};

    # JSONがO/Rマッパなどのinflate機構を通してハッシュになる前提
    my $energy = $parameter->{energy};
    # UPDATE user
    # SET energy = energy + ($energy * $num)
    # WHERE id = $user_id;
    my $result = $user->add_energy($energy * $num);

    return $result;
}

マスタデータの内容によって,使用するクラスパッケージを切り替えることにより,マスタデータだけでさまざまな効果を持つアイテムを作れました。

著者プロフィール

谷脇真琴(たにわきまこと)

1989年生まれ。山口県出身。

面白法人カヤックのゲーム事業部でサーバサイドアプリケーションの開発とワークフローの整備に携わってきた。

趣味はゲームと3Dプリンタの製作。

コメント

コメントの記入