152 lines
5.7 KiB
C#
152 lines
5.7 KiB
C#
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace Assets.Scripts {
|
|
public class World : MonoBehaviour {
|
|
public int seed;
|
|
|
|
public Transform player;
|
|
public Vector3 spawn;
|
|
public BiomeAttributes biome;
|
|
|
|
public Material material;
|
|
public BlockType[] blockTypes;
|
|
|
|
private readonly Chunk[,] _chunks = new Chunk[VoxelData.WorldSizeInChunks, VoxelData.WorldSizeInChunks];
|
|
private readonly List<ChunkCoord> _activeChunks = new List<ChunkCoord>();
|
|
|
|
private ChunkCoord _playersLastChunk;
|
|
|
|
private void Start() {
|
|
Random.InitState(seed);
|
|
|
|
spawn = new Vector3(VoxelData.WorldSizeInBlocks / 2f,
|
|
VoxelData.ChunkHeight / 2f,
|
|
VoxelData.WorldSizeInBlocks / 2f);
|
|
|
|
GenerateWorld();
|
|
_playersLastChunk = GetChunkCoord(player.position);
|
|
}
|
|
|
|
private void Update() {
|
|
ChunkCoord playerChunk = GetChunkCoord(player.position);
|
|
|
|
if (!playerChunk.Equals(_playersLastChunk)) {
|
|
_playersLastChunk = playerChunk;
|
|
CheckViewDistance();
|
|
}
|
|
}
|
|
|
|
private void GenerateWorld() {
|
|
for (int x = VoxelData.WorldSizeInChunks / 2 - VoxelData.ViewDistance; x < VoxelData.WorldSizeInChunks / 2 + VoxelData.ViewDistance; x++) {
|
|
for (int z = VoxelData.WorldSizeInChunks / 2 - VoxelData.ViewDistance; z < VoxelData.WorldSizeInChunks / 2 + VoxelData.ViewDistance; z++) {
|
|
CreateNewChunk(x, z);
|
|
}
|
|
}
|
|
|
|
player.position = spawn;
|
|
}
|
|
|
|
public ChunkCoord GetChunkCoord(Vector3 absPosition) {
|
|
int x = Mathf.FloorToInt(absPosition.x / VoxelData.ChunkWidth);
|
|
int z = Mathf.FloorToInt(absPosition.z / VoxelData.ChunkWidth);
|
|
return new ChunkCoord(x, z);
|
|
}
|
|
|
|
private void CheckViewDistance() {
|
|
ChunkCoord coord = GetChunkCoord(player.position);
|
|
ChunkCoord[] previouslyActiveChunks = _activeChunks.ToArray();
|
|
_activeChunks.Clear();
|
|
|
|
for (int x = coord.x - VoxelData.ViewDistance; x < coord.x + VoxelData.ViewDistance; x++) {
|
|
for (int z = coord.z - VoxelData.ViewDistance; z < coord.z + VoxelData.ViewDistance; z++) {
|
|
if (!IsChunkInWorld(new ChunkCoord(x, z))) continue;
|
|
Chunk chunk = _chunks[x, z];
|
|
|
|
if (chunk == null)
|
|
CreateNewChunk(x, z);
|
|
else if (!chunk.IsActive) {
|
|
chunk.IsActive = true;
|
|
}
|
|
|
|
_activeChunks.Add(new ChunkCoord(x, z));
|
|
}
|
|
}
|
|
|
|
foreach (ChunkCoord chunk in previouslyActiveChunks) {
|
|
if (!_activeChunks.Contains(chunk))
|
|
_chunks[chunk.x, chunk.z].IsActive = false;
|
|
}
|
|
}
|
|
|
|
private void CreateNewChunk(int x, int z) {
|
|
_chunks[x, z] = new Chunk(new ChunkCoord(x, z), this);
|
|
_activeChunks.Add(new ChunkCoord(x, z));
|
|
}
|
|
|
|
public bool IsChunkInWorld(ChunkCoord coord) {
|
|
return (coord.x > 0 && coord.x < VoxelData.WorldSizeInChunks - 1 &&
|
|
coord.z > 0 && coord.z < VoxelData.WorldSizeInChunks - 1);
|
|
}
|
|
|
|
public bool IsBlockInWorld(Vector3 pos) {
|
|
return (pos.x >= 0 && pos.x < VoxelData.WorldSizeInBlocks &&
|
|
pos.y >= 0 && pos.y < VoxelData.ChunkHeight &&
|
|
pos.z >= 0 && pos.z < VoxelData.WorldSizeInBlocks);
|
|
}
|
|
|
|
public byte GenerateBlock(Vector3 position) {
|
|
Vector3Int pos = new Vector3Int(Mathf.FloorToInt(position.x),
|
|
Mathf.FloorToInt(position.y),
|
|
Mathf.FloorToInt(position.z));
|
|
|
|
if (!IsBlockInWorld(position)) return 0;
|
|
if (pos.y == 0) return 1;
|
|
|
|
//Generate Block based on 2D Perlin Noise
|
|
int terrainHeight = Mathf.FloorToInt(Noise.Get2DNoise(new Vector2(pos.x, pos.z), 0, biome.terrainScale) * biome.terrainHeight + biome.solidGroundHeight);
|
|
int blockValue = 0;
|
|
|
|
if (pos.y < terrainHeight) blockValue = 2;
|
|
if (pos.y < terrainHeight && pos.y > terrainHeight - 4) blockValue = 5;
|
|
if (pos.y == terrainHeight) blockValue = 3;
|
|
|
|
if (blockValue == 2) {
|
|
foreach (var lode in biome.lodes) {
|
|
if ((pos.y > lode.minHeight && pos.y < lode.maxHeight) && Noise.Get3DNoise(pos, lode.offset, lode.scale, lode.threshold))
|
|
blockValue = lode.blockID;
|
|
}
|
|
}
|
|
|
|
return (byte)blockValue;
|
|
}
|
|
}
|
|
|
|
[System.Serializable]
|
|
public class BlockType {
|
|
public string blockName;
|
|
public bool isSolid;
|
|
|
|
[Header("Texture Values")]
|
|
public int backFaceTexture;
|
|
public int frontFaceTexture;
|
|
public int topFaceTexture;
|
|
public int bottomFaceTexture;
|
|
public int leftFaceTexture;
|
|
public int rightFaceTexture;
|
|
|
|
//Back - Front - Top - Bottom - Left - Right
|
|
public int GetTextureID(int faceIndex) {
|
|
switch (faceIndex) {
|
|
case 0: return backFaceTexture;
|
|
case 1: return frontFaceTexture;
|
|
case 2: return topFaceTexture;
|
|
case 3: return bottomFaceTexture;
|
|
case 4: return leftFaceTexture;
|
|
case 5: return rightFaceTexture;
|
|
|
|
default: return 0;
|
|
}
|
|
}
|
|
}
|
|
} |