Exemplo n.º 1
0
        public Chunk(Game1 game, Vector3 offset, Block[] blocks)
        {
            _game = game;
            _offset = offset;

            _boundingBox = new BoundingBox(
                new Vector3(_offset.X * WIDTH, _offset.Y * HEIGHT, _offset.Z * DEPTH),
                new Vector3((_offset.X + 1) * WIDTH, (_offset.Y + 1) * HEIGHT, (_offset.Z + 1) * DEPTH));

            _solidVertexList = new List<VertexPositionNormalTexture>();
            _solidIndexList = new List<int>();
            _solidIndicesDict = new Dictionary<int,List<int>>();
            _solidBlocksOffsetsList = new List<int>();

            _liquidVertexList = new List<VertexPositionNormalTexture>();
            _liquidIndexList = new List<int>();
            _liquidIndicesDict = new Dictionary<int, List<int>>();
            _liquidBlocksOffsetsList = new List<int>();

            _blocks = blocks;
            _blockAccessor = new BlockAccessor(_game.Map);

            _effect = new BasicEffect(_game.GraphicsDevice);
        }
Exemplo n.º 2
0
        private int BuildVertices(Block block, float x, float y, float z)
        {
            if (block.Type == BlockType.None)
                return 0;

            x += 0.5f;
            y += 0.5f;
            z += 0.5f;

            bool isLiquid = BlockHelper.IsLiquid(block);

            float scaleX = 0.5f, scaleY = 0.5f, scaleZ = 0.5f;

            var faces = new List<VertexPositionNormalTexture[]>();

            // Front
            if (DrawFace(block, _blockAccessor.MoveTo((int)x, (int)y, (int)z).Backward.Block))
            {
                var face = new VertexPositionNormalTexture[4];
                face[0].Position = new Vector3(1 * scaleX + x, 1 * scaleY + y, -1 * scaleZ + z);
                face[1].Position = new Vector3(1 * scaleX + x, -1 * scaleY + y, -1 * scaleZ + z);
                face[2].Position = new Vector3(-1 * scaleX + x, -1 * scaleY + y, -1 * scaleZ + z);
                face[3].Position = new Vector3(-1 * scaleX + x, 1 * scaleY + y, -1 * scaleZ + z);
                faces.Add(face);
            }

            //Back
            if (DrawFace(block, _blockAccessor.MoveTo((int)x, (int)y, (int)z).Forward.Block))
            {
                var face = new VertexPositionNormalTexture[4];
                face[0].Position = new Vector3(1 * scaleX + x, 1 * scaleY + y, 1 * scaleZ + z);
                face[1].Position = new Vector3(-1 * scaleX + x, 1 * scaleY + y, 1 * scaleZ + z);
                face[2].Position = new Vector3(-1 * scaleX + x, -1 * scaleY + y, 1 * scaleZ + z);
                face[3].Position = new Vector3(1 * scaleX + x, -1 * scaleY + y, 1 * scaleZ + z);
                faces.Add(face);
            }

            //Right
            if (DrawFace(block, _blockAccessor.MoveTo((int)x, (int)y, (int)z).Right.Block))
            {
                var face = new VertexPositionNormalTexture[4];
                face[0].Position = new Vector3(1 * scaleX + x, 1 * scaleY + y, -1 * scaleZ + z);
                face[1].Position = new Vector3(1 * scaleX + x, 1 * scaleY + y, 1 * scaleZ + z);
                face[2].Position = new Vector3(1 * scaleX + x, -1 * scaleY + y, 1 * scaleZ + z);
                face[3].Position = new Vector3(1 * scaleX + x, -1 * scaleY + y, -1 * scaleZ + z);

                faces.Add(face);
            }

            //Bottom
            if (DrawFace(block, _blockAccessor.MoveTo((int)x, (int)y, (int)z).Down.Block))
            {
                var face = new VertexPositionNormalTexture[4];
                face[0].Position = new Vector3(1 * scaleX + x, -1 * scaleY + y, -1 * scaleZ + z);
                face[1].Position = new Vector3(1 * scaleX + x, -1 * scaleY + y, 1 * scaleZ + z);
                face[2].Position = new Vector3(-1 * scaleX + x, -1 * scaleY + y, 1 * scaleZ + z);
                face[3].Position = new Vector3(-1 * scaleX + x, -1 * scaleY + y, -1 * scaleZ + z);

                faces.Add(face);
            }

            //Left
            if (DrawFace(block, _blockAccessor.MoveTo((int)x, (int)y, (int)z).Left.Block))
            {
                var face = new VertexPositionNormalTexture[4];
                face[0].Position = new Vector3(-1 * scaleX + x, -1 * scaleY + y, -1 * scaleZ + z);
                face[1].Position = new Vector3(-1 * scaleX + x, -1 * scaleY + y, 1 * scaleZ + z);
                face[2].Position = new Vector3(-1 * scaleX + x, 1 * scaleY + y, 1 * scaleZ + z);
                face[3].Position = new Vector3(-1 * scaleX + x, 1 * scaleY + y, -1 * scaleZ + z);

                faces.Add(face);
            }

            //Top
            if (DrawFace(block, _blockAccessor.MoveTo((int)x, (int)y, (int)z).Up.Block))
            {
                var face = new VertexPositionNormalTexture[4];
                face[0].Position = new Vector3(1 * scaleX + x, 1 * scaleY + y, 1 * scaleZ + z);
                face[1].Position = new Vector3(1 * scaleX + x, 1 * scaleY + y, -1 * scaleZ + z);
                face[2].Position = new Vector3(-1 * scaleX + x, 1 * scaleY + y, -1 * scaleZ + z);
                face[3].Position = new Vector3(-1 * scaleX + x, 1 * scaleY + y, 1 * scaleZ + z);

                faces.Add(face);
            }

            if (faces.Count > 0)
            {
                for (var i = 0; i < faces.Count; i++)
                {
                    var face = faces.ElementAt(i);

                    float[] uv = BlockHelper.GetUVMapping(block);

                    float left = uv[0] + 0.1f;
                    float right = uv[0] + uv[2] * 0.90f;
                    float top = uv[1] + 0.1f;
                    float bottom = uv[1] + uv[3] * 0.90f;

                    face[0].TextureCoordinate = new Vector2(right, top);
                    face[1].TextureCoordinate = new Vector2(right, bottom);
                    face[2].TextureCoordinate = new Vector2(left, bottom);
                    face[3].TextureCoordinate = new Vector2(left, top);
                }

                var indices = new int[faces.Count * 6];

                int j = 0;
                for (int i = 0; i < faces.Count; i++)
                {
                    var offset = i * 4;
                    indices[j++] = 0 + offset;
                    indices[j++] = 3 + offset;
                    indices[j++] = 2 + offset;

                    indices[j++] = 0 + offset;
                    indices[j++] = 2 + offset;
                    indices[j++] = 1 + offset;
                }

                for (int i = 0; i < indices.Length / 3; i++)
                {
                    var face = faces.ElementAt((int)(float)i / 2);

                    // i = 0 => face[3] - face[0], face[0] - face[2]
                    // i = 1 => face[2] - face[0], face[0] - face[1]
                    Vector3 firstvec = face[indices[i * 3 + 1] % 4].Position - face[indices[i * 3] % 4].Position;
                    Vector3 secondvec = face[indices[i * 3] % 4].Position - face[indices[i * 3 + 2] % 4].Position;
                    Vector3 normal = Vector3.Cross(firstvec, secondvec);
                    normal.Normalize();
                    face[indices[i * 3] % 4].Normal += normal;
                    face[indices[i * 3 + 1] % 4].Normal += normal;
                    face[indices[i * 3 + 2] % 4].Normal += normal;

                    face[indices[i * 3] % 4].Normal.Normalize();
                    face[indices[i * 3 + 1] % 4].Normal.Normalize();
                    face[indices[i * 3 + 2] % 4].Normal.Normalize();
                }

                var currentVertexOffset = isLiquid ? _liquidVertexList.Count : _solidVertexList.Count;

                var indicesDict = isLiquid ? _liquidIndicesDict : _solidIndicesDict;
                var vertexList = isLiquid ? _liquidVertexList : _solidVertexList;
                var indexList = isLiquid ? _liquidIndexList : _solidIndexList;
                var blocksOffsetsList = isLiquid ? _liquidBlocksOffsetsList : _solidBlocksOffsetsList;

                foreach (var face in faces)
                    foreach (var vertex in face)
                        vertexList.Add(vertex);

                var blockOffset = GetBlockOffset((int)x, (int)y, (int)z);
                indicesDict.Add(blockOffset, new List<int>());
                blocksOffsetsList.Add(blockOffset);

                foreach (var index in indices)
                {
                    indexList.Add(index + currentVertexOffset);
                    indicesDict[blockOffset].Add(index + currentVertexOffset);
                }
            }

            return faces.Count * 4;
        }
