スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

[Ruby]ローグ風ダンジョンを自動生成するプログラムを書いてみた。

最近ゲームAIについて勉強しているのですが、そのAIが動き回るための世界をまず作ろうと考え、構造がシンプルなのとこちらのページに触発されて前々から作ってみたかったという理由からローグライクなゲームを作ることにしました。

で、まず手をつけたのがダンジョン生成。これさえ完成してしまえばあとは割と気合でなんとかなります、多分。

class Createmap
H_MAX = 30 # マップの最大縦幅定数
W_MAX = 42 # マップの最大横幅定数
def initialize(h, w, hm, wm)
@h = h
@w = w
@hm = hm
@wm = wm
@map = Array.new(H_MAX){Array.new(W_MAX, 0)} # マップデータ用
@start = Array.new(@h){Array.new(@w, nil)} # 部屋の設置開始位置保持用
@room_there = Array.new(@h){Array.new(@w, nil)} # 部屋が存在するかどうか
sprit_equal
make_room_equal
make_road
delete_sprit
end

attr_reader :map

# デバッグ用CUI描画機能
#def render
# p @room_there
# @map.each_index do |i|
# @map[i].each_index do |j|
# print "■" if @map[i][j] == 0
# print "□" if @map[i][j] == 1
# print "#" if @map[i][j] == 9
# end
# puts
# end
#end

private
# 部屋を横にw個,縦にh個等間隔で分割する関数.第三・四引数は部屋の縦横最小サイズ
def sprit_equal
# 一部屋の大きさを決める
@h_size = H_MAX / @h
@w_size = W_MAX / @w
# 部屋が存在するかどうかを決める
@room_there.each_index do |a|
@room_there[a].each_index do |b|
@room_there[a][b] = rand(10) == 0? FALSE : TRUE
end
end

# 部屋の境界線を@mapに書き込む
@map.each_index do |i|
@map[i].each_index do |j|
@map[i][j] = 9 if i % @h_size == 0 && i != 0 && i != (H_MAX - 1)
@map[i][j] = 9 if j % @w_size == 0 && j != 0 && j != (W_MAX - 1)
end
end
end

# 等間隔に分割した領域に部屋を作る
def make_room_equal
#各領域に設置する部屋のサイズを決める
@room_size = Array.new(@h){Array.new(@w, nil)}
@room_size.each_index do |a|
@room_size[a].each_index do |b|
if @room_there[a][b]
@room_size[a][b] = [@hm + rand(@h_size - @hm - 2), @wm + rand(@w_size - @wm - 2)] if a == 0
@room_size[a][b] = [@hm + rand(@h_size - @hm - 4), @wm + rand(@w_size - @wm - 4)] if a > 0
end
end
end

# 各領域に部屋を設置する
@h.times do |i|
@w.times do |j|
if @room_there[i][j]
if i == 0
start_h = 1 + rand((@h_size - @room_size[i][j][0]) / 2)
else
start_h = 2 + rand((@h_size - @room_size[i][j][0]) / 2)
end
if j == 0
start_w = 1 + rand((@w_size - @room_size[i][j][1]) / 2)
else
start_w = 2 + rand((@w_size - @room_size[i][j][1]) / 2)
end
for c in start_h..(@room_size[i][j][0] + start_h)
for d in start_w..(@room_size[i][j][1] + start_w)
@map[c + i * @h_size][d + j * @w_size] = 1
end
end
@start[i][j] = [start_h, start_w]
end
end
end
end

# 設置した部屋に横方向と縦方向へ道を作る
def make_road
@h.times do |i|
@w.times do |j|
if @room_there[i][j]
# 横方向に通路を作成する
if j != (@w - 1) && @room_there[i][j + 1]
width_h1 = @start[i][j][0] + rand(@room_size[i][j][0])
width_w1 = @start[i][j][1] + @room_size[i][j][1]
# 一つ目の部屋から右へ通路を延ばす
width_w1.upto(@w_size){|a| @map[width_h1 + i * @h_size][a + j * @w_size] = 1}
width_h2 = @start[i][j + 1][0] + rand(@room_size[i][j + 1][0])
# 二つ目の部屋から左へ通路を延ばす
0.upto(@start[i][j + 1][1]){|b| @map[width_h2 + i * @h_size][b + (j + 1) * @w_size] = 1}
delta1 = (width_h1 - width_h2).abs
# 左右の部屋の通路を連結する
if delta1 > 1
if width_h1 > width_h2
width_h2.upto(width_h1){|c| @map[c + i * @h_size][(j + 1) * @w_size] = 1}
else
width_h1.upto(width_h2){|d| @map[d + i * @h_size][(j + 1) * @w_size] = 1}
end
end
end
# 縦方向に通路を作成する
if i != (@h - 1) && @room_there[i + 1][j]
height_h1 = @start[i][j][0] + @room_size[i][j][0]
height_w1 = @start[i][j][1] + rand(@room_size[i][j][1])
# 一つ目の部屋から下へ通路を延ばす
height_h1.upto(@h_size){|e| @map[e + i * @h_size][height_w1 + j * @w_size] = 1}
height_w2 = @start[i + 1][j][1] + rand(@room_size[i + 1][j][1])
# 二つ目の部屋から上へ通路を延ばす
0.upto(@start[i + 1][j][0]){|f| @map[f + (i + 1) * @h_size][height_w2 + j * @w_size] = 1}
delta2 = (height_w1 - height_w2).abs
if delta2 > 1
if height_w1 > height_w2
height_w2.upto(height_w1){|g| @map[(i + 1) * @h_size][g + j * @w_size] = 1}
else
height_w1.upto(height_w2){|h| @map[(i + 1) * @h_size][h + j * @w_size] = 1}
end
end
end
end
end
end
end

# 境界線を削除する
def delete_sprit
@map.each_index do |i|
@map[i].each_index do |j|
@map[i][j] = 0 if @map[i][j] == 9
end
end
end
end


# デバッグ用
#map =Createmap.new(3, 3, 3, 4)
#map.render


こんな感じ。勢いで作ったためかなり適当です。

均等に分割された部屋が欲しかったので(今後のAI関連の課題のため)、部屋を等分して線でつなげるというシンプルな構造になってます。

これをGUI化してEXEで固めたものを作ったのでおいておきます。
Roge.zip

次は、マップチップ用にこのダンジョンデータを弄って見た目を何とかすることからはじめようと思います。絵が揃わないとやる気がでないタイプなんで……。

テーマ : プログラミング - ジャンル : コンピュータ

コメント
コメントの投稿
管理者にだけ表示を許可する

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。