質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.40%

  • ゲーム開発

    232questions

  • RPG

    18questions

    RPG (Report Program Generator)とは、IBMの System i(AS/400)サーバ向けのプログラミング言語です。

RPGのアイテム(装備品)で、パワーアップの実装方法

解決済

回答 3

投稿

  • 評価
  • クリップ 1
  • VIEW 914

chankane

score 127

前提・実現したいこと

RPGをつくっています。装備品によってプレーヤーをパワーアップさせようかなと考えています。具体的には攻撃力や防御力などが該当します。
その実装方法について友達と相談して、意見が分かれたので意見をください。1が友人、2が私です。また、2つの意見のいいとこ取りをするいい意見がある場合はそれがベストです。
以上、よろしくお願いいたします。

  1. プレイヤー側にpowerup(アイテム)関数を作り、その中でアイテムの種類によってパワーアップする値を変える方法
  2. アイテム側にpowerup(プレイヤー)関数を作り、プレイヤーのメソッド(powerupAtack(),powerupDefense())を実行する方法

メリット

  1. 攻撃力や防御力といった変数が外部から隠ぺいされる
  2. アイテム側に実装(どんな効果か)を隠ぺいできる。つまり、プレイヤー側はアイテムの存在を意識しなくてよい。

デメリット

  1. アイテムが増えたとき、プレイヤー側のpowerup(アイテム)関数に処理を追加しなてはならない。アイテムの数が200,300に増えたときに、その関数もデカくなる
  2. 外から値をいじり放題
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+2

追記:ここで前提にしているアイテムは、装備品だけに限定した話で、消耗品は含んでいません。

いろいろな考え方があり、正解はないのですが、ゲームの仕様に合わせて都合よく作るのが良いと思います。

自分が前に作ったゲームでは、ステータスにはデフォルト値と現在の値の2つを用意し、
アイテムには、全ステータスの増加分(パーセント)を返すメソッドを用意しました。

// 攻撃力が10%アップするアイテムの例
// 全ステータス分のメソッドを用意し、効果がないステータスは0を返す
// マイナス効果があるなら、単に-5などとすれば良い。
item.getAttack();  // 10 
item.getDefense();  // 0
item.getCritical();  // 0

ステージの効果とか、敵の魔法などにより、プレイヤーのステータスへマイナス効果を与えるような仕様もあるため、いったんパーセントに直して最終的なステータス値を決める必要がありました。

デフォルト値は、アイテム効果を除いた素の値を返します。
レベルアップによって変化するのであれば、メンバ変数をreturnする事になります。

これはあくまでも例で、だいたいこんな事をやっていたという事を思い出しながら書いています。
アイテム効果の増加分については、固定となるためバトル前に計算してメンバ変数に持っておいても良いと思います。
ただ、戦闘中にアイテムが壊れるとか、敵から受ける状態異常などの都合もあり、必ず毎回計算する部分は出てきます。

// 防御力(デフォルト値)
int Player::getDefaultDefense() const {
    return mDefaultDefense;
}