Exemplo n.º 3
0
 private bool DrawFace(Block block1, Block block2)
 {
     if (BlockHelper.IsTransparent(block1) && BlockHelper.IsSolid(block2))
         return true;
     if (BlockHelper.IsSolid(block1) && BlockHelper.IsTransparent(block2))
         return true;
     else if (BlockHelper.IsSolid(block1) && BlockHelper.IsSolid(block2))
         return false;
     else if (BlockHelper.IsTransparent(block1) && BlockHelper.IsTransparent(block2) && !BlockHelper.IsNone(block1) && !BlockHelper.IsNone(block2))
         return false;
     else return true;
 }
Exemplo n.º 4
0
        private Chunk Generate3DNoiseChunk(Vector3 chunkOffset)
        {
            int noiseWidth = Map.NUM_CHUNKS_WIDTH * Chunk.WIDTH;
            int noiseDepth = Map.NUM_CHUNKS_DEPTH * Chunk.DEPTH;
            int noiseHeight = Map.NUM_CHUNKS_HEIGHT * Chunk.HEIGHT;

            Block[] blocks = new Block[Chunk.WIDTH * Chunk.HEIGHT * Chunk.DEPTH];

            for (int x = 0; x < Chunk.WIDTH; x++)
                for (int z = 0; z < Chunk.DEPTH; z++)
                {
                    int offset = x * Chunk.DEPTH * Chunk.HEIGHT + z * Chunk.HEIGHT;

                    for (int y = 0; y < Chunk.HEIGHT; y++)
                    {
                        int mapX = (int)chunkOffset.X * Chunk.WIDTH + x;
                        int mapY = (int)chunkOffset.Y * Chunk.HEIGHT + y;
                        int mapZ = (int)chunkOffset.Z * Chunk.DEPTH + z;

                        float octave1 = (SimplexNoise.noise(2.0f * mapX * 1 / noiseWidth, 2.0f * mapY * 1 / noiseHeight, 2.0f * mapZ * 1 / noiseDepth) + 1) / 2 * 0.7f;
                        float octave2 = (SimplexNoise.noise(4.0f * mapX * 1 / noiseWidth, 4.0f * mapY * 1 / noiseHeight, 4.0f * mapZ * 1 / noiseDepth) + 1) / 2 * 0.2f;
                        float octave3 = (SimplexNoise.noise(8.0f * mapX * 1 / noiseWidth, 8.0f * mapY * 1 / noiseHeight, 8.0f * mapZ * 1 / noiseDepth) + 1) / 2 * 0.1f;

                        float rnd = octave1 + octave2 + octave3;

                        if (rnd < 0.5)
                            blocks[offset + y] = new Block(BlockType.Rock);
                        else if(y < Map.WATER_HEIGHT * NUM_CHUNKS_HEIGHT * Chunk.HEIGHT)
                            blocks[offset + y] = new Block(BlockType.Water);
                        else
                            blocks[offset + y] = new Block(BlockType.None);
                    }

                }

            return new Chunk(_game, chunkOffset, blocks);
        }
Exemplo n.º 5
0
        public void SetBlockAt(int mapX, int mapY, int mapZ, Block block)
        {
            var offset = GetBlockOffset(mapX, mapY, mapZ);

            var oldBlock = _blocks[offset];
            _blocks[offset] = block;

            if (BlockHelper.IsNone(oldBlock) && !BlockHelper.IsNone(block))
            {
                // Replace none block with plain block => We must create new block vertices and destroy neighbours ones
            }
            else if (!BlockHelper.IsNone(oldBlock) && BlockHelper.IsNone(block))
            {
                // Replace plain block with none block => We must destroy vertices and build neighbours ones

                NumVertices -= DestroyBlockVertices(mapX, mapY, mapZ);
                var directions = _blockAccessor.AllDirections;

                foreach (var dir in directions)
                {
                    if (!_blockAccessor.MoveTo(mapX, mapY, mapZ).MoveTo(dir).IsNone)
                        NumVertices += RebuildBlockVertices(_blockAccessor.X, _blockAccessor.Y, _blockAccessor.Z);
                }
            }
            else if(block.Type != oldBlock.Type)
            {
                // Block type changed, need redraw
            }

            UpdateBuffers();
        }
Exemplo n.º 6
0
 public BlockAccessor(Map map)
 {
     _map = map;
     _outOfMapBlock = new Block(BlockType.None);
 }
