neo3D迷路

DXRuby1.1.0devにて。と書いておかないと1.0.7で動かそうとしてエラーになる人が出そうだから。
メッシュ作成と描画ができれば結構簡単に作れるのではないかと思ったが、なかなか難しい。

メッシュで迷路全体の壁を作ってしまって、描画一発で3D迷路する方法を試してみた。

require 'dxruby'

rgb = [[0, 0, 0], [0, 0, 155], [0, 155, 0], [0, 155, 155], [155, 0, 0], [155, 0, 155], [155, 155, 0], [155, 155,155]]
image = Image.new( 128 * 8, 128 )
rgb.each_with_index do |c, i|
  image.boxFill(i * 128, 0, i * 128 + 127, 127, c)
end

def createSquare(p, t)
  p = p.flatten
  t = t.flatten
  pa = Polygon.new
  pa.vertex = [p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8]]
  pa.tutv = [t[0], t[1], t[2], t[3], t[4], t[5]]
  pb = Polygon.new
  pb.vertex = [p[0], p[1], p[2] ,p[6], p[7], p[8], p[9], p[10], p[11]]
  pb.tutv = [t[0], t[1], t[4], t[5], t[6], t[7]]
  [pa, pb]
end

def createWall(pos, size, tutv)
  point = [[-1, -1, -1], [1, -1, -1], [1, -1, 1], [-1, -1, 1], [-1, 1, -1], [1, 1, -1], [1, 1, 1], [-1, 1, 1]]
  point.map! do |p1|
    [p1[0] * size + pos[0], p1[1] * size + pos[1], p1[2] * size + pos[2]]
  end
  p = createSquare([point[0], point[1], point[2], point[3]], tutv[0])
  p.concat createSquare([point[3], point[2], point[6], point[7]], tutv[1])
  p.concat createSquare([point[0], point[3], point[7], point[4]], tutv[2])
  p.concat createSquare([point[1], point[0], point[4], point[5]], tutv[3])
  p.concat createSquare([point[2], point[1], point[5], point[6]], tutv[4])
  p.concat createSquare([point[7], point[6], point[5], point[4]], tutv[5])
  p
end

tutv = []
for i in 1..6
  tutv.push([i * 128, 0, i * 128 + 127, 0, i * 128 + 127, 127, i * 128, 127])
end

# マップ
map = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
       [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
       [1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1],
       [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1],
       [1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1],
       [1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1],
       [1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1],
       [1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1],
       [1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1],
       [1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1],
       [1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1],
       [1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1],
       [1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1],
       [1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1],
       [1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1],
       [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
      ]

p = []
map.each_with_index do |ary, y|
  temp = []
  ary.each_with_index do |w, x|
    if w == 1
      p.concat(createWall([x * 640 - 640 * 8, y * 640 - 640 * 8, 0], 320, tutv))
    end
  p.concat(temp)
  end
end

m = Mesh.new(p, image)

Window.zn = -500

x = -6*640 + 320
z = -6*640 + 320
angle = 90
Window.loop do
  angle += Input.x * 8
  if Input.y != 0
    x = x + Math.cos((angle-90) * Math::PI / 180) * Input.y * -8
    z = z + Math.sin((angle-90) * Math::PI / 180) * Input.y * -8
  end
  x1 = Math.cos(-angle * Math::PI / 180) * -x - Math.sin(-angle * Math::PI / 180) * -z
  z1 = Math.sin(-angle * Math::PI / 180) * -x + Math.cos(-angle * Math::PI / 180) * -z
  Window.drawMesh([x1,240,z1], [90, angle, 0], [1,1,1], m, -10)
end

迷路がスケール→回転→移動という処理順なので、自分の位置にあわせて移動するのに移動量を回転しなければならない。
んで、がんばってみたけどまだなんか回転がおかしい。
これは俺がしょぼいからなのだが。
あと、衝突判定とか作るのも大変そうだ。移動は2Dだから、自分の大きさを作って判定すれば問題はないだろう。
そのへんはテキトーに作るんじゃなくて、丁寧に作りこめばちゃんとしたものは作れそうだとは思った。
とりあえずソート関連と1.0系の機能の実装がきちんとできたら開発版1.1系として1.1.0をWebに置こうかな。
誰か試して必要そうな機能とかの要望を出してくれると嬉しいのだけど。自分で作っておきながらさっぱりわからん。