mirror of
https://gitlab.com/MaddoScientisto/cirnogodot.git
synced 2026-06-01 11:15:33 +00:00
162 lines
No EOL
4.8 KiB
C#
162 lines
No EOL
4.8 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Cirno.Scripts.Enums;
|
|
using Cirno.Scripts.Resources.Roguelite;
|
|
using Godot;
|
|
using Godot.Collections;
|
|
|
|
namespace Cirno.Scripts.Controllers;
|
|
|
|
public partial class RogueliteRoomManager : Node2D
|
|
{
|
|
[Export] public Array<RogueliteRoomResource> Rooms { get; set; }
|
|
|
|
[Export] public Node2D SceneContainer { get; set; }
|
|
|
|
private Godot.Collections.Dictionary<Vector2I, RogueliteRoomResource> _grid = new();
|
|
[Export] public int DungeonWidth = 10;
|
|
[Export] public int DungeonHeight = 10;
|
|
[Export] public int MaxRooms = 12;
|
|
//[Export] public int Seed = -1;
|
|
|
|
[Export] public Vector2I TileSize { get; set; } = new Vector2I(16, 16);
|
|
[Export] public Vector2I RoomSizeInTiles { get; set; } = new Vector2I(20, 10);
|
|
|
|
public override void _Ready()
|
|
{
|
|
// Spawn first room
|
|
|
|
}
|
|
|
|
public void InitSpawning()
|
|
{
|
|
SpawnRoomsBinaryTree();
|
|
}
|
|
|
|
private void SpawnRoomsGrid()
|
|
{
|
|
//var firstRoom = Rooms.FirstOrDefault();
|
|
|
|
var origin = Vector2.Zero;
|
|
var tileSize = new Vector2(16, 16);
|
|
|
|
for (int i = 0; i < 10; i++)
|
|
{
|
|
for (int j = 0; j < 10; j++)
|
|
{
|
|
var roomIndex = GD.RandRange(0, Rooms.Count - 1);
|
|
var room = Rooms[roomIndex];
|
|
//SpawnRoom(room, origin + (room.Size * new Vector2(i, j) * tileSize));
|
|
}
|
|
}
|
|
|
|
//CallDeferred(MethodName.RebakeNavigationDeferred);
|
|
}
|
|
|
|
private void SpawnRoomsBinaryTree()
|
|
{
|
|
var directions = new List<Vector2I>
|
|
{
|
|
new Vector2I(0, -1), // North
|
|
new Vector2I(0, 1), // South
|
|
new Vector2I(1, 0), // East
|
|
new Vector2I(-1, 0), // West
|
|
};
|
|
|
|
var origin = Vector2I.Zero;
|
|
var tileSize = new Vector2(16, 16);
|
|
var gridRoomSizeInTiles = new Vector2(20, 10);
|
|
|
|
var starterRooms = Rooms.Where(x => x.Type is RoomType.Starter).ToList();
|
|
var regularRooms = Rooms.Where(x => x.Type == RoomType.Regular).ToList();
|
|
|
|
var starterRoom = starterRooms[GD.RandRange(0, starterRooms.Count - 1)];
|
|
|
|
var spawnedStartRoom = SpawnRoom(starterRoom, origin);
|
|
MarkRoom(origin, starterRoom.Size, starterRoom);
|
|
|
|
Queue<(Vector2I Position, RogueliteRoomResource Room)> queue = new();
|
|
queue.Enqueue((origin, starterRoom));
|
|
|
|
int spawnedRoomCount = 1;
|
|
|
|
while (spawnedRoomCount < MaxRooms && queue.Count > 0)
|
|
{
|
|
var (currentPos, currentRoom) = queue.Dequeue();
|
|
|
|
foreach (var dir in directions)
|
|
{
|
|
var offsetPos = currentPos + dir;
|
|
|
|
// Avoid placing rooms in occupied space
|
|
if (_grid.ContainsKey(offsetPos)) continue;
|
|
|
|
var nextRoom = regularRooms[GD.RandRange(0, regularRooms.Count - 1)];
|
|
var roomSize = nextRoom.Size;
|
|
|
|
// Multi-tile room placement validation
|
|
if (!CanPlaceRoom(offsetPos, roomSize)) continue;
|
|
|
|
SpawnRoom(nextRoom, offsetPos);
|
|
MarkRoom(offsetPos, roomSize, nextRoom);
|
|
queue.Enqueue((offsetPos, nextRoom));
|
|
spawnedRoomCount++;
|
|
|
|
if (spawnedRoomCount >= MaxRooms)
|
|
break;
|
|
}
|
|
}
|
|
|
|
//SpawnSpecialRooms(rng);
|
|
|
|
|
|
}
|
|
|
|
private void RebakeNavigationDeferred()
|
|
{
|
|
GameManager.Instance.RebakeNavigation();
|
|
}
|
|
|
|
private RogueliteRoom SpawnRoom(RogueliteRoomResource room, Vector2I gridPos)
|
|
{
|
|
var position = gridPos * TileSize * RoomSizeInTiles;
|
|
|
|
var roomScene = GD.Load<PackedScene>(room.ScenePath);
|
|
var spawnedScene = this.CreateChild<RogueliteRoom>(roomScene, position);
|
|
|
|
// for reference
|
|
//SpawnRoom(room, origin + (room.Size * new Vector2(i, j) * tileSize));
|
|
|
|
return spawnedScene.Spawn(CheckConnection);
|
|
}
|
|
|
|
private bool CheckConnection(Vector2I pos)
|
|
{
|
|
return _grid.ContainsKey(pos); // <- this is your dungeon grid dictionary
|
|
}
|
|
|
|
private bool CanPlaceRoom(Vector2I origin, Vector2I size)
|
|
{
|
|
for (int x = 0; x < size.X; x++)
|
|
{
|
|
for (int y = 0; y < size.Y; y++)
|
|
{
|
|
var pos = origin + new Vector2I(x, y);
|
|
if (_grid.ContainsKey(pos)) return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private void MarkRoom(Vector2I origin, Vector2I size, RogueliteRoomResource room)
|
|
{
|
|
for (int x = 0; x < size.X; x++)
|
|
{
|
|
for (int y = 0; y < size.Y; y++)
|
|
{
|
|
var pos = origin + new Vector2I(x, y);
|
|
_grid[pos] = room;
|
|
}
|
|
}
|
|
}
|
|
} |