Last active
October 26, 2018 06:10
-
-
Save obelisk68/ede984fd5766bd5293b220b3d035d621 to your computer and use it in GitHub Desktop.
3D maze
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
class CubeMaze | |
class Wall | |
def initialize(x, y, h, ob) | |
@wall = Array.new(h + 1) {Array.new(y) {Array.new(x, 1)}} | |
@x, @y = x, y | |
@cube = ob | |
end | |
attr_reader :wall | |
def break(num, n) | |
x, y, h = get_wall_coodinate(num) | |
c1, c2 = get_wall_numbers(x, y, h - 1, n) | |
if c1 != c2 | |
@wall[h][y][x] = 0 | |
c1, c2 = c2, c1 if c1 > c2 | |
@cube.replace(c2, c1) | |
end | |
end | |
def get_wall_coodinate(num) | |
h = num / @x / @y + 1 | |
y = num % (@x * @y) / @x | |
x = num % @x | |
[x, y, h] | |
end | |
def get_wall_numbers(x, y, h, n) | |
f = [0, 0, 1].rotate(-n) | |
x1, y1, h1 = get_cell_coordinate(x, y, h, n) | |
c1 = cells[h1 + f[2]][y1 + f[1]][x1 + f[0]] | |
c2 = cells[h1][y1][x1] | |
[c1, c2] | |
end | |
def get_cell_coordinate(x, y, h, n) | |
case n | |
when 1 | |
x, y, h = h, x, y | |
when 2 | |
x, y, h = y, h, x | |
end | |
[x, y, h] | |
end | |
def cells | |
@cube.cells | |
end | |
end | |
def initialize(x, y, z) | |
@cells = Array.new(z) do |i| | |
Array.new(y) {|j| Array.new(x) {|k| x * y * i + x * j + k}} | |
end | |
@xy = Wall.new(x, y, z, self) | |
@yz = Wall.new(y, z, x, self) | |
@zx = Wall.new(z, x, y, self) | |
@left_wall = [*0...3 * x * y * z - (x * y + y * z + z * x)] | |
@x, @y, @z = x, y, z | |
end | |
attr_reader :cells, :xy, :yz, :zx | |
def break_wall | |
wall_num = @left_wall.sample | |
@left_wall.delete(wall_num) | |
case wall_num | |
when 0 ...(s1 = @x * @y * (@z - 1)) | |
@xy.break(wall_num, 0) | |
when s1...(s2 = s1 + @y * @z * (@x - 1)) | |
@yz.break(wall_num - s1, 1) | |
when s2...(s2 + @z * @x * (@y - 1)) | |
@zx.break(wall_num - s2, 2) | |
else | |
raise "error" | |
end | |
end | |
def replace(from, to) | |
each_cell do |x, y, z| | |
@cells[z][y][x] = to if @cells[z][y][x] == from | |
end | |
end | |
def each_cell | |
@z.times {|i| @y.times {|j| @x.times {|k| yield(k, j, i)}}} | |
end | |
def finish | |
each_cell do |x, y, z| | |
return false unless @cells[z][y][x] == @cells[0][0][0] | |
end | |
true | |
end | |
def generate | |
break_wall until finish | |
[@xy.wall, @yz.wall, @zx.wall] | |
end | |
end |
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
require_relative '3d_maze_generate' | |
require_relative 'miniopengl' | |
module WalkMaze | |
def self.go(x, y, z, xy, yz, zx) | |
MiniOpenGL.app width: 500, height: 500, depth_buffer: :on, title: "3D maze" do | |
px, py, pz = x - 1, y - 1, z - 1 #迷路のスタート位置 | |
dir = [-1, 0, 0] #最初の向きの設定 | |
draw do | |
glEnable(GL_BLEND) #混合処理を可能にします | |
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) | |
self.color_alpha = 0.93 | |
glEnable(GL_DEPTH_TEST) #隠面消去 | |
clear | |
grid = ->(x1, y1, z1, n) { | |
(z1 + 1).times do |i| | |
(y1 + 1).times do |j| | |
coodinates = [0, j, i, x, j, i] | |
line3(*coodinates.rotate(-n)) | |
end | |
(x1 + 1).times do |j| | |
coodinates = [j, 0, i, j, y, i] | |
line3(*coodinates.rotate(-n)) | |
end | |
end | |
} | |
color(1, 1, 1) | |
grid.(x, y, z, 0) | |
grid.(y, z, x, 1) | |
#ひとつの壁の端にわずかに隙間を作る | |
modify = ->(points) { | |
result = [] | |
points.each_slice(3) do |po| | |
result += po.zip(points[0, 3]).map {|a| (a[0] - a[1]).zero? ? a[0] + 0.002 : a[0] - 0.002} | |
end | |
result | |
} | |
#壁の描画 | |
color(0, 0.8, 0) | |
(z + 1).times do |z1| | |
y.times do |y1| | |
x.times do |x1| | |
next if xy[z1][y1][x1].zero? | |
vtx = [x1, y1, z1, x1, y1 + 1, z1, x1 + 1, y1 + 1, z1, x1 + 1, y1, z1] | |
draw_vertex(GL_QUADS, 3, modify.(vtx)) | |
end | |
end | |
end | |
color(0, 0, 0.8) | |
(x + 1).times do |x1| | |
z.times do |z1| | |
y.times do |y1| | |
next if yz[x1][z1][y1].zero? | |
vtx = [x1, y1, z1, x1, y1 + 1, z1, x1, y1 + 1, z1 + 1, x1, y1, z1 + 1] | |
draw_vertex(GL_QUADS, 3, modify.(vtx)) | |
end | |
end | |
end | |
color(0.8, 0, 0) | |
(y + 1).times do |y1| | |
x.times do |x1| | |
z.times do |z1| | |
next if zx[y1][x1][z1].zero? | |
vtx = [x1, y1, z1, x1, y1, z1 + 1, x1 + 1, y1, z1 + 1, x1 + 1, y1, z1] | |
draw_vertex(GL_QUADS, 3, modify.(vtx)) | |
end | |
end | |
end | |
stack do | |
color(1, 1, 1) | |
translate(0.5, 0.5, 0.5) | |
glutSolidSphere(0.3, 20, 16) | |
end | |
display | |
end #--draw end | |
look = ->{ | |
x2, y2, z2 = px + 0.5, py + 0.5, pz + 0.5 | |
look_at(x2, y2, z2, x2 + dir[0], y2 + dir[1], z2 + dir[2], 0, 0, 1) | |
} | |
reshape do |w, h| | |
viewport(0, 0, w, h) | |
init_projection | |
perspective(120, w / h.to_f, 0.2, 20) | |
init_modelview | |
look.() | |
end | |
#dirの方向へ行けるなら移動 | |
move = ->(po, dir) { | |
next_po = po.zip(dir).map {|x| x[0] + x[1]} | |
dir1 = dir.map {|c| (c == 1) ? 1 : 0} | |
f = if dir[0].nonzero? | |
yz[po[0] + dir1[0]][po[2] + dir1[2]][po[1] + dir1[1]].zero? | |
elsif dir[1].nonzero? | |
zx[po[1] + dir1[1]][po[0] + dir1[0]][po[2] + dir1[2]].zero? | |
else | |
xy[po[2] + dir1[2]][po[1] + dir1[1]][po[0] + dir1[0]].zero? | |
end | |
px, py, pz = next_po if f | |
p [px, py, pz] | |
} | |
is_end = ->{ px.zero? && py.zero? && pz.zero? } | |
key_in do |key| | |
case key | |
when " " | |
move.([px, py, pz], dir) | |
when "e" | |
exit if is_end.() | |
end | |
init_modelview | |
look.() | |
redisplay | |
end | |
key_in2 do |key| | |
case key | |
when GLUT_KEY_LEFT | |
dir = [-dir[1], dir[0], 0] | |
when GLUT_KEY_RIGHT | |
dir = [dir[1], -dir[0], 0] | |
when GLUT_KEY_UP | |
move.([px, py, pz], [0, 0, 1]) | |
when GLUT_KEY_DOWN | |
move.([px, py, pz], [0, 0, -1]) | |
end | |
init_modelview | |
look.() | |
redisplay | |
end | |
end | |
end | |
end | |
x, y, z = 3, 4, 5 | |
xy, yz, zx = CubeMaze.new(x, y, z).generate | |
WalkMaze.go(x, y, z, xy, yz, zx) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment