Last active
December 13, 2015 16:58
-
-
Save umegaya/4943761 to your computer and use it in GitHub Desktop.
mrogue 設計
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| scene | |
| +-childs (entity) | |
| +- wall (x, y) | |
| +- wall (x1, y1) | |
| +- player (xx, yy) | |
| +- item1 | |
| +- item2 | |
| +- NPC (xx1, yy1) | |
| +- item1 | |
| +- item2 | |
| +- ItemN (xxx, yyy) | |
| pop @ x, y => refresh (x, y) | |
| depop @ x, y => refresh (x, y) | |
| move @ x1,y1 - x2,y2 => refresh (x1, y1), refresh (x2, y2) | |
| change @ x, y => refresh (x, y) | |
| sceneは縦x, 横yの配列の配列の配列 | |
| scene[x][y]にはx, y座標にあるオブジェクト全体が積まれている | |
| refresh(x, y)はscene[x][y]の配列を総なめしてプライオリティに従って表示する | |
| (ユーザー、モンスター>アイテム モンスター、アイテム内部ではランク的なものでソート) | |
| canvasは画面サイズの(たぶん7x10)ボタンの配列で画像の表示と入力の受付を行う | |
| x, yが画面内の場合のみrefreshは実際の描画を書き換えることになる | |
| そうでない場合、x,yが画面内に入ってきたタイミングでrefresh(x,y)を呼び出して画像をセットする感じ | |
| おそらく通知がくるのはユーザーの周囲、canvas + 2のサイズ相当のみ (12x12かな?) | |
| ほかは可視範囲内に入ったときにとってくる。たぶん12マス分 | |
| 可視範囲は小さくできてもいい | |
| client { | |
| scene[MAX_X][MAX_Y] | |
| canvas[DISP_X][DISP_Y] | |
| canvas_origin_x, canvas_origin_y | |
| visible_w, visible_h | |
| -- viewportは | |
| canvas_origin_x + (canvas_origin_x - visible_w) / 2, | |
| canvas_origin_y + (canvas_origin_y - visible_h) / 2, | |
| canvas_origin_x - (canvas_origin_x - visible_w) / 2, | |
| canvas_origin_y - (canvas_origin_y - visible_h) / 2, | |
| } | |
| server { | |
| scene[MAX_X][MAX_Y] | |
| } | |
| ユーザーが行動するごとに経過時間がキューに積まれる(そうしないとレスポンスが相当悪くなる) | |
| 5,4,4,5秒経過する行動を4回やるとキューには | |
| {5,4,4,5}とつまれ、サーバー内部のfiberによって | |
| tick(5), tick(4), tick(4), tick(5)と処理される。たぶんwaitはなくてもよい | |
| tickごとにオブジェクトのon_tickが実行されそれに応じた行動をとることになる。 | |
| 単純にtickを実行するとそれしか処理されないのでやっぱりwaitは必要。 | |
| 一回tickをするたびにsuspendすればよかったりするかも | |
| 0.5秒ぐらい? | |
| Object | |
| 複雑な継承構造は作らない | |
| 移動、AI、攻撃など、機能ごとに応じてモジュールを作り、mixinしてオブジェクトを作る | |
| データからクラスを組み立て、それをインスタンス化するイメージ | |
| ID, name, hp, attack, defense, attack_module, move_module, AI, Skill1, Skill2, Skill3, Skill4 | |
| 100, dragon, 100000, 1000, 1000, DoubleAttack, FlyMove, StrongAI, FireBreath, None, None, None | |
| => | |
| class Dragon.extends.NPC.with.DoubleAttack.with.FlyMove.with.StrongAI.with.FireBreath {} | |
| を作成してDragon.newでオブジェクトを作るとこれがドラゴンとして振る舞う、ようなイメージ | |
| 現状の課題は、ランダムで有無が決まるtraitsをどうするか、と動的に状態が変わるtraitsをどうするか | |
| 例を挙げると | |
| 前者は、ときどき強力な武器を持ったコボルトがいる、というのをどうデータで表現するか | |
| 後者は、酩酊すると仲間を斬りつける、といったAIの変化をどう表現するか | |
| どちらもベースのtraitsのロジックの中に突っ込んでしまえばいいような気もするが、 | |
| 前者で例えば、侍というモンスターだけが強力な日本刀を持っている、であるとか | |
| 後者でドラゴンだけは酩酊するとそのときだけしか使わないスキルをつかう、 | |
| などはそれだとベースのロジックがふくれあがる結果となるのでさけたい。 | |
| 前者はInventoryTraits的なもので対応する | |
| 後者は難しい問題でbuff/debuffをどう管理するかという問題と関係している。 | |
| MMO的にEffectのリストをちゃんと処理するべきか。(フラグにしてベースのロジックに持っていくか、動的にAITraitsを差し替えるかはまた別の問題) | |
| Builder, Probability, Template | |
| ============================== | |
| Builderはランダムなダンジョンの地形を作り、アイテムやモンスターを配置するロジックを表現する | |
| BaseBuilderやMonsterHouseBuilderがある | |
| Builderは以下のカテゴリー分けでアイテムや門巣をポップさせる | |
| unique(U) | |
| legend(L) | |
| ultra-rare(UR) | |
| super-rare(SR) | |
| rare(R) | |
| uncommon(UC) | |
| common(C) | |
| probabilityは実際にポップさせるidを(templateと連携して)決定する | |
| Builder:pop(category, type) --> category: U,L,UR,SR,R,UC,C, type --> monster, item, terrain | |
| probability:choose(category, type) | |
| end | |
| probability : templates(monster, item, terrain)を受け取ってなかみをランダムにpopさせる。 | |
| ポップするもので、何か特定のタイプを増やすとか、そういうのはここを差し替える(ゴールド強化ダンジョン!アイテム強化ダンジョン!みたいな) | |
| templateは | |
| 実際にポップするentityの具体的なパラメーターや振る舞いを保持している。また上記のカテゴリー分けも持っている(U,L,UR,SR,R,UC,C) | |
| UI | |
| アイテムリスト:swipeで右から? | |
| ログ:オーバーレイ表示 or 左からswipe | |
| 画面上へのアクション:タップ。 | |
| 何もないところへのタップは自動移動 | |
| アイテムが表示されているところは:そこまで移動して拾う? | |
| NPCが表示されているところは:そのNPCをターゲットして攻撃 | |
| shootできればshoot | |
| そうでなければ近くまで移動してattack | |
| アイテム、マジック、スキル | |
| 1ダンジョンは1スレッドで処理される前提 | |
| action queue | |
| ============ | |
| ユーザーの操作はかならずaction queueというテーブルを生成する。 | |
| action queueはfiberによってシーケンシャルに実行される。 | |
| 通信はしてもしなくてもよい。action queueの実行中は別のアクションは基本的に開始できない | |
| キャンセルはできる。(攻撃を受けたときなど、自動的にキャンセルされる場合もある) | |
| attack, skill, magic, effect | |
| ============================ | |
| effectは様々なシチュエーションでユーザーに発生する効果を定義するtrait | |
| 時間でダメージを受けたり攻撃ごとに体力が回復したりみたいな。 | |
| skillはeffectとeffectのパラメータの組み合わせをいくつか集めてまとまった効果にしたもの。エンティティの属性として付与されている | |
| magicはskillと同様だが、魔法書を「使って」いくらかの時間を費やすことで使用回数がスタックされるもの | |
| attackをどう定義するか | |
| attackもskillとして定義されるべきか | |
| entity | |
| - inventory | |
| items | |
| - equipment | |
| weapon | |
| armor | |
| shield | |
| helm | |
| gauntlet | |
| left-ring | |
| right-ring | |
| amulet | |
| - magic_inventory | |
| magics | |
| - attack | |
| attack_skill | |
| - skill_inventory | |
| skills | |
| attackは | |
| basic_attack | |
| weapon_attack | |
| AI | |
| ===== | |
| AIは「行動の種類」と「手段」、「ターゲット」を決定するのが役割(手段はないこともある) | |
| (例:「隣のuser」を「武器」で「攻撃」、「自分」に「薬草」を「使う」、「石ころ」を「拾う」) | |
| 目的に沿って上記を選択するので、自身の「気分」みたいなものを持っていることが望ましい | |
| attack | |
| rescue | |
| escape | |
| みたいな。 | |
| choose_howみたいなやつで、そのユーザーが利用可能な手段の中から適当なものをリストアップする。 | |
| リストアップしたものをベースはランダムで選んでもいいし、賢いアルゴならもっとがんばって選んでもいい。 | |
| ベースのシステムではリストアップ>ランダムで選ぶところまでにする。 | |
| 「気分」の遷移も簡単にやっちゃう。 | |
| defaultではattack、体力が2割以下でa)回復手段があればrescue、b)なければescape | |
| hate, monsterのgroupなどもより賢くするのであれば必要だが今回は考えない | |
| user:attack(target, user:weapon()) | |
| user:use(user, herb) | |
| user:pick(item) | |
| how item is used | |
| ================= | |
| - 範囲内に存在しているエンティティに対して使用する | |
| user:use(item, target) | |
| - 装備している武器onlyで範囲内に存在しているエンティティに対して攻撃する | |
| user:attack(item, target) | |
| - 向きを指定して、その方向にいるオブジェクトのうち一番最初or範囲内全て(これはterrain or field_objectを生成してそれを移動させることで可能かもしれない) | |
| :弓をうつ、杖を使う、薬を投げる | |
| user:fire(item, dirx, diry) | |
| - 場所を指定して、その場所および周囲に存在するオブジェクトのうちいくつかor全部 | |
| :爆弾 | |
| user:throw(item, posx, posy) | |
| - 自分のみ。inventory windowから直接使うだけ。 | |
| :薬を飲む、巻物を読むなど。 | |
| user:use(item, user) | |
| action | |
| ====== | |
| タップした先のグリッドに存在するオブジェクトと可能なアクション(見えている場合) | |
| npc : 話す(friendly)、攻撃(enemy) | |
| monster : 話す(friendly)、攻撃(enemy) | |
| field_object : 使う、壊す | |
| item : 拾う、使う | |
| upstair : のぼる(ダンジョンから脱出する) | |
| downstair : おりる(次の階へ) | |
| タップ=>フリックで選択 | |
| その場所の1つ手前までは自動で移動し、あとはnpcなどであればその位置で最終的なアクション、itemやterrainであれば同じ位置まで移動して最終アクションをする | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment