Random Dungeon Maker Core from RDGC - Ruby(Random) Dungeon Game Core
Ruby
Switch branches/tags
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
lib
spec
.document
.gitignore
Gemfile
LICENSE
README.rdoc
Rakefile
rdgc-dm.gemspec

README.rdoc

rdgc-dm

Author

parrot_studio <parrot at users.sourceforge.jp>

License

The MIT License

  • 要求されたサイズのランダムダンジョンを生成

  • ダンジョンは部屋と道で構成される

Install

gem install rdgc-dm

Usage

require 'rubygems'
require 'rdgc-dm'

include RDGC::Maker

board = DivideDungeonMaker.create(30, 40) # width=30, height=40のMap::Boardを作る場合
board = DivideDungeonMaker.create(30, 40, :min_room_count = 4) # パラメータ指定(4つ以上の部屋数を期待)

board.each do |x, y|    # each で各座標を順に処理
  t = board.tile(x, y)  # Tileオブジェクト取得
  case
  when t.wall?          # 壁
    ...
  when t.room?          # 部屋
    ...
  when t.road?          # 道
    ...
  end
end

board.each_tile do |x, y, t| # each_tileで座標とTileを一緒に取得
  ...
end

rooms = board.rooms # Map::Roomオブジェクトの配列取得
roads = board.roads # Map::Roadオブジェクトの配列取得

r = rooms.choice
x, y = r.random_point # あるエリアのランダムな座標を取得

board.room?(2, 3)      # 指定座標(x, y)が部屋か判定
board.road?(2, 3)      # 指定座標(x, y)が道か判定
board.movable?(2, 3)   # 指定座標(x, y)が移動可能(=部屋or道)か判定

# その他、Map::Areaに定義されたメソッドは全て使える

# RDGC::Util::RandomUtilで定義され、top-levelにinclude済みのメソッド
# 数値は全て整数を指定すること

bool_rand            # trueかfalseを返す
range_rand(min, max) # minからmaxまでのどれかの整数値を返す
select_rand(:a => 3, :b => 2, :c => 1) # :aを3/(3+2+1)、:bを2/(3+2+1)...の確率で返す

dice(5, 10)      # 10面のサイコロを5回振った合計を返す
5.dice(10)       # Integer#dice(max)が定義済みで、この場合はdice(5, 10)と同じ 
5.d10            # TRPGプレイヤーにおなじみの書き方

# その他、細かなメソッドはソースやspec等参照

Create Parameters

前提として、生成パラメータは努力目標
できるだけ指定を満たそうとはするが、ランダムなので保証はできない

まず全体を一つのBlockとして定義し、それを再帰的に分割した後、
各Blockに部屋か交差点を作るため、Blockとは1:1の関係になる
  • :min_block_size => 分割Blockの最低サイズ

  • :min_block_count => Blockの最低生成数

  • :max_block_count => Blockの最大生成数

  • :min_room_size => 部屋の最低サイズ(デフォルトは4で、4以下は強制的に4)

  • :max_room_size => 部屋の最大サイズ

  • :min_room_count => 部屋の最低生成数(デフォルトは2)

  • :max_room_count => 部屋の最大生成数

  • :force_room_count => 部屋の固定生成数(min/max_room_countを無視)

  • :max_depth => 分割再帰の深さ max_depth=nのとき、Blockの最大数は2^nになる

  • :cross_road_ratio => 交差点生成率(0 <= x <= 9)

0.2.2修正点

  • min_block_countを追加。分割可能なBlockがあれば指定数まで分割しようとする

  • force_room_countを追加。他のroom_count指定を無視し、指定された数の部屋を作る。ただし、Blockの数を超えられない

  • min_room_size最低値を2固定に修正。1を指定しても2に修正される

Blind Area(from 0.2)

Boardが保持する座標系について、座標ごとの可視・不可視を制御する仕組み
あくまで状態の管理であり、描画時にその情報を元にした処理を行わないと意味がない
サンプル実装である"RO"gueの動作を参考に

sourceforge.jp/projects/rdgc/

require 'rubygems'
require 'rdgc-dm'

board = RDGC::Maker::DivideDungeonMaker.create(30, 40)
# Boardを作っただけでは可視制御は有効にならない
board.blind_mode? #=> false

# 1. Board#set_blind_modeで可視制御を有効にする
board.set_blind_mode # :none/:normal/:blind 省略時は:normal

# 2. 必要ならばArea#set_blindでArea単位の個別指定をする
board.rooms.choice.set_blind(:dark)

# 3. Board#fill_blindで可視状態を初期化する
# 2.と3.の手順が逆転すると正常に動かない
board.fill_blind

# 4. Board#open_blind(x, y, view_range)で不可視状態を可視状態にする
# playerが(5, 10)に存在し、見える範囲が2
view_range = 2
board.open_blind(5, 10, view_range)

# 5. Board#visible?/invisible?/dark?で可視性をチェックし、描画に使う
board.visible?(5, 10) #=> true
board.visible?(3, 10) #=> true
board.visible?(2, 10) #=> false
# 実際には移動可能範囲のみが可視状態になる(壁があればそこは処理されない)

# ...

# playerが(6, 10)に移動した
board.open_blind(6, 10, view_range)
board.visible?(6, 10) #=> true
board.visible?(5, 10) #=> true
# 一度歩いた場所は見えるようになっている
board.visible?(3, 10) #=> true

Area#set_blindに指定できるレベル

  • :none => Area内は最初から全て可視

  • :open => 最初は全体が不可視だが、Area内の座標に対してopen_blindされると、Area全体が可視状態になる

  • :blind => 最初は全体が不可視で、open_blindされた場所だけが可視状態

  • :dark => open_blind時にArea内の状態が一度初期化され、常にopen_blindされた領域しか見えない(ダークゾーン)

Board#set_blind_modeに指定できるレベル

  • :normal => Roomが全て:open、Roadが全て:blind(デフォルト)

  • :none => Room/Road共に:none

  • :blind => Room/Road共に:blind

Board全体を:darkに指定するオプションは定義されていない
必要ならば手動で行う

board.areas.each{|a| a.blind_level(:dark)}

FAQ

パラメータが適用されない

パラメータには適用優先順位があります
  1. min_block_size

  2. min_block_count

  3. max_block_count

  4. max_depth

  5. force_room_count

  6. min_room_count

  7. max_room_count

  8. cross_road_ratio

  9. max_room_size

  10. min_room_size

上位のパラメータに対し、下位のパラメータが矛盾した場合、
無視はしませんが、保証はされません

max_room_count=1なのに部屋が2個できる

min_room_countのデフォルト値が2なので、
上記の優先順位に従い、部屋が2個できます
(デフォルトが2個なのは、スタート地点とゴール地点を作るためです)
明示的にforce_room_count=1を指定しないと部屋が一つだけにはなりません

道に(部屋でない)行き止まりができる

仕様です

それで片付けるのもあれなので補足すると、
つなげられそうな交差点を、できるだけつなぐようにしているものの、
周囲に残りBlockがない等、どうしようもない場合に行き止まりができます

あまりたくさんできると問題ですが、
たまにあるくらいはゲームとしていいんじゃないかと

最大分割深度(max_depth)って何?

DivideDungeonMakerは最初のBlockを起点にして、再帰的な分割をしようとします

この分割回数の最大値がmax_depthの指定で、これを小さくすることで、
小さいBlockだらけになるのを防げます
max_depth=nの時、作られるBlockの最大値は2^nです

イベントやBOSS用に、広い部屋が1つだけ欲しい

min_room_sizeをx/y以上にしたうえで、
min_block_sizeをx/y以上にするか、max_block_count=1を指定してください
全体が1Blockになり、限界までRoomを大きくしようとします

スタートとゴール(階段)って無いの?

rdgc-dmはあくまで部屋と道(の座標系)を作るための仕組みです
スタートやゴールの概念は各ゲームによって異なるため、
rdgc-dmには含んでいません(RDGCとしては存在します)

Area#ramdom_pointで各Areaのランダムな座標が取れますので、
それを使ってスタートやゴールや障害を配置してください

部屋を作りたくない(ただの迷路にしたい)

0.2.2から追加されたforce_room_count=0を指定してください
部屋を一切作らなくなります

自分でロジックを書きたい

  • RDGC::Maker::DungeonMakerをincludeしたクラス

  • RDGC::Maker::TempBlockを継承したクラス

これらを組み合わせると自分のロジックが書けます
詳しくはDivideDungeonMaker/DivideTempBlockのソースを見てください

Copyright

Copyright © 2010-2011 parrot_studio. See LICENSE for details