Exemplo n.º 7
0
        private Chunk Generate2DNoiseChunk(Vector3 chunkOffset)
        {
            PerlinNoise perlinNoise = new PerlinNoise(_game.Map.Seed);

            int noiseWidth = Map.NUM_CHUNKS_WIDTH * Chunk.WIDTH;
            int noiseDepth = Map.NUM_CHUNKS_DEPTH * Chunk.DEPTH;

            int mapHeight = Map.NUM_CHUNKS_HEIGHT * Chunk.HEIGHT;

            Block[] blocks = new Block[Chunk.WIDTH * Chunk.HEIGHT * Chunk.DEPTH];

            for (int x = 0; x < Chunk.WIDTH; x++)
                for (int z = 0; z < Chunk.DEPTH; z++)
                {
                    int offset = x * Chunk.DEPTH * Chunk.HEIGHT + z * Chunk.HEIGHT;

                    int mapX = (int)chunkOffset.X * Chunk.WIDTH + x;
                    int mapY = (int)chunkOffset.Y * Chunk.HEIGHT;
                    int mapZ = (int)chunkOffset.Z * Chunk.DEPTH + z;

                    float octave1 = (perlinNoise.Noise(2.0f * mapX * 1 / noiseWidth, 2.0f * mapZ * 1 / noiseDepth) + 1) / 2 * 0.7f;
                    float octave2 = (perlinNoise.Noise(4.0f * mapX * 1 / noiseWidth, 4.0f * mapZ * 1 / noiseDepth) + 1) / 2 * 0.2f;
                    float octave3 = (perlinNoise.Noise(8.0f * mapX * 1 / noiseWidth, 8.0f * mapZ * 1 / noiseDepth) + 1) / 2 * 0.1f;

                    float rnd = octave1 + octave2 + octave3;

                    int grassHeight = (int)Math.Floor(rnd * mapHeight) - mapY;

                    int dirtHeight = grassHeight - 4;

                    int curY = 0;

                    for (; curY < (dirtHeight) && curY < Chunk.HEIGHT; curY++)
                        blocks[offset + curY] = new Block(BlockType.Rock);

                    for (; curY < grassHeight && curY < Chunk.HEIGHT; curY++)
                        blocks[offset + curY] = new Block(BlockType.Dirt);

                    if (curY == grassHeight && curY < Chunk.HEIGHT)
                    {
                        blocks[offset + curY] = new Block(BlockType.Grass);
                        curY++;
                    }

                    for (; curY < Map.WATER_HEIGHT * NUM_CHUNKS_HEIGHT * Chunk.HEIGHT; curY++)
                    {
                        blocks[offset + curY] = new Block(BlockType.Water);
                    }

                    for (; curY < Chunk.HEIGHT; curY++)
                    {
                        blocks[offset + curY] = new Block(BlockType.None);
                    }

                }

            return new Chunk(_game, chunkOffset, blocks);
        }
Exemplo n.º 8
0
 public static bool IsSolid(Block block)
 {
     return !IsNone(block) && !IsLiquid(block);
 }
Exemplo n.º 9
0
 public static bool IsTransparent(Block block)
 {
     return IsNone(block) || IsLiquid(block);
 }
Exemplo n.º 10
0
 public static bool IsSelectable(Block block)
 {
     return block.Type != BlockType.None;
 }
Exemplo n.º 11
0
 public static bool IsNone(Block block)
 {
     return block.Type == BlockType.None;
 }
Exemplo n.º 12
0
 public static bool IsLiquid(Block block)
 {
     return block.Type == BlockType.Water;
 }
Exemplo n.º 13
0
        public static float[] GetUVMapping(Block block)
        {
            int numTexturesPerRow = 2;
            int numTexturesPerCol = 2;

            float width = 1.0f / numTexturesPerRow;
            float height = 1.0f / numTexturesPerCol;

            float x = ((float)(((int)block.Type - 1) % numTexturesPerRow)) / numTexturesPerRow;
            float y = ((float)(int)(((int)block.Type - 1) / numTexturesPerRow)) / numTexturesPerCol;

            return new float[] { x, y, width, height };
        }
Exemplo n.º 14
0
 public void ReplaceWithBlock(Block block)
 {
     var chunk = _map.GetChunkAt(X, Y, Z);
     chunk.SetBlockAt(X, Y, Z, block);
 }