Files
kicking-high/proto3/godot/city/building.gd
2020-04-19 04:20:13 +03:00

460 lines
14 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")
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
var contour = [
Vector2(-10, -10), Vector2(-8, -10), Vector2(-8, -8), Vector2(-6, -8), Vector2(-6, -10),
Vector2(10, -10), Vector2(10, -8), Vector2(8, -8), Vector2(8, -6), Vector2(10, -6),
Vector2(10, 10), Vector2(8, 10), Vector2(8, 8), Vector2(6, 8), Vector2(6, 10),
Vector2(-10, 10), Vector2(-10, 8), Vector2(-8, 8), Vector2(-8, 6), Vector2(-10, 6), Vector2(-15, 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():
$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()
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)
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():
$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
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)
$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))
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() > 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 p = walls_tiles.duplicate()
var area_code: int = 1
while p.size() > 0:
var tile = p.pop_front()
print("tile ", tile)
var point_flags = grid_walls[tile]
for t in [FLAG_ENTRY_MASK, FLAG_WINDOW_MASK]:
if (point_flags & t != 0):
if created_roots.empty():
print("p")
grid_areas[tile] = area_code
area_code += 1
created_roots.push_back(tile)
else:
print("pp")
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
area_code += 1
created_roots.push_back(tile)
func grow_areas_left():
for k in range(grid_areas.size()):
pass
print(grid_areas)
print(grid_walls)
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
print("left ", leftm)
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
print("right ", rightm)
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
print("up ", upm)
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
print("down ", downm)
if old_point_flags != point_flags:
print("point flags %04x" % (old_point_flags), " after %04x" % (point_flags))
grid_walls[tile] = point_flags
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
func _process(delta):
match(state):
0:
init_grid()
init_walls()
convert_walls()
create_entry_door()
create_windows(0.0)
create_areas(4)
build_area_walls()
display_walls()
# place_flats()
# grow_flats()
# draw_grid()
# draw_walls()
# print(grid)
# for k in range(150):
# build_corridor()
state = 1