using System;
using System.Collections;
using System.Collections.Generic;
using Unity.Mathematics;
using UnityEditor;
using UnityEngine;
using UnityEngine.Tilemaps;
using UnityEngine.UIElements;
public class MapGenerator : MonoBehaviour
{
public Tilemap tileMap;
public TileBase waterPrefab;
public TileBase grassPrefab;
public TileBase sandPrefab;
public TileBase forestPrefab;
public TileBase mountainPrefab;
public GameObject player;
public int width;
public int height;
public int[,] map;
float[,] noiseMap;
float noiseValue;
[Range(0, 100)]
public int randomFillPercentage;
public float seed;
public bool useRandomSeed;
public float scale;
private void Start()
{
GenerateMap();
}
void Update() {
if (Input.GetMouseButtonDown(0)) {
GenerateMap();
}
}
void GenerateMap() {
map = new int[height, width];
proceduralGen();
for (int i = 0; i < 5; i++) {
SmoothMap();
}
AddTerrainTypes();
DrawTiles();
}
void proceduralGen() {
noiseMap = new float[height, width];
// Generating random float value to use as seed
float randomFloat = UnityEngine.Random.Range(0, 10000000f);
// Checking if useRandomSeed Boolean is true in the inspector
if (useRandomSeed) {
seed = randomFloat;
}
System.Random pseudoRandom = new System.Random((int)seed);
// Offset to add to Perlin noise
float offsetX = randomFloat + 100f;
float offsetY = randomFloat + 200f;
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
float xCoord = (float)x / width * scale + offsetX;
float yCoord = (float)y / height * scale + offsetY;
noiseMap[x, y] = Mathf.PerlinNoise(xCoord, yCoord);
// Add randomization to the Perlin noise
float randomValue = (float)pseudoRandom.NextDouble() * 2f - 1f;
noiseValue += randomValue * 0.1f;
// Edge of the map is water
if (x == 0 || x == width - 1 || y == 0 || y == height - 1) {
map[x, y] = 0;
} else {
map[x, y] = (pseudoRandom.Next(0, 100) < randomFillPercentage) ? 0 : 1;
}
}
}
}
void AddTerrainTypes()
{
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
if (map[x, y] == 0)
{
int terrainType;
noiseValue = noiseMap[x, y];
if (noiseValue < 0.1f)
{
terrainType = 2; // Mountains
}
else if (noiseValue < 0.4f)
{
terrainType = 3; // Forests
}
else
{
terrainType = 4; // savanna
}
// Add random variations to terrain types
switch (terrainType)
{
case 2: // Mountains
map[x, y] = 2;
break;
case 3: // Forests
map[x, y] = 3;
break;
case 4: // Savanna
map[x, y] = 4;
break;
default: // Water
map[x, y] = 1;
break;
}
}
}
}
}
void DrawTiles()
{
if (map != null)
{
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
Vector3Int pos = new Vector3Int(-width / 2 + x, -height / 2 + y, 0);
tileMap.SetTile(pos, map[x, y] == 1 ? grassPrefab : waterPrefab);
switch (map[x, y])
{
case 2:
tileMap.SetTile(pos, mountainPrefab);
break;
case 3:
tileMap.SetTile(pos, forestPrefab);
break;
case 4:
tileMap.SetTile(pos, sandPrefab);
break;
default:
tileMap.SetTile(pos, waterPrefab);
break;
}
}
}
}
}
void SmoothMap() {
for (int x = 0; x < width; x++){
for (int y = 0; y < height; y++){
int neighbourWallTile = GetSurroundingWallCount(x, y);
if (neighbourWallTile > 4) {
map[x, y] = 1;
} else if (neighbourWallTile < 4) {
map[x, y] = 0;
}
}
}
}
int GetSurroundingWallCount(int gridX, int gridY)
{
int wallCount = 0;
for (int neighbourX = gridX - 1; neighbourX <= gridX + 1; neighbourX++) {
for (int neighbourY = gridY - 1; neighbourY <= gridY + 1; neighbourY++) {
if (neighbourX >= 0 && neighbourX < width && neighbourY >= 0 && neighbourY < height) {
if (neighbourX != gridX || neighbourY != gridY) {
wallCount += map[neighbourX, neighbourY];
}
} else {
wallCount++;
}
}
}
return wallCount;
}
}