ゲームリソース(wood、iron、gold)にインスタンスまたはクラスを使用する


31

そこで、木材、鉄、金などの資源を売買する場所に船を送ることができるゲームを作っています。

今、私はゲーム内でリソースをどのように作成すべきか疑問に思っていました。私は2つのオプションを思いつきました

  1. リソースごとにクラスを作成します。

    public class ResourceBase {
        private int value;
        // other base properties
    }
    
    public class Gold : ResourceBase {
         public Gold {
             this.value = 40 // or whatever
         }
    }
    
  2. リソースクラスのインスタンスを作成する

    public class Resource {
        string name;
        int value;
    
        public Resource(string name, int value) {
            this.name = name;
            this.value = value;
         }
     }
    
    // later on...
    
    Resource gold = new Resource("Gold",40);
    

2番目のオプションを使用すると、resources.jsonファイルからゲームリソースを埋めることができます。この構造が気に入っています。

新しいアイデア/デザインパターン/構造はいつでも歓迎です!

編集:アサシンクリードブラックフラッグのコンパニオンアプリのようなものです。下の画像のリソースバーをご覧ください

編集2:「JSONファイルからアイテム/リソースをロードする」についてさらに調査を行ったところ、このブログ「Game DevelopmentでのJSONの力-アイテム」が見つかりました。オプション1とオプション2のベストを示しています。各リソースに機能を追加することができます:)

ここに画像の説明を入力してください


1
Minecraftには、リソースごとに個別のクラスがあります(そうすべきではありません)
-MCMastery

@MCMasteryああ、Minecraftはオープンソースですか?その構造を見てみたいと思います。言及するためのthx
MDijkstra

1
それはそうではありませんが、サーバーに対しては常に難読化が解除さ
MCMastery

12
そのような文字列を使用しないでください。「金」を「グロッド」などと誤入力するのは非常に簡単であり、デバッグするのは非常に苦痛です。enum代わりに使用します。
ノロナー

Minecraftは技術的にはオープンソースではありませんが、ほぼ完全に逆コンパイルおよび難読化解除されています。あなたは、インターネット上のdeobfuscatedソースのどこを見つけることができないはずですが、あなたはダウンロードしてから、それを行うための処理を実行することができますfiles.minecraftforge.net(MDKのダウンロードは1つがあなたがしたいです)
JamEngulfer

回答:


51

コードを書き直したり更新したりすることなく、いつでも新しいリソースタイプまたはアイテムを導入できるという事実のために、2番目のアプローチに進みます(データ駆動型開発)。


編集:

一部の値が変更されることはないと100%確信している場合でも、これが一般的に良い方法である理由をもう少し詳しく説明します。

コメントに記載されているコンソールゲームの例を見てみましょう。これは、たとえば暗号化キー、自分の名前などを本当に持っている(または望んでいない)場合を除き、何もハードコーディングしない理由について非常に良い理由を提供するからです

コンソールでゲームをリリースする場合、通常、これらはレビュープロセスを経る必要があります。レビュープロセスでは、コンソールメーカーのQAがゲームをテストし、プレイし、問題を探します。これは必須であり、費用がかかります。認定だけでもリリースに30,000〜50,000ドルかかる可能性があることを一度読んだことがあると思います。

ゲームをリリースするようにプッシュし、30,000ドルを支払って待つことを想像してください。そして、突然、ゲームの価値の一部が文字通り壊れていることに気づきます。50ゴールドの鉄の棒を購入し、55ゴールドで販売できるとしましょう。

職業はなんですか?そのようなものをハードコーディングした場合は、新しい更新/リリースバージョンを作成する必要があります。これはもう一度レビューを行う必要があるため、最悪の場合は再認証に再度料金を支払うことになります。Ubisoftは気にしないと思いますが、あなた自身の小さなインディーズゲームの開発者のポケットには…いや!

