Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using Godot;
- using System;
- using System.Collections.Generic;
- public partial class PlayerPlacement : Node2D
- {
- public int[,] currentMap; // int[,] map will be passed by reference from GameManager when connecting signal
- int biggestAreaSize;
- List<Vector2I> finalAreas;
- public TileMap levelTilemap;
- void calculatePlayField(int currentRow, int currentCol, ref bool[,] visited)
- {
- List<Vector2I> potentialAreas = new List<Vector2I>();
- Stack<Vector2I> dfsStack = new Stack<Vector2I>();
- dfsStack.Push(new Vector2I(currentRow,currentCol));
- int sizeOfArea=0;
- Vector2I currTop;
- while(dfsStack.Count!=0)
- {
- currTop=dfsStack.Pop();
- potentialAreas.Add(currTop);
- visited[currTop.X,currTop.Y]=true;
- if(currTop.X-1>=0)
- if(currentMap[currTop.X-1,currTop.Y]==1 && !visited[currTop.X-1,currTop.Y])
- dfsStack.Push(new Vector2I(currTop.X-1, currTop.Y));
- if(currTop.X+1<currentMap.GetLength(0))
- if(currentMap[currTop.X+1,currTop.Y]==1 && !visited[currTop.X+1,currTop.Y])
- dfsStack.Push(new Vector2I(currTop.X+1, currTop.Y));
- if(currTop.Y-1>=0)
- if(currentMap[currTop.X,currTop.Y-1]==1 && !visited[currTop.X,currTop.Y-1])
- dfsStack.Push(new Vector2I(currTop.X, currTop.Y-1));
- if(currTop.Y+1<currentMap.GetLength(1))
- if(currentMap[currTop.X,currTop.Y+1]==1 && !visited[currTop.X,currTop.Y+1])
- dfsStack.Push(new Vector2I(currTop.X, currTop.Y+1));
- sizeOfArea+=1;
- }
- if(potentialAreas.Count > biggestAreaSize)
- {
- biggestAreaSize = potentialAreas.Count;
- finalAreas = potentialAreas;
- }
- }
- void bfs(int currentRow, int currentCol, ref bool[,] visited)
- {
- if (currentRow < 0 || currentRow >= currentMap.GetLength(0) || currentCol < 0 || currentCol >= currentMap.GetLength(1))
- return;
- if (visited[currentRow, currentCol])
- return;
- visited[currentRow,currentCol] = true;
- if(currentMap[currentRow, currentCol]!=0)
- calculatePlayField(currentRow, currentCol, ref visited);
- if(currentRow-1>=0)
- bfs(currentRow-1, currentCol, ref visited);
- if(currentRow+1<currentMap.GetLength(0))
- bfs(currentRow+1, currentCol, ref visited);
- if(currentCol-1>=0)
- bfs(currentRow, currentCol-1, ref visited);
- if(currentCol+1<currentMap.GetLength(1))
- bfs(currentRow, currentCol+1, ref visited);
- }
- void identifyBiggestEmptyArea() // same map will be used as parameter. will return areas within biggest area
- {
- if (currentMap == null)
- {
- GD.PrintErr("PlayerPlacement: currentMap is null! Assign it before calling identifyBiggestEmptyArea().");
- return;
- }
- bool[,] visited = new bool[currentMap.GetLength(0),currentMap.GetLength(1)]; // all initialized to 0
- biggestAreaSize = 0;
- finalAreas = new List<Vector2I>();
- bfs(0,0,ref visited);
- }
- void playerPositioning()
- {
- Random rand = new Random();
- Vector2 tileWorldPos;
- Node2D playerNode = GetTree().Root.FindChild("Player", true, false) as Node2D;
- foreach(Vector2I pos in finalAreas)
- {
- if
- (
- currentMap[pos.X+0,pos.Y+1]==0 && // ground should be right below
- currentMap[pos.X+(-1),pos.Y+1]==0 && // checking for surrounding blocks of air
- currentMap[pos.X+0,pos.Y-1]==1 &&
- currentMap[pos.X+1,pos.Y+1]==0 &&
- currentMap[pos.X+(-1),pos.Y+0]==1 &&
- currentMap[pos.X+1,pos.Y+0]==1 &&
- currentMap[pos.X+(-1),pos.Y+(-1)]==1 &&
- currentMap[pos.X+(1),pos.Y+(-1)]==1
- )
- {
- // So that positioning stays a little random,
- // I am going to have a random number decide the chance that I will place the player here.
- if(rand.Next(0, 100)>=50)
- {
- GD.Print("Found a suitable place!");
- tileWorldPos = levelTilemap.MapToLocal(pos);
- tileWorldPos=levelTilemap.ToGlobal(tileWorldPos);
- playerNode.GlobalPosition = tileWorldPos;
- // Uncomment for debugging
- // levelTilemap.SetCell(
- // 0,
- // pos,
- // 0,
- // new Vector2I(7, 5), 0
- // ); // Red marker for where player is placed.
- break;
- }
- }
- }
- }
- void placePlayer() // int[,] map will be passed by reference from GameManager when connecting signal
- {
- if (levelTilemap == null)
- {
- GD.PushError("PlayerPlacement.cs: levelTilemap is null! Cannot place player. Make sure SetTileMap() is called with a valid TileMap before placePlayer().");
- return;
- }
- if (currentMap == null)
- {
- GD.PushError("PlayerPlacement.cs: currentMap is null! Cannot place player. Make sure SetBitmap() is called with a valid map before placePlayer().");
- return;
- }
- GD.Print("Identify biggest area for setting up level within map...");
- identifyBiggestEmptyArea();
- GD.Print("Placing player...");
- playerPositioning();
- }
- public void SetTileMap(TileMap tilemap)
- {
- if(tilemap == null)
- GD.PushError("PlayerPlacement.cs: SetTileMap called with null tilemap!");
- GD.Print("SetTilemap from PlayerPlacement called!");
- levelTilemap = tilemap;
- }
- public void SetBitmap(int[,] map)
- {
- if(map == null)
- GD.PushError("PlayerPlacement.cs: SetBitmap called with null map!");
- GD.Print("SetBitmap from PlayerPlacement called!");
- currentMap = map;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement