【ソーシャルゲーム】サーバサイドにおけるスタミナ管理【前編】

今回はソシャゲに必ずと言っていいほどあるスタミナの管理方法をサーバサイドでの実装に焦点に絞って説明したいと思います。

まず、プレイヤーのスタミナは自然回復しますが上限があり、自然回復やスタミナ回復薬を使用したとしても、上限値を超えることがない場合について見ていきます。

今どき、スタミナが上限を超えないソシャゲは少ないだろうと思われるかもしれませんが、スタミナが上限を超える場合も同じように考えることができるので, 少しだけ我慢してお付き合い下さい。

スタミナが上限を超える場合の実装は【後編】の記事で述べたいと思います。

結論

通常、プレイヤーのスタミナは「現在スタミナ値」と「スタミナ最終更新日時」の2つで管理することが多いかもしれませんが、実は「スタミナ全快日時」だけを管理しておけばOKです。

前提条件

説明に入る前に前提条件として、スタミナは次のように定義されていると仮定します。

スタミナ最大値 120
自然回復間隔(スタミナを1回復するのに必要な秒数) 60

つまり、スタミナを1回復するのにかかる時間は1分なので、スタミナを0から満タンまで回復するのに120分かかることになります。

プレイヤーレベルに応じて「スタミナ最大値」が増えるケースも多いですが、今回は固定にしておきます。

スタミナの操作については「現在スタミナ値の取得」「スタミナ減算」「スタミナ加算」ができたら十分だと思いますので、以降ではその3つのケースについて説明します。

それではQ&A形式で具体例を幾つか上げていきます。

スタミナ全快時間から現在スタミナ値を取得

例1

Q
現在日時が「2020-09-07 14:00:00」で、「スタミナ全快日時」が現在日時の5時間前の「2020-09-07 09:00:00」になっていた場合、「現在スタミナ値」はいくつでしょうか?

A
満タンの120になります。

例2

Q
現在日時が「2020-09-07 14:00:00」で、「スタミナ全快日時」が現在日時の30分後である「2020-09-07 14:30:00」になっていた場合、「現在スタミナ値」はいくつでしょうか?

A
30分後に満タンの120になるので、120-30=90になります。

例でなんとなくわかったと思いますが、「スタミナ全快日時」から「現在スタミナ値」を算出する方法をロジックで書くと次のようになります。

if (スタミナ全快日時 <= 現在日時)
{
    return スタミナ最大値
}
else
{
    return スタミナ最大値 - 小数点切り上げ((スタミナ全快日時 - 現在日時) / 自然回復間隔)
}

スタミナを消費するタイミングで消費に必要なスタミナがあることのチェック、もしくは、スタミナを加算するタイミングで上限を超えることがないことのチェックなどは、「現在スタミナ値」が必要になるため、その場合はこのロジックを使うことになります。

なお、サーバからアプリに対して、スタミナ情報を返却する場合には、「現在スタミナ値」は不要で「スタミナ全快日時」をそのまま返却したらよいと思います。というのも、ほとんどのアプリではスタミナ全快に要する時間(もしくは1回復するのに要する時間)をリアルタイムで表示することが多く、それを行うためには「スタミナ全快日時」(に加えて「スタミナ最大値」「自然回復間隔」)があれば十分だからです。

スタミナの減算

次はスタミナを減らす場合考えてみます。

例3

Q
現在日時が「2020-09-07 14:00:00」で、「スタミナ全快日時」が現在日時の30分後である「2020-09-07 14:30:00」になっていた場合、スタミナを30減らすと「スタミナ全快時間」はいくつになるでしょうか?

A
スタミナを30消費することによって、満タンに必要な時間が30分延長になったので「スタミナ全快時間」は「2020-09-07 15:00:00」になります。

例4

Q
現在日時が「2020-09-07 14:00:00」で、「スタミナ全快日時」が現在日時の2時間前である「2020-09-07 12:00:00」になっていた場合、スタミナを30減らすと「スタミナ全快時間」はいくつになるでしょうか?

A
まず消費前にスタミナは満タンになっています。
その状態からスタミナを30を減らしたので全快するのに掛かる時間も30分です。
つまり「スタミナ全快時間」は現在日時の30分後である「2020-09-07 14:30:00」になります。

例のとおり、スタミナを減らす場合は少し注意が必要です。

最初からスタミナが満タンでない状態からスタミナを消費したら、その消費した分だけ「スタミナ全快日時」を延長すればよいのですが、「満タンの状態から満タンでない状態になった」は現在日時を基準として満タンになるための時間を再計算する必要があります。

というのも、例4の場合だと、「スタミナ全快日時」を延長してしまうと「2020-09-07 12:00:00」が「2020-09-07 12:30:00」になり、消費したにも関わらずスタミナが満タンのままになってしまうためです。

以上を踏まえてスタミナ消費のロジックを書くと次のようになります。

スタミナ全快延長時間 = スタミナ消費量 * 自然回復間隔

if (スタミナ全快日時 <= 現在日時)
{
    スタミナ全快日時 = 現在日時 + スタミナ全快延長時間
}
else
{
    スタミナ全快日時 = スタミナ全快日時 + スタミナ全快延長時間
}

スタミナの加算

最後にスタミナを増やす場合を考えます。

ここでスタミナを増やすのは自然回復ではなく、スタミナ回復薬の使用など外部の要素によってスタミナが回復する場合になります。

例5

Q
現在日時が「2020-09-07 14:00:00」で、「スタミナ全快日時」が現在日時の2時間後である「2020-09-07 16:00:00」になっていた場合、スタミナを30増やすと「スタミナ全快日時」はいくつになるでしょうか?

A
スタミナを30獲得することによって、満タンに必要な時間が30分短縮したので「スタミナ全快時間」は「2020-09-07 15:30:00」になります。

例6

Q
現在日時が「2020-09-07 14:00:00」で、「スタミナ全快日時」が現在日時の2時間後である「2020-09-07 16:00:00」になっていた場合、スタミナを150増やすと「スタミナ全快日時」はいくつになるでしょうか?

A
スタミナが満タンになり自然回復しないので「スタミナ全快日時」は「2020-09-07 14:00:00」以前の値であれば何でもOKです。

スタミナを増やす場合は減らすよりも簡単です。

獲得したスタミナの分だけ「スタミナ全快日時」を短縮すればよいからです。

スタミナを増やすロジックを書くと次のようになります。

スタミナ全快短縮時間 = スタミナ獲得量 * 自然回復間隔

スタミナ全快日時 = スタミナ全快日時 - スタミナ全快短縮時間
※スタミナ全快日時が現在日時以前になったらスタミナは満タンということになります。

いかがでしょうか?

「スタミナ全快日時」だけで、しかも複雑な計算をすることなく、プレイヤーのスタミナが管理できることがおわかり頂けたと思います。

実は「スタミナ全快日時」でスタミナが管理できたのは、「スタミナが上限を超えない」という制約があったためです。

そこで【後編】の記事では「スタミナが上限を超える」ことがあるという仕様のもとで、今回と同じようにスタミナを管理する方法を述べたいと思います。

Kitaru

Programmer

【ソーシャルゲーム】サーバサイドにおけるスタミナ管理【前編】

お気軽に
お問い合わせください。

お問い合わせ