ただし、ゲームが更新されたゲーム定義(JSONファイル形式など)をときどきチェックすることを想像してください。ゲームは、新しいアップデートを必要とせずに、いつでも最新バージョンをダウンロードして使用できます。その不均衡/悪用/バグは、再認証やその他の支払いを必要とせずにいつでも修正できます。わずかなデザインの決定だけで、価値があるとは思わず、5桁のお金を節約しました!それは素晴らしいことではありませんか?:)

誤解しないでください。これは、他の種類のソフトウェアおよびプラットフォームにも適用されます。一般に、更新されたデータファイルのダウンロードは、それがゲームであろうと何らかのアプリケーション/ツールであろうと、標準ユーザーにとってはるかに簡単で実行可能です。WindowsのProgram Filesの下にインストールされたゲームを想像してください。アップデータには、何かを変更するための管理者権限が必要であり、実行中のプログラムを変更することはできません。DDDを使用すると、プログラムはデータをダウンロードして使用するだけです。プレーヤーは、更新があることに気付かないかもしれません。


6
DDDの場合は+1。これは、リソースなどに非常に適しています。
Kromsterは、サポートモニカ

@Funnydutchman誰かの答えがあなたを助けたなら、左の数字の上にある矢印をクリックして彼らの答えを支持するのがStack Exchangeの習慣です。回答が最も役立つ場合は、下の矢印の下にあるチェックマークをクリックして回答を受け入れます。どちらのアクションも回答者に評判のボーナスを与え、使用可能な回答をコミュニティにもっと見やすくします。
Nzall

2
最初の方法でコードをどのように書き換える必要があるのか​​わかりません。クラスを追加するだけです(何かが足りない場合を除く)。
SirPython

4
そして、これがオブジェクト指向コードとオブジェクトオブステッドコードの違いです。オブジェクト階層を作成できるからといって、必ずしもそうする必要があるとは限りません。
corsiKa

2
@AgustínLadoクライアントが「これは変わらないだろう」と言ったたびにドルを持っていて、それが変わったら、私たちを夕食のためにまともなレストランに連れて行くことができましたただの平凡なレストラン...まだ2人分の夕食に十分な時間。)
corsiKa

29

経験則では、オブジェクトが異なるコードのみを必要とする場合は異なるクラスを使用し、オブジェクトが異なる値のみを必要とする場合は同じクラスのインスタンスを使用します。

リソースに固有の異なるゲームメカニクスがある場合、それらをクラスで表すのが理にかなっている場合があります。あなたはプルトニウムを持っている場合たとえば、に応じたprocreate半減時間とウサギを持つフィボナッチ数列、それは基本クラスを持っている意味をなさない可能性があるResource方法でUpdate無操作と2つの派生クラスとして実装HalfLifeResourceし、SelfGrowingResourceそのメソッドをオーバーライドして値を増減します(また、両方を隣り合わせて保存するときに何が起こるかを制御するロジックを含めることもできます)。

しかし、あなたのリソースが本当にただの馬鹿げた数字である場合、単純な変数よりももっと凝ったものでそれらを実装することは意味がありません。


あなたの答えを@Phillippに感謝します。これが私が考えていたことです。しかし、リソースはプロパティ/メソッドの点で実際には変更されないので、今はオプション2を使用します
-MDijkstra

14

追加したい2つの追加オプションがあります:
インターフェース:リソースクラスが5つの整数の単なる「ストレージ」であり、各エンティティがリソースに関して異なるロジックを持っている場合(例えば、プレイヤーの支出/略奪、都市の生産リソース)。その場合、クラスをまったく必要としない場合があります。一部のエンティティが他のエンティティとやり取りできる変数を持っていることを公開したかっただけです。

interface IHasResources {
  int Gold { get; set; }
  int Wood { get; set; }
  int Cloth { get; set; }
  // ....
}

class Player : IHasResources { }
class City: IHasResources { }

