From 72452dcb4c8511ba5b139a272c64da20e6c25149 Mon Sep 17 00:00:00 2001 From: Segey Lapin Date: Mon, 20 Apr 2020 01:31:57 +0300 Subject: [PATCH] Proper door layout; started multiple floors --- proto3/godot/city/building.gd | 1160 ++++++++++++++++++--------------- 1 file changed, 623 insertions(+), 537 deletions(-) diff --git a/proto3/godot/city/building.gd b/proto3/godot/city/building.gd index 4098b4d..386cd81 100644 --- a/proto3/godot/city/building.gd +++ b/proto3/godot/city/building.gd @@ -11,31 +11,6 @@ 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") -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_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) # Called when the node enters the scene tree for the first time. var rnd: RandomNumberGenerator @@ -45,27 +20,600 @@ var contour = [ Vector2(20, 20), Vector2(8, 20), Vector2(8, 8), Vector2(6, 8), Vector2(6, 20), Vector2(-20, 20), Vector2(-20, 8), Vector2(-8, 8), Vector2(-8, 6), Vector2(-20, 6), Vector2(-25, 2), ] -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 enterance var spaces = [ "entry", "window", "corridoor" ] -var walls_tiles = [] #var adj = { # "entry": ["hall"], # "hall": ["hall1", "kitchen", "toilet1", "bathroom1", "hall2"], #} -func init_grid(): +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_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 + 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 = [ + [1, 32], + [2, 64], + [4, 128], + [8, 256] + ] + 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 + 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 create_areas(min_d: int = 4): + var created_roots = [] + for t in range(grid_walls.size()): + if grid_walls[t] & FLAG_FLOOR: + grid_areas[t] = 0x0 + else: + grid_areas[t] = 0xffff + var area_code: int = 1 + 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 & 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) + 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 +func debug_contour(): $debug.begin(Mesh.PRIMITIVE_LINES) for k in range(contour.size()): var p1 = contour[k] @@ -73,74 +621,20 @@ func init_grid(): $debug.add_vertex(Vector3(p1.x, 3.0, p1.y)) $debug.add_vertex(Vector3(p2.x, 3.0, p2.y)) $debug.end() - 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 -# for e in adj.keys(): -# if !e in spaces: -# spaces.push_back(e) +#onready var building_floor = Floor.new() var cur_pos: = Vector2() -func init_walls(): - 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 convert_walls(): +func debug_walls(fl): $debug.begin(Mesh.PRIMITIVE_LINES) - 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 + 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 + grid_size, py) - var p2 = Vector2(px + grid_size, py + grid_size) - var p3 = Vector2(px, py + grid_size) + 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)) @@ -149,456 +643,48 @@ func convert_walls(): $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)) - 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) $debug.end() -func create_entry_door(): - var tile = walls_tiles[rnd.randi() % walls_tiles.size()] - var point_flags = grid_walls[tile] - var flags = [ - [1, 32], - [2, 64], - [4, 128], - [8, 256] - ] - 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 -func create_windows(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 create_areas(min_d: int = 4): - var created_roots = [] - for t in range(grid_walls.size()): - if grid_walls[t] & FLAG_FLOOR: - grid_areas[t] = 0x0 - else: - grid_areas[t] = 0xffff - var area_code: int = 1 - 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 & 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) -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 build_doors(): - var adj = build_area_adj() - print("adj: ", adj) - 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(what, p0, p1): - var obj = what.instance() - 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(): - 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: wall, - FLAG_ENTRY_MASK: entry, - FLAG_WINDOW_MASK: window, - FLAG_DOOR_MASK: door - } - for k in objects.keys(): - if point_flags & k != 0: - obje = objects[k] - if point_flags & (k & FLAG_LEFT_MASK) != 0: - instance_wall(obje, p3, p0) - if point_flags & (k & FLAG_UP_MASK) != 0: - instance_wall(obje, p0, p1) - if point_flags & (k & FLAG_RIGHT_MASK) != 0: - instance_wall(obje, p1, p2) - if point_flags & (k & FLAG_DOWN_MASK) != 0: - instance_wall(obje, p2, p3) - - if point_flags & FLAG_FLOOR != 0: - var fd = fl.instance() - add_child(fd) - var xform = Transform() - var p = p0 - xform.origin = Vector3(p.x, 0, p.y) - fd.transform = xform - 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 +} +var floors = [] +var nfloors = 3 +var floor_bases = [] func _process(delta): match(state): 0: - init_grid() - init_walls() - convert_walls() - create_entry_door() - create_windows(0.6) - create_areas(4) + 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].create_areas(4) state = 1 1: - var b1 = grow_areas_left() - var b2 = grow_areas_up() - var b3 = grow_areas_right() - var b4 = grow_areas_down() + var b1 = floors[0].grow_areas_left() + var b2 = floors[0].grow_areas_up() + var b3 = floors[0].grow_areas_right() + var b4 = floors[0].grow_areas_down() if !b1 && !b2 && !b3 && !b4: state = 2 2: - build_doors() - build_area_walls() - display_walls() -# place_flats() -# grow_flats() -# draw_grid() -# draw_walls() -# print(grid) -# for k in range(150): -# build_corridor() + floors[0].build_doors() + floors[0].build_area_walls() + floors[0].display_walls(floor_bases[0], objd) state = 3