// 防御力(アイテム効果を含めた現在の値)
// バトルではこの値を使用
int Player::getDefense() {
    int base = getDefaultDefense();

    // 現在装備しているアイテム
    std::vector<Item*> items = getItems();

    // アイテム効果(増加分のパーセント)を計算
    int addPercent = 0;
    for(auto item: items) {
       // 防御力を返すメソッドなので、アイテムの防御力のところだけ考えればいい
       addPercent += item->getDefense();
    }

    // バトル中の敵の魔法などにより防御力が下がるような仕様があるなら
    // ここで、その分だけaddPercentから引いておく

    // 最終的な割合を計算
    // 80, 90, 100, 105などの値になる
    float percent = 100 + addPercent;

    // 割合が0以下となったら、計算するまでもないので0を返す
    if(percent <= 0.0f) {
        return 0;
    }

    // デフォルト値を元に最終的な値を計算
    float value = (float)base * (percent / 100.0f);

    // ここでは整数にしたいので、四捨五入して値を決定
    return (int)(value + 0.5f);  
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/07/02 09:32

    そうですか、違いはありませんか。確かにアイテムが対象とするデータは同じです。お察しの通りです。
    データ型を区別することで、意図を伝える&強制力を持たせるといった効果があるよといった感じで理解しています。たしかに間違ったアイテムが渡せてしまいますね(この勇者、食べると攻撃的があがるバナナを装備しやがったぞ!!みたいなことがおこるかも)

    キャンセル

  • 2017/07/02 09:38

    それはそれで面白いんですけどねw
    この質問の中で出てきた内容だけで判断するしかないので、構造的に違いはないのかなと思いました。
    消費する、しないという違いがありますので、これをどう表現するかだけかなと。
    私は、データ型(クラス)を分ける派ですが、クラスは分けずに消費型かどうかを返すメソッドを作る派というのも正しいです。
    実はもっと違う仕様があるか、作っていく中で違いが出てくる可能性も当然あると思います。
    でも考えすぎると、手が止まってしまうので、ある程度ざっくり方針を決めて実装してみる。
    実装してみたところ、うまく行かないかしっくり来ないので後で書き直すという事でも良い気もします。
    荒くても全体を作り切るほうが大切ですので。

    キャンセル

  • 2017/07/02 09:46

    そうなんです。いままさに考えすぎて手が止まっている状態です(笑)
    私の悪いところです(゚д゚lll)ガーン
    たぶん私もデータ型を分ける派になりそうです。
    相談しているなかで、あらかた方針に関してのアドバイスをもらったので、自分なりにカスタマイズしながら”とりあえず”つくってみようかなと思います。
    ご回答ありがとうございました。

    キャンセル

+1

これはどのように設計するか、という問題ですね。正解は無いと思います。ですが指針になるものはあります。

オブジェクト指向で考えます。
オブジェクト指向であれば、プレイヤー、アイテムは別々のオブジェクトとして存在することになります。
プレイヤーが属性として持っているのは、HP,MP,力,素早さなどになります。
アイテムが属性として持っているのはHP+5,MP+5,力+1,素早さ-1などになります。

この時にオブジェクトとしての振る舞いを考えると、アイテムとプレイヤーの関係はプレイヤーがアイテムを使用する(装備する)という関係です。ですので、プレイヤー.equip(アイテム)のようなメソッドによりパワーアップ(またはダウン)をするのが自然です。装備を外した場合はプレイヤー.remove(アイテム)ということになります。

いまいち投稿者の方とご友人の想定されているメリットデメリットがわかりませんが、デメリット1はオブジェクト指向で考えることで解消されるはずです。また、メリット1,2とも言える事ですが隠ぺいする事が目的では無く、隠ぺいすることでどのようなメリットがあるかを考えた方が良いように思います。メリットがないのであれば隠ぺいすることに意味はありません。

他の方のご意見も聞きたいですが、ぜひベストな設計目指して試行錯誤して見てください。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/07/02 01:13

    >アイテムはプレイヤーのパラメータを変動させる数値を持ちます
    >アイテムオブジェクトを生成する際に変動させるパラメータが決定されます。(力+3など)
    ということは、その勇者.use(薬草)の実装は、
    ・薬草から変動させるパラメータをget
    ・プレイヤーのパラメータにそれを反映させる
    といった流れになると思います。たぶん。
    そういった場合、getしてきた値がなんの値(HPなのか MPなのか 力なのか)か判別する必要が出てきます。その判別はどのようにしたらよいですか?正直思いつきません。勘違いをしていたらすみません。あと、急ぎではないので、日付をまたいでしまっても大丈夫です。

    キャンセル

  • 2017/07/02 01:21

    アイテムによりHPを増やす、MPを増やす、力を増やす、などバラバラなので、結局全パラメータを追加するようにすればよいのではないでしょうか。そのうえで、HP増減なしであれば変わらず、MPの増加があれば増加、などではどうでしょう。

    キャンセル

  • 2017/07/02 02:11

    mingos様の最初の回答の通りですね
    実装の手順などいろいろ参考にさせて頂きます
    ありがとうございました

    キャンセル

+1

既にベストアンサーでクローズですが、
残念ながら退会されたユーザの回答にコメントさせてもらったので具体を示しておきます。
mingosさんとchankaneさんのやり取りのJava実装と言えるものになってます。
ちなみに、2017/07/02 08:25のchankaneさんの発想はGoodでした。

GitHubにソースをアップしたので見てみてください。
以下にMainのソースだけ抜粋しておきます。
※当然ながらこの抜粋ソースだけでは動きません。

package org.pygmy.rpg;

import org.pygmy.rpg.character.Character;
import org.pygmy.rpg.item.Item;
import org.pygmy.rpg.item.armor.concrete.IronArmor;
import org.pygmy.rpg.item.concrete.Portion;
import org.pygmy.rpg.item.weapon.concrete.IronSword;
import org.pygmy.rpg.item.weapon.concrete.SteelAxe;

public class Main {

    public static void main(String[] args) {

        // プレーヤーと敵を作成
        Character player = new Character("player", 100, 10, 10);
        Character enemy = new Character("enemy", 100, 10, 10);

        // プレーヤーにポーションを持たせる
        System.out.println("アイテム:ポーションを持たせる");
        dumpCountOfItems(player);
        player.giveItem(Portion.create());
        dumpCountOfItems(player);

        // 攻撃
        System.out.println("攻撃");
        dumpPointOfLife(player);
        enemy.attackTo(player);
        dumpPointOfLife(player);

        // 武器と防具を装備
        player.equip(IronSword.create());
        player.equip(IronArmor.create());

        enemy.equip(SteelAxe.create());

        // 攻撃(装備後)
        System.out.println("攻撃(装備後)");
        dumpPointOfLife(player);
        enemy.attackTo(player);
        dumpPointOfLife(player);

        // プレーヤーのポーションを使う
        // 1) ポーションを取り出して…
        System.out.println("アイテム:ポーションを取り出して…");
        dumpCountOfItems(player);
        Item item = player.takeItem(Portion.class);
        dumpCountOfItems(player);
        // 2) 使う
        System.out.println("アイテム:使って…");
        dumpPointOfLife(player);
        item.useTo(player);
        dumpPointOfLife(player);
        // 3)使い切った?
        if (item.isUsedup()) {
            System.out.println("アイテム:捨てる");
        } else {
            System.out.println("アイテム:戻す");
            dumpCountOfItems(player);
            player.giveItem(item);
            dumpCountOfItems(player);
        }
    }

    private static void dumpPointOfLife(Character character) {
        System.out.println(character.getName() + " -> Point of Life = " + character.getPointOfLife());
    }

    private static void dumpCountOfItems(Character character) {
        System.out.println(character.getName() + " -> Count of Items = " + character.getCountOfItems());
    }
}

アイテムの取り回し方がポイントです。
GitHubにアップしたソースには設計や実装上のエッセンスも少し入れてみました。
ゲームの仕様によってメリット・デメリットはあると思いますが、
気付いてもらえれば発想の幅が広がったり、実装スキル向上になると思います。

マップの件以来の回答です。
着々と進められているようで良かったです。
是非、完成させてくださいね。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/07/04 08:17

    おはようございます
    早速参考にさせて頂きます
    おそらく完成させるまでまたお世話になることがあると思いますので、よろしくお願いいたしますm(._.)m

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.40%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • ゲーム開発

    232questions

  • RPG

    18questions

    RPG (Report Program Generator)とは、IBMの System i(AS/400)サーバ向けのプログラミング言語です。