さらに、これには敵の艦隊を略奪するのとまったく同じコードで都市を略奪できる利点があり、コードの再利用が促進されます。
欠点は、多くのクラスがそれを実装している場合、そのようなインターフェースを実装するのは面倒なことであるため、元の問題ではなくインターフェースを使用して、オプション1または2で解決する可能性があります。

interface IHasResources { 
   IEnumerable<Resource> Resources { get; }
}

インスタンス(enumを使用):場合によっては、リソースタイプを定義するときに文字列ではなくenumを使用することが望ましい場合があります。

enum Resource {
   Gold, Wood, Cloth, //...
}

class ResourceStorage {
   public Resource ResourceType { get; set; }
   public int Value { get; set; }
}

IDEはdotを書き込んだ後に割り当てるときにすべての有効なリソースのリストを提供するため、少しの「安全性」を提供します。ResourceType = Resource.さらに、明示的なTypeまたはcomposition / フラグなど、必要な列挙型を持つ「トリック」あります作成するときに役立つと想像できます:

[Flags]
enum Metal {
 Copper = 0x01/*01*/, Tin = 0x02/*10*/, Bronze = 0x03/*11*/
}
Metal alloy = Metal.Copper; //lets forget Value(s) for sake of simplicity
alloy |= Metal.Tin; //now add a bit of tin
Console.WriteLine(alloy); //will print "Bronze"


最高のものについては、特効薬はありませんが、個人的にはどのような形のインスタンスにも寄りかかりますが、インターフェースほど派手ではないかもしれませんが、シンプルで、継承ツリーが散らからず、広く理解されています。


2
あなたの答えをありがとう@wondra私は列挙型オプションが好きで、銅と錫からその青銅を作った方法; p
MDijkstra

2
列挙型ソリューションに賛成票を投じることができるように、私は特にこのコミュニティに参加しました。enum Description属性を使用して、enumの JSON表現(my-great-enum)からenumのC#表現()にマップすることもできますMyGreatEnum
ダンフォーブス

どうやら私はJavaループから脱出しすぎたようです。インターフェースのフィールド宣言を持つことが許可されるのはいつですか?私の知る限り、これらは自動的に静的で最終的なものであり、したがって、質問で説明されている目的にはあまり使用されません。
M.ヘルツカンプ

2
@ M.Herzkampそれはフィールドではなく、プロパティです-Javaはプロパティをサポートしていません。質問にはC#のタグが付けられ、C#はインターフェイスのプロパティを許可します-プロパティは結局のところ内部のメソッドです。フラグアノテーションについても同じことが怖く、Javaでサポートされていませんが、完全にはわかりません。
ウォンドラ

それを片付けてくれてありがとう!私はC#タグを見逃し、質問のコードは非常にひどくJavaに似ていました:D
M.Herzkamp

2

次の3つの利点があるオプション1を使用する必要があります。

  1. リソースをインスタンス化する方が簡単です-リソースのタイプをパラメーターとして渡す必要はなく、たとえば、 new Gold(50)
  2. リソースに特別な動作を与える必要がある場合は、そのクラスを変更することでできます。
  3. リソースが特定のタイプかどうかを確認する方が簡単です- resource instanceof Gold

すべての答えには長所と短所があり、どちらが良いかを選ぶのは難しいです。質問を編集しましたが、その構造についてどう思いますか?
MDijkstra

1

リソースに独自のビジネスロジックがない場合、または環境、他のリソース(カバーしたトレード以外)またはプレーヤーとのやり取りの特殊なケースシナリオがない場合、オプション2を使用すると、新しいリソースを簡単に追加できます。

クラフト用に2つのリソースを混在させるとどうなるか、リソースの特性が大きく異なる場合(水の入ったバケツが石炭の塊とは非常に異なる場合)またはその他の複雑な経済的相互作用を考慮する必要がある場合、アプローチ1はエンジンに対してははるかに柔軟ですが、データに対してはそうではありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.