Files
SpaceBots/.svn/pristine/50/5023af43a0ccb21ebcce9a55d732811dd478184a.svn-base
2026-01-21 23:51:53 +01:00

192 lines
7.4 KiB
Plaintext

extends Node3D
class_name LevelGenerator
var levelGrid: Array[Array]
@export var gridSize: int = 250
var spawnableRooms: Array[RoomData]
var biomes: Array[Biome]
var rng := RandomNumberGenerator.new()
func _ready() -> void:
initGrid()
var spaceshipRoomList := RoomListSpaceship.new() # Have something choose the map in this part later
spawnableRooms = spaceshipRoomList.rooms
var temp: Array[DoorPosition]
# Generate the level
temp = spawnRoom(spawnableRooms[0],Vector2i(30,30),0,true)
for x in temp:
spawnRoomAtDoor(spawnableRooms,x)
#spawnRoomAtDoor(spawnableRooms[0],temp[x])
printLevelGrid()
#Utility
func initGrid() -> void:
for x in gridSize:
var newRow: Array
levelGrid.push_back(newRow)
for y in gridSize:
var newCell := GridCell.new()
levelGrid[x].push_back(newCell)
func addGridCells(cell1: GridCell,cell2: GridCell) -> GridCell:
var returnCell: GridCell = GridCell.new()
returnCell.spaceTaken = cell1.spaceTaken or cell2.spaceTaken
returnCell.door = cell2.door
returnCell.doorOrientation = cell2.doorOrientation
returnCell.biome = cell1.biome
return returnCell
func addArrays2D(array1: Array[Array], array2: Array[Array], arr2pos: Vector2i = Vector2i(0,0)) -> void:
if array1.size() <= (arr2pos.x) + array2.size(): return
if array1[arr2pos.y].size() <= (arr2pos.y) + array2[0].size(): return
for x in array2.size():
for y in array2[x].size():
array1[x+arr2pos.x][y+arr2pos.y] = addGridCells(array1[x+arr2pos.x][y+arr2pos.y],array2[x][y])
func checkOverlapArrays2D(array1: Array[Array], array2: Array[Array], arr2pos: Vector2i = Vector2i(0,0)) -> bool:
if array1.size() <= (arr2pos.x) + array2.size(): return true
if array1[arr2pos.y].size() <= (arr2pos.y) + array2[0].size(): return true
for x in array2.size():
for y in array2[x].size():
if array1[x+arr2pos.x][y+arr2pos.y].spaceTaken and array2[x][y].spaceTaken: return true
return false
func rotateArray2D(array: Array[Array], numberOfRotationsBy90Degrees: int) -> void:
var size: int = array.size()
var layerCount: int = size/2
for x in numberOfRotationsBy90Degrees%4:
for layer in layerCount:
var first: int = layer
var last: int = size - first - 1
for element in range(first, last):
var offset = element - first
var top = array[first][element]
var right = array[element][last]
var bot = array[last][last-offset]
var left = array[last-offset][first]
array[element][last] = top
array[last][last-offset] = right
array[last-offset][first] = bot
array[first][element] = left
func getDoorPosition(cell: GridCell, GridCellPosition: Vector2i) -> DoorPosition:
if !cell.door:
print("Tried to get door at cell that isnt a door")
return null
var returnDoorPosition := DoorPosition.new()
returnDoorPosition.pos = GridCellPosition
returnDoorPosition.orientation = cell.doorOrientation
return returnDoorPosition
func addObject(AddedObject:PackedScene, Parent: Node3D, Position: Vector3, Rotation: Vector3= Vector3(0,0,0)):
if !AddedObject:
print("tried to add object but packed scene is null")
return
var obj = AddedObject.instantiate()
Parent.add_child(obj)
obj.position = Position
obj.rotation = Rotation
return obj
#Spawning Rooms
func rotateRoomData(roomData: RoomData, numberOfRotationsBy90Degrees: int) -> void:
rotateArray2D(roomData.roomGrid,numberOfRotationsBy90Degrees)
roomData.rotations = wrapi(roomData.rotations + numberOfRotationsBy90Degrees,0,4)
for door in roomData.doorPositions:
door.rotatePosRight(roomData.roomGrid.size(),numberOfRotationsBy90Degrees)
func spawnRoom(roomDataInput: RoomData,pos: Vector2i,numberOfRotationsBy90Degrees: int = 0, centered: bool = false) -> Array[DoorPosition]: #Pos corresponds to the upper left corner of the room immage
var roomData: RoomData = roomDataInput.duplicateRoom()
var roomScene: PackedScene = load(roomData.roomSceneRef)
rotateRoomData(roomData,numberOfRotationsBy90Degrees)
var roomGrid := roomData.roomGrid
var doorPositions: Array[DoorPosition] = roomData.doorPositions
if centered:
pos = Vector2i(pos.x-(roomGrid.size()/2),pos.y-(roomGrid[0].size()/2))
addArrays2D(levelGrid,roomGrid,pos)
addObject(roomScene,self,Vector3(pos.x+(roomGrid.size()/2),0,pos.y+(roomGrid[0].size()/2)),Vector3(0,(roomData.rotations%4)*PI/2,0))
for door in doorPositions:
door.pos = pos + door.pos
return doorPositions
func getDoorFromRoom(roomData: RoomData,index: int) -> DoorPosition:
return roomData.doorPositions[index % roomData.doorPositions.size()]
func putRoomAtDoor(roomData: RoomData, door: DoorPosition,spawnDoorIndex: int) -> Array: ##Return array contains roomData, spawn Pos in that order
#Init Values:
var spawnDoor: DoorPosition = getDoorFromRoom(roomData,spawnDoorIndex) #Which door from the spawned room connects to the exiting room
var doorOrientationDifference : int = wrapi(spawnDoor.orientation - door.orientation,0,4) #Difference in orinet. between spawned and existing room
var numberOfRoomRotations: int = 0 #How many rotations are needed to make spawned rooms spawn door face the existing door
var spawnPos: Vector2i
var doorOffset: Vector2i #Offset by 1 space so the doors are next to eachother and not inside eachoter
#Find number of rotations and then rotate the room
if !doorOrientationDifference == 2:
if doorOrientationDifference == 1:
numberOfRoomRotations = 3
if doorOrientationDifference == 0:
numberOfRoomRotations = 2
if doorOrientationDifference == 3:
numberOfRoomRotations = 1
rotateRoomData(roomData,numberOfRoomRotations)
#Get new values for spawnDoor and set door offset
spawnDoor = getDoorFromRoom(roomData,spawnDoorIndex)
match spawnDoor.orientation:
0: doorOffset = Vector2i(0,-1)
1: doorOffset = Vector2i(1,0)
2: doorOffset = Vector2i(0,1)
3: doorOffset = Vector2i(-1,0)
#Set spawn pos and return values
spawnPos = door.pos - spawnDoor.pos + doorOffset
var returnArray: Array = [roomData,spawnPos]
return returnArray
func spawnRoomAtDoor(roomDataInput: Array[RoomData], door: DoorPosition) -> void:
var roomData: RoomData = null
var spawnDoorIndex: int = -1
#Choose the room to use
var rooms: Array[RoomData] = roomDataInput.duplicate()
rooms.shuffle()
for room in rooms:
#Check if room has allready been found
if roomData and spawnDoorIndex != -1:
break
#Randomise door checking order
var doorIndices: Array[int]
for x in room.doorPositions.size():
doorIndices.push_back(x)
doorIndices.shuffle()
#Check if doorIndex fits and assign roomData and spawnDoorIndex if it does
for doorIndex in doorIndices:
if checkIfRoomFits(room,door,doorIndex):
roomData = room.duplicateRoom()
spawnDoorIndex = doorIndex
break
#Check if a room has been found
if !roomData or spawnDoorIndex == -1: return
#Get Spawn Info and spawn room
var spawnInfo: Array = putRoomAtDoor(roomData,door,spawnDoorIndex)
spawnRoom(spawnInfo[0],spawnInfo[1])
func checkIfRoomFits(roomDataInput: RoomData,door: DoorPosition,spawnDoorIndex: int) -> bool:
var roomData: RoomData = roomDataInput.duplicateRoom()
var spawnInfo: Array = putRoomAtDoor(roomData,door,spawnDoorIndex)
if checkOverlapArrays2D(levelGrid,spawnInfo[0].roomGrid,spawnInfo[1]):
return false
else:
return true
#Debug Functions
func printLevelGrid() -> void:
for x in levelGrid.size():
for y in levelGrid[x].size():
if levelGrid[x][y].spaceTaken:
debugCubeAtPos(Vector2(x,y))
func debugCubeAtPos(pos: Vector2):
var debugCube: PackedScene = preload("res://test/debugCube.tscn")
addObject(debugCube,self,Vector3(pos.x+0.5,0,pos.y+0.5))