818 lines
24 KiB
GDScript3
818 lines
24 KiB
GDScript3
extends Spatial
|
|
|
|
|
|
# Declare member variables here. Examples:
|
|
# var a = 2
|
|
# var b = "text"
|
|
|
|
var wall = preload("res://scenes/maps/wall.escn")
|
|
var window = preload("res://scenes/maps/window.tscn")
|
|
var door = preload("res://scenes/maps/door.tscn")
|
|
var entry = preload("res://scenes/maps/door-outside.tscn")
|
|
var fl = preload("res://scenes/maps/floor.escn")
|
|
var stairs = preload("res://scenes/maps/stairs-small.escn")
|
|
|
|
|
|
# Called when the node enters the scene tree for the first time.
|
|
var rnd: RandomNumberGenerator
|
|
var contour = [
|
|
Vector2(-10, -10), Vector2(10, -10),
|
|
Vector2(10, 10), Vector2(-10, 10)
|
|
]
|
|
|
|
var spaces = [
|
|
"entry",
|
|
"window",
|
|
"corridoor"
|
|
]
|
|
#var adj = {
|
|
# "entry": ["hall"],
|
|
# "hall": ["hall1", "kitchen", "toilet1", "bathroom1", "hall2"],
|
|
#}
|
|
class Floor extends Reference:
|
|
const FLAG_WALL_LEFT = (1 << 0)
|
|
const FLAG_WALL_UP = (1 << 1)
|
|
const FLAG_WALL_RIGHT = (1 << 2)
|
|
const FLAG_WALL_DOWN = (1 << 3)
|
|
const FLAG_FLOOR = (1 << 4)
|
|
const FLAG_ENTRY_LEFT = (1 << 5)
|
|
const FLAG_ENTRY_UP = (1 << 6)
|
|
const FLAG_ENTRY_RIGHT = (1 << 7)
|
|
const FLAG_ENTRY_DOWN = (1 << 8)
|
|
const FLAG_WINDOW_LEFT = (1 << 9)
|
|
const FLAG_WINDOW_UP = (1 << 10)
|
|
const FLAG_WINDOW_RIGHT = (1 << 11)
|
|
const FLAG_WINDOW_DOWN = (1 << 12)
|
|
const FLAG_DOOR_LEFT = (1 << 13)
|
|
const FLAG_DOOR_UP = (1 << 14)
|
|
const FLAG_DOOR_RIGHT = (1 << 15)
|
|
const FLAG_DOOR_DOWN = (1 << 16)
|
|
const FLAG_STAIRS = (1 << 17)
|
|
const FLAG_WALL_MASK = (FLAG_WALL_LEFT | FLAG_WALL_UP | FLAG_WALL_RIGHT | FLAG_WALL_DOWN)
|
|
const FLAG_ENTRY_MASK = (FLAG_ENTRY_LEFT | FLAG_ENTRY_UP | FLAG_ENTRY_RIGHT | FLAG_ENTRY_DOWN)
|
|
const FLAG_WINDOW_MASK = (FLAG_WINDOW_LEFT | FLAG_WINDOW_UP | FLAG_WINDOW_RIGHT | FLAG_WINDOW_DOWN)
|
|
const FLAG_DOOR_MASK = (FLAG_DOOR_LEFT | FLAG_DOOR_UP | FLAG_DOOR_RIGHT | FLAG_DOOR_DOWN)
|
|
const FLAG_LEFT_MASK = (FLAG_WALL_LEFT | FLAG_ENTRY_LEFT | FLAG_WINDOW_LEFT | FLAG_DOOR_LEFT)
|
|
const FLAG_UP_MASK = (FLAG_WALL_UP | FLAG_ENTRY_UP | FLAG_WINDOW_UP | FLAG_DOOR_UP)
|
|
const FLAG_RIGHT_MASK = (FLAG_WALL_RIGHT | FLAG_ENTRY_RIGHT | FLAG_WINDOW_RIGHT | FLAG_DOOR_RIGHT)
|
|
const FLAG_DOWN_MASK = (FLAG_WALL_DOWN | FLAG_ENTRY_DOWN | FLAG_WINDOW_DOWN | FLAG_DOOR_DOWN)
|
|
var wall_length = 2.0
|
|
var grid_areas = []
|
|
var grid_walls = []
|
|
var grid_rect: = Rect2()
|
|
var grid_size = 2.0
|
|
var size_x:int = 0
|
|
var size_y:int = 0
|
|
var windows = []
|
|
var walls_tiles = []
|
|
var enterance
|
|
var enterance_tile = -1
|
|
var stairs_pos: Vector2
|
|
var stairs_tile: int
|
|
const big_stairs_w = 10
|
|
const big_stairs_h = 8
|
|
const small_stairs_w = 4
|
|
const small_stairs_h = 4
|
|
func copy():
|
|
var ret = Floor.new()
|
|
ret.wall_length = wall_length
|
|
ret.grid_areas = grid_areas.duplicate()
|
|
ret.grid_walls = grid_walls.duplicate()
|
|
ret.grid_rect = grid_rect
|
|
ret.grid_size = grid_size
|
|
ret.size_x = size_x
|
|
ret.size_y = size_y
|
|
ret.windows = windows.duplicate()
|
|
ret.walls_tiles = walls_tiles.duplicate()
|
|
ret.enterance = enterance
|
|
ret.enterance_tile = enterance_tile
|
|
ret.stairs_pos = stairs_pos
|
|
ret.stairs_tile = stairs_tile
|
|
return ret
|
|
func init_grid(contour):
|
|
for k in range(contour.size()):
|
|
var p1 = contour[k]
|
|
var p2 = contour[(k + 1) % contour.size()]
|
|
for x in contour:
|
|
grid_rect = grid_rect.expand(x)
|
|
size_x = grid_rect.size.x / grid_size + 2
|
|
size_y = grid_rect.size.y / grid_size + 2
|
|
grid_areas.resize(size_x * size_y)
|
|
grid_walls.resize(size_x * size_y)
|
|
for t in range(size_x * size_y):
|
|
grid_areas[t] = 0
|
|
grid_walls[t] = 0
|
|
func init_walls(contour):
|
|
for y in range(size_y):
|
|
for x in range(size_x):
|
|
var point_flags = 0
|
|
var px = float(x) * grid_size + grid_rect.position.x - grid_size
|
|
var py = float(y) * grid_size + grid_rect.position.y - grid_size
|
|
var p0 = Vector2(px - 0.1, py - 0.1)
|
|
var p1 = Vector2(px - 0.1 + grid_size + 0.1, py)
|
|
var p2 = Vector2(px + grid_size + 0.1, py + grid_size + 0.1)
|
|
var p3 = Vector2(px - 0.1, py + grid_size + 0.1)
|
|
var p4 = p0 + Vector2(grid_size * 0.5, grid_size * 0.5) + Vector2(0.1, 0.1)
|
|
var p01 = p0.linear_interpolate(p1, 0.5)
|
|
var p12 = p1.linear_interpolate(p2, 0.5)
|
|
var p23 = p2.linear_interpolate(p3, 0.5)
|
|
var p30 = p3.linear_interpolate(p0, 0.5)
|
|
if Geometry.is_point_in_polygon(p0, PoolVector2Array(contour)):
|
|
point_flags |= 1
|
|
if Geometry.is_point_in_polygon(p1, PoolVector2Array(contour)):
|
|
point_flags |= 2
|
|
if Geometry.is_point_in_polygon(p2, PoolVector2Array(contour)):
|
|
point_flags |= 4
|
|
if Geometry.is_point_in_polygon(p3, PoolVector2Array(contour)):
|
|
point_flags |= 8
|
|
if Geometry.is_point_in_polygon(p4, PoolVector2Array(contour)):
|
|
point_flags |= 16
|
|
if Geometry.is_point_in_polygon(p01, PoolVector2Array(contour)):
|
|
point_flags |= 32
|
|
if Geometry.is_point_in_polygon(p12, PoolVector2Array(contour)):
|
|
point_flags |= 64
|
|
if Geometry.is_point_in_polygon(p23, PoolVector2Array(contour)):
|
|
point_flags |= 128
|
|
if Geometry.is_point_in_polygon(p30, PoolVector2Array(contour)):
|
|
point_flags |= 256
|
|
if point_flags == 0:
|
|
grid_areas[y * size_x + x] = 0xffff
|
|
else:
|
|
grid_areas[y * size_x + x] = 0
|
|
grid_walls[y * size_x + x] = point_flags
|
|
func grid2pos(x: int, y: int):
|
|
var px = float(x) * grid_size + grid_rect.position.x - grid_size
|
|
var py = float(y) * grid_size + grid_rect.position.y - grid_size
|
|
return Vector2(px, py)
|
|
func convert_walls():
|
|
for y in range(size_y):
|
|
for x in range(size_x):
|
|
var left = false
|
|
var right = false
|
|
var up = false
|
|
var down = false
|
|
var f = false
|
|
var point_flags = grid_walls[y * size_x + x]
|
|
var px = float(x) * grid_size + grid_rect.position.x - grid_size
|
|
var py = float(y) * grid_size + grid_rect.position.y - grid_size
|
|
var p0 = Vector2(px, py)
|
|
var p1 = Vector2(px + grid_size, py)
|
|
var p2 = Vector2(px + grid_size, py + grid_size)
|
|
var p3 = Vector2(px, py + grid_size)
|
|
match(point_flags):
|
|
0x1ff:
|
|
f = true
|
|
0x01, 0x02, 0x4, 0x08, 0x108, 0x84, 0x8c, 0x88, 0x0, 0x22, 0x23, 0x21, 0x046:
|
|
f = false
|
|
0x109, 0x101, 0x12b, 0x18d, 0x042, 0x06, 0xe4, 0x67, 0x40, 0x64, 0xc6:
|
|
f = false
|
|
0x80, 0xc, 0x1ce, 0x100, 0x1a9, 0x9, 0x161, 0x3, 0x20:
|
|
f = false
|
|
0xd6, 0xde:
|
|
f = true
|
|
up = true
|
|
left = true
|
|
0x19c, 0x1de, 0x1df, 0x1da:
|
|
f = true
|
|
up = true
|
|
0x19a, 0x19b, 0x198:
|
|
f = true
|
|
up = true
|
|
right = true
|
|
0xf4, 0xf6, 0xf7, 0xff, 0xfe, 0x1fe:
|
|
f = true
|
|
left = true
|
|
0x1b3, 0x1bb, 0x1bf, 0x199, 0x1bd, 0x1b9:
|
|
f = true
|
|
right = true
|
|
0x1fd, 0x1fb, 0x1f7, 0x1f6:
|
|
f = true
|
|
0x72, 0x76:
|
|
f = true
|
|
left = true
|
|
down = true
|
|
0x73, 0x152, 0x173, 0x17b, 0x177, 0x172, 0x17f:
|
|
f = true
|
|
down = true
|
|
0x131, 0x133, 0x139:
|
|
f = true
|
|
right = true
|
|
down = true
|
|
0x52, 0x56:
|
|
f = true
|
|
down = true
|
|
up = true
|
|
left = true
|
|
0x96:
|
|
f = true
|
|
left = true
|
|
right = true
|
|
up = true
|
|
0x11a, 0x110:
|
|
f = true
|
|
up = true
|
|
right = true
|
|
down = true
|
|
0x33:
|
|
f = true
|
|
left = true
|
|
right = true
|
|
down = true
|
|
_:
|
|
if point_flags & 0x10 != 0:
|
|
print("%03x" % (point_flags))
|
|
else:
|
|
print("skip %03x" % (point_flags))
|
|
if up:
|
|
if y > 0:
|
|
if grid_walls[(y - 1) * size_x + x] & 16 != 0:
|
|
up = false
|
|
if down:
|
|
if y < size_y - 1:
|
|
if grid_walls[(y + 1) * size_x + x] & 16 != 0:
|
|
down = false
|
|
if left:
|
|
if x > 0:
|
|
if grid_walls[y * size_x + x - 1] & 16 != 0:
|
|
left = false
|
|
if right:
|
|
if x < size_x - 1:
|
|
if grid_walls[y * size_x + x + 1] & 16 != 0:
|
|
right = false
|
|
if !up && f:
|
|
if y > 0:
|
|
if grid_walls[(y - 1) * size_x + x] & 16 == 0:
|
|
up = true
|
|
if !down && f:
|
|
if y < size_y - 1:
|
|
if grid_walls[(y + 1) * size_x + x] & 16 == 0:
|
|
down = true
|
|
if !left && f:
|
|
if x > 0:
|
|
if grid_walls[y * size_x + x - 1] & 16 == 0:
|
|
left = true
|
|
if !right && f:
|
|
if x < size_x - 1:
|
|
if grid_walls[y * size_x + x + 1] & 16 == 0:
|
|
right = true
|
|
point_flags = 0
|
|
if left:
|
|
point_flags |= 1
|
|
if up:
|
|
point_flags |= 2
|
|
if right:
|
|
point_flags |= 4
|
|
if down:
|
|
point_flags |= 8
|
|
if f:
|
|
point_flags |= 16
|
|
grid_walls[y * size_x + x] = point_flags
|
|
if point_flags & 0xf != 0:
|
|
walls_tiles.push_back(y * size_x + x)
|
|
func create_entry_door(rnd):
|
|
var tile = walls_tiles[rnd.randi() % walls_tiles.size()]
|
|
var point_flags = grid_walls[tile]
|
|
var flags = [
|
|
[FLAG_WALL_LEFT, FLAG_ENTRY_LEFT],
|
|
[FLAG_WALL_UP, FLAG_ENTRY_UP],
|
|
[FLAG_WALL_RIGHT, FLAG_ENTRY_RIGHT],
|
|
[FLAG_WALL_DOWN, FLAG_ENTRY_DOWN]
|
|
]
|
|
var rflags = []
|
|
for p in flags:
|
|
if point_flags & p[0] != 0:
|
|
rflags.push_back(p)
|
|
var f = rflags[rnd.randi() % rflags.size()]
|
|
point_flags &= ~f[0]
|
|
point_flags |= f[1]
|
|
grid_walls[tile] = point_flags
|
|
enterance_tile = tile
|
|
func allocate_stairs(area_code: int):
|
|
var stairs_w = small_stairs_w
|
|
var stairs_h = small_stairs_h
|
|
var stairs_grid_w = int((stairs_w + grid_size * 0.5) / grid_size)
|
|
var stairs_grid_h = int((stairs_h + grid_size * 0.5) / grid_size)
|
|
print("size_x ", size_x)
|
|
print("size_y ", size_y)
|
|
print("stairs grid size: ", stairs_grid_w, " ", stairs_grid_h)
|
|
var candidates = []
|
|
var candidates_tile = []
|
|
for i in range(size_y - stairs_grid_h):
|
|
for j in range(size_x - stairs_grid_w):
|
|
var ok = true
|
|
for ii in range(stairs_grid_h):
|
|
for jj in range(stairs_grid_w):
|
|
if grid_walls[(i + ii) * size_x + j + jj] != FLAG_FLOOR:
|
|
ok = false
|
|
break
|
|
if grid_areas[(i + ii) * size_x + j + jj] != 0:
|
|
ok = false
|
|
break
|
|
if ok:
|
|
candidates_tile.push_back(i * size_x + j)
|
|
var pos = grid2pos(j, i) + Vector2(stairs_w, stairs_h) * 0.5
|
|
print("stairs tile: ", i * size_x +j, " pos: ", pos)
|
|
candidates.push_back(pos)
|
|
assert(candidates_tile.size() > 0)
|
|
var pos = 0
|
|
for xpos in range(1, candidates_tile.size(), 1):
|
|
if abs(enterance_tile - candidates_tile[xpos]) < abs(enterance_tile - candidates_tile[pos]):
|
|
pos = xpos
|
|
stairs_tile = candidates_tile[pos]
|
|
stairs_pos = candidates[pos]
|
|
print("result: tile: ", stairs_tile, " pos: ", stairs_pos)
|
|
for i in range(stairs_grid_h):
|
|
for j in range(stairs_grid_w):
|
|
grid_areas[stairs_tile + i * size_x + j] = area_code
|
|
grid_walls[stairs_tile + i * size_x + j] |= FLAG_STAIRS
|
|
func remove_stairs_floor():
|
|
var stairs_w = small_stairs_w
|
|
var stairs_h = small_stairs_h
|
|
var stairs_grid_w = int((stairs_w + grid_size * 0.5) / grid_size)
|
|
var stairs_grid_h = int((stairs_h + grid_size * 0.5) / grid_size)
|
|
for i in range(stairs_grid_h):
|
|
for j in range(stairs_grid_w):
|
|
grid_walls[stairs_tile + i * size_x + j] &= ~FLAG_FLOOR
|
|
|
|
func clear_entry_door():
|
|
if enterance_tile < 0:
|
|
return
|
|
var point_flags = grid_walls[enterance_tile]
|
|
var flags = [
|
|
[FLAG_ENTRY_LEFT, FLAG_WALL_LEFT, FLAG_WINDOW_LEFT],
|
|
[FLAG_ENTRY_UP, FLAG_WALL_UP, FLAG_WINDOW_UP],
|
|
[FLAG_ENTRY_RIGHT, FLAG_WALL_RIGHT, FLAG_WINDOW_RIGHT],
|
|
[FLAG_ENTRY_DOWN, FLAG_WALL_DOWN, FLAG_WINDOW_DOWN]
|
|
]
|
|
var rflags = []
|
|
for p in flags:
|
|
if point_flags & p[0] != 0:
|
|
rflags.push_back(p)
|
|
for f in rflags:
|
|
point_flags &= ~f[0]
|
|
point_flags |= f[1]
|
|
grid_walls[enterance_tile] = point_flags
|
|
enterance_tile = -1
|
|
|
|
func create_windows(rnd, pwindow: float):
|
|
for tile in walls_tiles:
|
|
var point_flags = grid_walls[tile]
|
|
var flags = [
|
|
[1, 512],
|
|
[2, 1024],
|
|
[4, 2048],
|
|
[8, 4096]
|
|
]
|
|
var rflags = []
|
|
for p in flags:
|
|
if point_flags & p[0] != 0:
|
|
if rnd.randf() > 1.0 - pwindow:
|
|
rflags.push_back(p)
|
|
for f in rflags:
|
|
point_flags &= ~f[0]
|
|
point_flags |= f[1]
|
|
grid_walls[tile] = point_flags
|
|
func tile_distance(tile1: int, tile2: int):
|
|
var last_x = tile1 % size_x
|
|
var last_y = int(tile1 / size_x)
|
|
var cur_x = tile2 % size_x
|
|
var cur_y = int(tile2 / size_x)
|
|
var dst = Vector2(cur_x - last_x, cur_y - last_y).length()
|
|
return int(dst)
|
|
func init_areas():
|
|
for t in range(grid_walls.size()):
|
|
if grid_walls[t] & FLAG_FLOOR:
|
|
grid_areas[t] = 0x0
|
|
else:
|
|
grid_areas[t] = 0xffff
|
|
func create_areas(min_d: int = 4, start_code: int = 1) -> int:
|
|
var created_roots = []
|
|
var area_code: int = start_code
|
|
for t in [FLAG_ENTRY_MASK, FLAG_WINDOW_MASK]:
|
|
var p = walls_tiles.duplicate()
|
|
while p.size() > 0:
|
|
var tile = p.pop_front()
|
|
var point_flags = grid_walls[tile]
|
|
if point_flags & FLAG_STAIRS != 0:
|
|
continue
|
|
if (point_flags & t != 0):
|
|
if t == FLAG_ENTRY_MASK:
|
|
print("entry")
|
|
if created_roots.empty():
|
|
grid_areas[tile] = area_code
|
|
if t == FLAG_ENTRY_MASK:
|
|
enterance = area_code
|
|
area_code += 1
|
|
created_roots.push_back(tile)
|
|
else:
|
|
var mdst = 1000000000
|
|
for e in created_roots:
|
|
var dst = tile_distance(e, tile)
|
|
if mdst > dst:
|
|
mdst = dst
|
|
print(mdst)
|
|
if mdst >= min_d:
|
|
grid_areas[tile] = area_code
|
|
if t == FLAG_ENTRY_MASK:
|
|
enterance = area_code
|
|
area_code += 1
|
|
created_roots.push_back(tile)
|
|
assert(enterance != null)
|
|
return area_code
|
|
func grow_areas_left():
|
|
var count = 0
|
|
for tile in range(grid_areas.size()):
|
|
var code = grid_areas[tile]
|
|
var point_flags = grid_walls[tile]
|
|
if code == 0xffff:
|
|
continue
|
|
if (point_flags & FLAG_FLOOR) == 0:
|
|
continue
|
|
var x = tile % size_x
|
|
var y = int(tile / size_x)
|
|
if x > 0:
|
|
var code_left = grid_areas[tile - 1]
|
|
if code_left == 0:
|
|
grid_areas[tile - 1] = code
|
|
count += 1
|
|
return false if count == 0 else true
|
|
func grow_areas_right():
|
|
var count = 0
|
|
for tile in range(grid_areas.size()):
|
|
var code = grid_areas[tile]
|
|
var point_flags = grid_walls[tile]
|
|
if code == 0xffff:
|
|
continue
|
|
if (point_flags & FLAG_FLOOR) == 0:
|
|
continue
|
|
var x = tile % size_x
|
|
var y = int(tile / size_x)
|
|
if x < size_x - 1:
|
|
var code_right = grid_areas[tile + 1]
|
|
if code_right == 0:
|
|
grid_areas[tile + 1] = code
|
|
count += 1
|
|
return false if count == 0 else true
|
|
func grow_areas_up():
|
|
var count = 0
|
|
for tile in range(grid_areas.size()):
|
|
var code = grid_areas[tile]
|
|
var point_flags = grid_walls[tile]
|
|
if code == 0xffff:
|
|
continue
|
|
if (point_flags & FLAG_FLOOR) == 0:
|
|
continue
|
|
var x = tile % size_x
|
|
var y = int(tile / size_x)
|
|
if y > 0:
|
|
var code_up = grid_areas[tile - size_x]
|
|
if code_up == 0:
|
|
grid_areas[tile - size_x] = code
|
|
count += 1
|
|
return false if count == 0 else true
|
|
func grow_areas_down():
|
|
var count = 0
|
|
for tile in range(grid_areas.size()):
|
|
var code = grid_areas[tile]
|
|
var point_flags = grid_walls[tile]
|
|
if code == 0xffff:
|
|
continue
|
|
if (point_flags & FLAG_FLOOR) == 0:
|
|
continue
|
|
var x = tile % size_x
|
|
var y = int(tile / size_x)
|
|
if y < size_y - 1:
|
|
var code_down = grid_areas[tile + size_x]
|
|
if code_down == 0:
|
|
grid_areas[tile + size_x] = code
|
|
count += 1
|
|
print(grid_areas)
|
|
print(grid_walls)
|
|
return false if count == 0 else true
|
|
func add_adj(adj, ncode, ncode2, ntile, ntile2, adj_type):
|
|
print("add_adj ", ncode)
|
|
if adj.has(ncode):
|
|
if adj[ncode].has(ncode2):
|
|
adj[ncode][ncode2].push_back([ntile, ntile2, adj_type])
|
|
else:
|
|
adj[ncode][ncode2] = [[ntile, ntile2, adj_type]]
|
|
else:
|
|
adj[ncode] = {}
|
|
adj[ncode][ncode2] = [[ntile, ntile2, adj_type]]
|
|
|
|
func build_area_adj():
|
|
var adj = {}
|
|
for tile in range(grid_areas.size()):
|
|
var code = grid_areas[tile]
|
|
var point_flags = grid_walls[tile]
|
|
if code == 0xffff:
|
|
continue
|
|
if (point_flags & FLAG_FLOOR) == 0:
|
|
continue
|
|
var x = tile % size_x
|
|
var y = int(tile / size_x)
|
|
print(tile, " ", code, " ", point_flags)
|
|
if x > 0:
|
|
var code_left = grid_areas[tile - 1]
|
|
if code_left != code && code_left != 0xffff:
|
|
add_adj(adj, code, code_left, tile, tile - 1, FLAG_DOOR_LEFT)
|
|
if x < size_x - 1:
|
|
var code_right = grid_areas[tile + 1]
|
|
if code_right != code && code_right != 0xffff:
|
|
add_adj(adj, code, code_right, tile, tile + 1, FLAG_DOOR_RIGHT)
|
|
if y > 0:
|
|
var code_up = grid_areas[tile - size_x]
|
|
if code_up != code && code_up != 0xffff:
|
|
add_adj(adj, code, code_up, tile, tile - size_x, FLAG_DOOR_UP)
|
|
if y < size_y - 1:
|
|
var code_down = grid_areas[tile + size_x]
|
|
if code_down != code && code_down != 0xffff:
|
|
add_adj(adj, code, code_down, tile, tile + size_x, FLAG_DOOR_DOWN)
|
|
assert(!adj.empty())
|
|
return adj
|
|
func build_area_walls():
|
|
for tile in range(grid_areas.size()):
|
|
var code = grid_areas[tile]
|
|
var point_flags = grid_walls[tile]
|
|
var old_point_flags = point_flags
|
|
if code == 0xffff:
|
|
continue
|
|
if (point_flags & FLAG_FLOOR) == 0:
|
|
continue
|
|
var x = tile % size_x
|
|
var y = int(tile / size_x)
|
|
var leftm = point_flags & FLAG_LEFT_MASK
|
|
var rightm = point_flags & FLAG_RIGHT_MASK
|
|
var upm = point_flags & FLAG_UP_MASK
|
|
var downm = point_flags & FLAG_DOWN_MASK
|
|
if (leftm == 0) && x > 0:
|
|
var left_code = grid_areas[tile - 1]
|
|
if code != left_code:
|
|
var left_flags = grid_walls[tile - 1]
|
|
if (point_flags & FLAG_LEFT_MASK == 0) && (left_flags & FLAG_RIGHT_MASK == 0):
|
|
point_flags |= FLAG_WALL_LEFT
|
|
if (rightm == 0) && x < size_x - 1:
|
|
var right_code = grid_areas[tile + 1]
|
|
if code != right_code:
|
|
var right_flags = grid_walls[tile + 1]
|
|
if (point_flags & FLAG_RIGHT_MASK == 0) && (right_flags & FLAG_LEFT_MASK == 0):
|
|
point_flags |= FLAG_WALL_RIGHT
|
|
if upm == 0 && y > 0:
|
|
var up_code = grid_areas[tile - size_x]
|
|
if code != up_code:
|
|
var up_flags = grid_walls[tile - size_x]
|
|
if (point_flags & FLAG_UP_MASK == 0) && (up_flags & FLAG_DOWN_MASK == 0):
|
|
point_flags |= FLAG_WALL_UP
|
|
if downm == 0 && y < size_y - 1:
|
|
var down_code = grid_areas[tile + size_x]
|
|
if code != down_code:
|
|
var down_flags = grid_walls[tile + size_x]
|
|
if (point_flags & FLAG_DOWN_MASK == 0) && (down_flags & FLAG_UP_MASK == 0):
|
|
point_flags |= FLAG_WALL_DOWN
|
|
# if old_point_flags != point_flags:
|
|
# print("point flags %04x" % (old_point_flags), " after %04x" % (point_flags))
|
|
grid_walls[tile] = point_flags
|
|
func make_door_graph():
|
|
var adj = build_area_adj()
|
|
var unreached = []
|
|
var reached = []
|
|
var pairs = {}
|
|
var spanning_tree = {}
|
|
for k in adj.keys():
|
|
for l in adj[k].keys():
|
|
if pairs.has(k):
|
|
if !l in pairs[k]:
|
|
pairs[k].push_back(l)
|
|
else:
|
|
pairs[k] = [l]
|
|
if !k in unreached:
|
|
unreached.push_back(k)
|
|
if !l in unreached:
|
|
unreached.push_back(l)
|
|
var vstart = enterance
|
|
reached.push_back(vstart)
|
|
unreached.erase(vstart)
|
|
while unreached.size() > 0:
|
|
var record = 100000
|
|
var rindex = -1
|
|
var uindex = -1
|
|
for ri in range(reached.size()):
|
|
for ui in range(unreached.size()):
|
|
var rval = reached[ri]
|
|
var dist = 1 if unreached[ui] in pairs[rval] else 10000
|
|
if dist < record:
|
|
record = dist
|
|
rindex = ri
|
|
uindex = ui
|
|
if uindex >= 0:
|
|
var rvalue = reached[rindex]
|
|
var uvalue = unreached[uindex]
|
|
if spanning_tree.has(rvalue):
|
|
if !uvalue in spanning_tree[rvalue]:
|
|
spanning_tree[rvalue].push_back(uvalue)
|
|
else:
|
|
spanning_tree[rvalue] = [uvalue]
|
|
reached.push_back(unreached[uindex])
|
|
unreached.remove(uindex)
|
|
else:
|
|
assert(false)
|
|
pairs = {}
|
|
for k in spanning_tree.keys():
|
|
for l in spanning_tree[k]:
|
|
if pairs.has(k):
|
|
pairs[k].push_back(l)
|
|
else:
|
|
pairs[k] = [l]
|
|
if pairs.has(l):
|
|
pairs[l].push_back(k)
|
|
else:
|
|
pairs[l] = [k]
|
|
var new_adj = {}
|
|
for k in adj.keys():
|
|
for l in adj[k].keys():
|
|
if pairs.has(k) && l in pairs[k]:
|
|
if !new_adj.has(k):
|
|
new_adj[k] = {}
|
|
new_adj[k][l] = adj[k][l]
|
|
print("new adj: ", new_adj)
|
|
return new_adj
|
|
func build_doors():
|
|
var adj = make_door_graph()
|
|
var queue = [enterance]
|
|
var seen = []
|
|
while queue.size() > 0:
|
|
var item = queue.pop_front()
|
|
if item in seen:
|
|
continue
|
|
seen.push_back(item)
|
|
for e in adj[item].keys():
|
|
var data = adj[item][e][0]
|
|
var tile = data[0]
|
|
var point_flags = grid_walls[tile]
|
|
var rtype = data[2]
|
|
match(rtype):
|
|
FLAG_DOOR_LEFT:
|
|
point_flags &= ~FLAG_LEFT_MASK
|
|
FLAG_DOOR_UP:
|
|
point_flags &= ~FLAG_UP_MASK
|
|
FLAG_DOOR_RIGHT:
|
|
point_flags &= ~FLAG_RIGHT_MASK
|
|
FLAG_DOOR_DOWN:
|
|
point_flags &= ~FLAG_DOWN_MASK
|
|
point_flags |= rtype
|
|
grid_walls[tile] = point_flags
|
|
if !e in seen:
|
|
queue.push_back(e)
|
|
|
|
func instance_wall(base: Spatial, what, p0, p1):
|
|
var obj = what.instance()
|
|
base.add_child(obj)
|
|
var v = p1 - p0
|
|
var xform = Transform().rotated(Vector3(0, 1, 0), -v.angle())
|
|
var p = p0 + v * 0.5
|
|
xform.origin = Vector3(p.x, 0, p.y)
|
|
obj.transform = xform
|
|
func display_walls(base: Spatial, objdata: Dictionary):
|
|
for y in range(size_y):
|
|
for x in range(size_x):
|
|
var point_flags = grid_walls[y * size_x + x]
|
|
var px = float(x) * grid_size + grid_rect.position.x - grid_size
|
|
var py = float(y) * grid_size + grid_rect.position.y - grid_size
|
|
var p0 = Vector2(px, py)
|
|
var p1 = Vector2(px + grid_size, py)
|
|
var p2 = Vector2(px + grid_size, py + grid_size)
|
|
var p3 = Vector2(px, py + grid_size)
|
|
var obje
|
|
var objects = {
|
|
FLAG_WALL_MASK: objdata.wall,
|
|
FLAG_ENTRY_MASK: objdata.entry,
|
|
FLAG_WINDOW_MASK: objdata.window,
|
|
FLAG_DOOR_MASK: objdata.door
|
|
}
|
|
for k in objects.keys():
|
|
if point_flags & k != 0:
|
|
obje = objects[k]
|
|
if point_flags & (k & FLAG_LEFT_MASK) != 0:
|
|
instance_wall(base, obje, p3, p0)
|
|
if point_flags & (k & FLAG_UP_MASK) != 0:
|
|
instance_wall(base, obje, p0, p1)
|
|
if point_flags & (k & FLAG_RIGHT_MASK) != 0:
|
|
instance_wall(base, obje, p1, p2)
|
|
if point_flags & (k & FLAG_DOWN_MASK) != 0:
|
|
instance_wall(base, obje, p2, p3)
|
|
|
|
if point_flags & FLAG_FLOOR != 0:
|
|
var fd = objdata.floor.instance()
|
|
base.add_child(fd)
|
|
var xform = Transform()
|
|
var p = p0
|
|
xform.origin = Vector3(p.x, 0, p.y)
|
|
fd.transform = xform
|
|
assert(stairs_pos != null)
|
|
if stairs_pos:
|
|
var fd = objdata.stairs.instance()
|
|
base.add_child(fd)
|
|
var xform = Transform()
|
|
var p = stairs_pos
|
|
xform.origin = Vector3(p.x, 0, p.y)
|
|
fd.transform = xform
|
|
func debug_contour():
|
|
$debug.begin(Mesh.PRIMITIVE_LINES)
|
|
for k in range(contour.size()):
|
|
var p1 = contour[k]
|
|
var p2 = contour[(k + 1) % contour.size()]
|
|
$debug.add_vertex(Vector3(p1.x, 3.0, p1.y))
|
|
$debug.add_vertex(Vector3(p2.x, 3.0, p2.y))
|
|
$debug.end()
|
|
#onready var building_floor = Floor.new()
|
|
|
|
var cur_pos: = Vector2()
|
|
func debug_walls(fl):
|
|
$debug.begin(Mesh.PRIMITIVE_LINES)
|
|
for y in range(fl.size_y):
|
|
for x in range(fl.size_x):
|
|
var gpos = fl.grid2pos(x, y)
|
|
var px = gpos.x
|
|
var py = gpos.y
|
|
var p0 = Vector2(px, py)
|
|
var p1 = Vector2(px + fl.grid_size, py)
|
|
var p2 = Vector2(px + fl.grid_size, py + fl.grid_size)
|
|
var p3 = Vector2(px, py + fl.grid_size)
|
|
$debug.add_vertex(Vector3(p0.x, 0.1, p0.y))
|
|
$debug.add_vertex(Vector3(p1.x, 0.1, p1.y))
|
|
$debug.add_vertex(Vector3(p1.x, 0.1, p1.y))
|
|
$debug.add_vertex(Vector3(p2.x, 0.1, p2.y))
|
|
$debug.add_vertex(Vector3(p2.x, 0.1, p2.y))
|
|
$debug.add_vertex(Vector3(p3.x, 0.1, p3.y))
|
|
$debug.add_vertex(Vector3(p3.x, 0.1, p3.y))
|
|
$debug.add_vertex(Vector3(p0.x, 0.1, p0.y))
|
|
$debug.end()
|
|
|
|
func _ready():
|
|
rnd = RandomNumberGenerator.new()
|
|
rnd.seed = OS.get_unix_time()
|
|
|
|
var state = 0
|
|
var objd = {
|
|
"wall": wall,
|
|
"window": window,
|
|
"door": door,
|
|
"floor": fl,
|
|
"entry": entry,
|
|
"stairs": stairs
|
|
}
|
|
var floors = []
|
|
var nfloors = 40
|
|
var floor_bases = []
|
|
var area_code = 1
|
|
func _process(delta):
|
|
match(state):
|
|
0:
|
|
for k in range(nfloors):
|
|
floors.push_back(Floor.new())
|
|
var b = Spatial.new()
|
|
add_child(b)
|
|
b.translation.y = 3.0 * float(k)
|
|
floor_bases.push_back(b)
|
|
floors[0].init_grid(contour)
|
|
floors[0].init_walls(contour)
|
|
floors[0].convert_walls()
|
|
floors[0].create_entry_door(rnd)
|
|
floors[0].create_windows(rnd, 0.6)
|
|
floors[0].init_areas()
|
|
floors[0].allocate_stairs(area_code)
|
|
area_code += 1
|
|
for k in range(0, nfloors, 1):
|
|
if k > 0:
|
|
floors[k] = floors[0].copy()
|
|
floors[k].clear_entry_door()
|
|
area_code = floors[k].create_areas(4, area_code)
|
|
state = 1
|
|
1:
|
|
var b1 = false
|
|
var b2 = false
|
|
var b3 = false
|
|
var b4 = false
|
|
for k in range(nfloors):
|
|
var tb1 = floors[k].grow_areas_left()
|
|
if tb1:
|
|
b1 = true
|
|
var tb2 = floors[k].grow_areas_up()
|
|
if tb2:
|
|
b2 = true
|
|
var tb3 = floors[k].grow_areas_right()
|
|
if tb3:
|
|
b3 = true
|
|
var tb4 = floors[k].grow_areas_down()
|
|
if tb4:
|
|
b4 = true
|
|
if !b1 && !b2 && !b3 && !b4:
|
|
state = 2
|
|
2:
|
|
for k in range(nfloors):
|
|
floors[k].build_doors()
|
|
floors[k].build_area_walls()
|
|
floors[k].remove_stairs_floor()
|
|
floors[k].display_walls(floor_bases[k], objd)
|
|
state = 3
|