292 lines
9.0 KiB
GDScript
292 lines
9.0 KiB
GDScript
extends Node
|
|
|
|
export var mapSize = 128
|
|
var playerSpawn = Vector2()
|
|
var PLAYER_OBJ = preload("res://Nodes/Player.tscn")
|
|
|
|
const PATH_SIZE = 2
|
|
|
|
func _ready():
|
|
|
|
MusicPlayer.stop()
|
|
MusicPlayer.stream = load("res://Music/DOS-88/Checking Manifest.ogg")
|
|
MusicPlayer.volume_db = 0
|
|
MusicPlayer.play()
|
|
|
|
|
|
UpdateProgress("Loading generation libraries...")
|
|
randomize()
|
|
|
|
func UpdateProgress(message):
|
|
print(message)
|
|
$LoadingScreen.get_child(2).text = message
|
|
|
|
func setTile(x,y, value):
|
|
var tileValue = -1
|
|
if(value == "block"):
|
|
tileValue = 0
|
|
elif(value == "safe_block"):
|
|
tileValue = 2
|
|
elif(value == "player"):
|
|
playerSpawn = Vector2(x,y)
|
|
elif(value == "ladder"):
|
|
tileValue = 1
|
|
elif(value == "light"):
|
|
createObject(x,y, "res://Nodes/Light.tscn")
|
|
elif(value == "coin"):
|
|
createObject(x,y, "res://Nodes/Pickup.tscn")
|
|
elif(value == "enemy"):
|
|
createObject(x,y, "res://Nodes/Enemies/Basic.tscn")
|
|
elif(value == "exit"):
|
|
createObject(x,y, "res://Nodes/Exit.tscn")
|
|
$TileMap.set_cell(x, y, tileValue)
|
|
|
|
func createObject(x,y,objectPath):
|
|
var obj = load(objectPath).instance()
|
|
add_child(obj)
|
|
var pos = $TileMap.map_to_world(Vector2(x,y))
|
|
obj.position = Vector2(pos.x + 8, pos.y + 8)
|
|
|
|
func generateStructure(x,y, structure):
|
|
var symbolDictionary = {
|
|
"x" : "safe_block",
|
|
"p" : "player",
|
|
"l" : "ladder",
|
|
"c" : "coin",
|
|
"e" : "enemy",
|
|
"#" : "exit",
|
|
"?": "light"
|
|
}
|
|
var largestX = 0
|
|
var largestY = structure.size()
|
|
for structY in range(0, structure.size()):
|
|
for structX in range(0, structure[structY].size()):
|
|
if structX > largestX:
|
|
largestX = structX
|
|
var symbol = structure[structY][structX]
|
|
setTile(x + structX, y + structY, symbolDictionary.get(symbol))
|
|
var rect = Rect2(Vector2(x-1,y-1),Vector2(largestX+1,largestY+1))
|
|
return rect
|
|
|
|
|
|
func fillMap(value="block"):
|
|
for x in range(0, mapSize):
|
|
for y in range(0, mapSize):
|
|
setTile(x,y,value)
|
|
|
|
func spawnPlayer():
|
|
var tempVector = Vector2(playerSpawn.x * $TileMap.cell_size.x, playerSpawn.y * $TileMap.cell_size.y)
|
|
var player = PLAYER_OBJ.instance()
|
|
add_child(player)
|
|
player.position = tempVector
|
|
player.get_child(0).current = true
|
|
var welcome = load("res://Nodes/PlayerGreetings.tscn").instance()
|
|
add_child(welcome)
|
|
welcome.position = Vector2(tempVector.x - 16, tempVector.y - 16)
|
|
$TileMap.set_cell(playerSpawn.x, playerSpawn.y, -1)
|
|
$LoadingScreen.hideSelf()
|
|
|
|
var rooms = Array()
|
|
func createConnections():
|
|
var graph = AStar.new()
|
|
var point_id = 0
|
|
for x in range(mapSize):
|
|
for y in range(mapSize):
|
|
if $TileMap.get_cell(x,y) == 0:
|
|
graph.add_point(point_id, Vector3(x,y,0))
|
|
|
|
if x > 0 && $TileMap.get_cell(x - 1, y) == 0:
|
|
var left_point = graph.get_closest_point(Vector3(x - 1, y, 0))
|
|
graph.connect_points(point_id, left_point)
|
|
|
|
if y > 0 && $TileMap.get_cell(x, y - 1) == 0:
|
|
var above_point = graph.get_closest_point(Vector3(x, y - 1, 0))
|
|
graph.connect_points(point_id, above_point)
|
|
|
|
point_id += 1
|
|
|
|
var room_graph = AStar.new()
|
|
point_id = 0
|
|
for room in rooms:
|
|
var room_center = room.position + room.size / 2
|
|
room_graph.add_point(point_id, Vector3(room_center.x, room_center.y, 0))
|
|
point_id += 1
|
|
|
|
while !is_everything_connected(room_graph):
|
|
add_random_connection(graph, room_graph)
|
|
|
|
func is_everything_connected(graph):
|
|
var points = graph.get_points()
|
|
var start = points.pop_back()
|
|
for point in points:
|
|
var path = graph.get_point_path(start, point)
|
|
if !path:
|
|
return false
|
|
return true
|
|
|
|
func add_random_connection(stone_graph, room_graph):
|
|
|
|
var start_room_id = get_least_connected_point(room_graph)
|
|
var end_room_id = get_nearest_unconnected_point(room_graph, start_room_id)
|
|
|
|
var start_position = pick_random_door_location(rooms[start_room_id])
|
|
var end_position = pick_random_door_location(rooms[end_room_id])
|
|
|
|
var closet_start_point = stone_graph.get_closest_point(start_position)
|
|
var closet_end_point = stone_graph.get_closest_point(end_position)
|
|
|
|
var path = stone_graph.get_point_path(closet_start_point, closet_end_point)
|
|
|
|
for pos in path:
|
|
for i in range(PATH_SIZE):
|
|
if($TileMap.get_cell(pos.x+i, pos.y+i) == 0):
|
|
setTile(pos.x+i, pos.y+i, "-1")
|
|
if($TileMap.get_cell(pos.x+i, pos.y-i) == 0):
|
|
setTile(pos.x+i, pos.y-i, "-1")
|
|
if($TileMap.get_cell(pos.x-i, pos.y+i) == 0):
|
|
setTile(pos.x-i, pos.y+i, "-1")
|
|
if($TileMap.get_cell(pos.x-i, pos.y-i) == 0):
|
|
setTile(pos.x-i, pos.y-i, "-1")
|
|
if $TileMap.get_cell(pos.x, pos.y - 2) == -1:
|
|
if $TileMap.get_cell(pos.x, pos.y - 1) == -1:
|
|
if $TileMap.get_cell(pos.x, pos.y) == -1:
|
|
if !isNextToCell(pos.x, pos.y, 1):
|
|
setTile(pos.x, pos.y, "ladder")
|
|
#elif(rand_range(0,1) > 0.666):
|
|
# setTile(pos.x, pos.y, "light")
|
|
|
|
elif $TileMap.get_cell(pos.x, pos.y + 2) == -1:
|
|
if $TileMap.get_cell(pos.x, pos.y + 1) == -1:
|
|
if $TileMap.get_cell(pos.x, pos.y) == -1:
|
|
if !isNextToCell(pos.x, pos.y, 1):
|
|
setTile(pos.x, pos.y, "ladder")
|
|
|
|
room_graph.connect_points(start_room_id, end_room_id)
|
|
|
|
func isNextToCell(x, y, tileId):
|
|
return $TileMap.get_cell(x-1, y) == tileId or $TileMap.get_cell(x+1, y) == tileId or $TileMap.get_cell(x, y-1) == tileId or $TileMap.get_cell(x, y+1) == tileId
|
|
|
|
func get_least_connected_point(graph):
|
|
var point_ids = graph.get_points()
|
|
|
|
var least
|
|
var tied_for_least
|
|
|
|
for point in point_ids:
|
|
var count = graph.get_point_connections(point).size()
|
|
if !least or count < least:
|
|
least = count
|
|
tied_for_least = [point]
|
|
elif count == least:
|
|
tied_for_least.append(point)
|
|
|
|
return tied_for_least[randi() % tied_for_least.size()]
|
|
|
|
func get_nearest_unconnected_point(graph, target_point):
|
|
var target_position = graph.get_point_position(target_point)
|
|
var point_ids = graph.get_points()
|
|
|
|
var nearest
|
|
var tied_for_nearest = []
|
|
|
|
for point in point_ids:
|
|
if point == target_point:
|
|
continue
|
|
|
|
var path = graph.get_point_path(point, target_point)
|
|
if path:
|
|
continue
|
|
|
|
var dist = (graph.get_point_position(point) - target_position).length()
|
|
if !nearest || dist < nearest:
|
|
nearest = dist
|
|
tied_for_nearest = [point]
|
|
elif dist == nearest:
|
|
tied_for_nearest.append(point)
|
|
return tied_for_nearest[randi() % tied_for_nearest.size()]
|
|
|
|
func pick_random_door_location(room):
|
|
var options = []
|
|
|
|
for x in range(room.position.x + 1, room.end.x - 2):
|
|
if $TileMap.get_cell(x, room.position.y) == -1:
|
|
options.append(Vector3(x, room.position.y, 0))
|
|
if $TileMap.get_cell(x, room.end.y) == -1:
|
|
options.append(Vector3(x, room.end.y - 1, 0))
|
|
|
|
for y in range(room.position.y + 1, room.end.y - 2):
|
|
if $TileMap.get_cell(room.position.x, y) == -1:
|
|
options.append(Vector3(room.position.x, y, 0))
|
|
if $TileMap.get_cell(room.end.x - 1, y) == -1:
|
|
options.append(Vector3(room.end.x - 1, y, 0))
|
|
|
|
|
|
return options[randi() % options.size()]
|
|
|
|
func defaultGenerator(padding = 16):
|
|
|
|
UpdateProgress("Running default generator with map size " + String(mapSize) + "x" + String(mapSize))
|
|
fillMap()
|
|
|
|
|
|
var randomStructures = [
|
|
[
|
|
['x','x','x','x','x','x','x','x','x','x','x','x'],
|
|
[' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '],
|
|
[' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '],
|
|
[' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '],
|
|
['x','x',' ',' ','x',' ',' ','x',' ',' ','x','x'],
|
|
['x',' ',' ',' ','x',' ',' ','x',' ',' ',' ','x'],
|
|
['x',' ',' ',' ','x',' ','e','x',' ','e',' ','x'],
|
|
['x','x','x','x','x','x','x','x','x','x','x','x']
|
|
],
|
|
[
|
|
['x','x','x','x','x','x','x','x','x','x','x','x'],
|
|
[' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '],
|
|
[' ',' ',' ',' ','x','l',' ','x',' ',' ',' ',' '],
|
|
[' ','e',' ',' ','x',' ',' ','x',' ',' ',' ',' '],
|
|
['x','x','x','x','x','l',' ','x','x','x','x','x'],
|
|
['x',' ',' ',' ','x',' ',' ','x',' ',' ',' ','x'],
|
|
['x','c',' ',' ',' ',' ','e',' ',' ',' ','c','x'],
|
|
['x','x','x','x','x','x','x','x','x','x','x','x']
|
|
],
|
|
]
|
|
|
|
|
|
for i in range(rand_range(mapSize/32, mapSize/8)):
|
|
rooms.append(generateStructure(rand_range(padding, mapSize - padding),rand_range(padding, mapSize - padding), randomStructures[rand_range(0, randomStructures.size())]))
|
|
|
|
|
|
#Create spawn point
|
|
UpdateProgress("Creating client connection port...")
|
|
var spawnStructure = [
|
|
['x','x','x','x','x','x','x','x','x'],
|
|
['x',' ','?',' ',' ',' ','?',' ','x'],
|
|
['x',' ',' ',' ',' ',' ',' ',' ',' '],
|
|
['x',' ','p',' ',' ',' ',' ',' ',' '],
|
|
['x','x','x','x','x','x','x','x','x']]
|
|
rooms.append(generateStructure(rand_range(padding, mapSize/3),rand_range(padding, mapSize/3), spawnStructure))
|
|
|
|
var exitStructure = [
|
|
['x','x','x','x','x','x','x'],
|
|
['x',' ',' ',' ',' ',' ','x'],
|
|
['x',' ',' ',' ',' ',' ','x'],
|
|
[' ',' ',' ','#',' ',' ',' '],
|
|
[' ',' ','x','x','x',' ',' '],
|
|
[' ',' ','x','x','x',' ',' ']]
|
|
|
|
rooms.append(generateStructure(rand_range(padding, mapSize - padding),rand_range(padding, mapSize - padding*3), exitStructure))
|
|
|
|
createConnections()
|
|
|
|
$TileMap.set_cell(playerSpawn.x, playerSpawn.y, 0)
|
|
|
|
|
|
UpdateProgress("Removing all possible escapes...")
|
|
for x in range(0, mapSize):
|
|
for y in range(0, mapSize):
|
|
if x < padding or y < padding or x >= mapSize - padding or y >= mapSize - padding:
|
|
setTile(x,y,"block")
|
|
|
|
spawnPlayer()
|
|
|