Example #1
0
        public override void MakeChunkData(int chunkX, int chunkZ, Block[, ,] arrayToFill, List<EntitySchema> entityDataToFill)
        {
            for (int x = 0; x < GameConstants.CHUNK_X_WIDTH; x++)
            {
                for (int z = 0; z < GameConstants.CHUNK_Z_LENGTH; z++)
                {
                    int height = FindHeight(chunkX * GameConstants.CHUNK_X_WIDTH + x, chunkZ * GameConstants.CHUNK_Z_LENGTH + z);

                    for (int y = 0; y < GameConstants.CHUNK_Y_HEIGHT; y++)
                    {
                        Block block;

                        if (y <= height)
                            block = new Block(1);
                        else
                            block = new Block(0);

                        arrayToFill[x, y, z] = block;
                    }

                    if (x == 0 && z == 0)
                        entityDataToFill.Add(new EntitySchema(0, x, height+5, z));
                }
            }
        }
Example #2
0
        private static void addBlockData(int chunkX, int chunkZ, Block[, ,] arrayToFill)
        {
            for (int x = 0; x < GameConstants.CHUNK_X_WIDTH; x++)
            {
                for (int y = 0; y < GameConstants.CHUNK_Y_HEIGHT; y++)
                {
                    for (int z = 0; z < GameConstants.CHUNK_Z_LENGTH; z++)
                    {
                        Block block;

                        //ground everywhere, and pyramid mountains
                        //that are right on the corners of the chunks

                        if (y == 0) //uniform ground everywhere, but sometimes ice
                        {
                            if ((chunkX & 1) == 0 || (chunkZ & 1) == 0)
                                block = new Block(1);
                            else
                                block = new Block(2);
                        }
                        else if (y == 10 && x == 5 && z == 5)
                        {
                            block = new Block(1);
                        }
                        else if ((chunkX & 1) == 0 && (chunkZ & 1) == 0) //even/even chunk coords, etc.
                        {
                            if (z >= x + y + 5)
                                block = new Block(1);
                            else
                                block = new Block(0);
                        }
                        else if ((chunkX & 1) == 1 && (chunkZ & 1) == 0)
                        {
                            if (z >= (GameConstants.CHUNK_X_WIDTH - x) + y + 5)
                                block = new Block(1);
                            else
                                block = new Block(0);
                        }
                        else if ((chunkX & 1) == 0 && (chunkZ & 1) == 1)
                        {
                            if ((GameConstants.CHUNK_Z_LENGTH - z - 2) >= x + y + 5)
                                block = new Block(1);
                            else
                                block = new Block(0);
                        }
                        else
                        {
                            if ((GameConstants.CHUNK_Z_LENGTH - z - 3) >= (GameConstants.CHUNK_X_WIDTH - x - 1) + y + 5)
                                block = new Block(1);
                            else
                                block = new Block(0);
                        }

                        arrayToFill[x, y, z] = block;
                    }
                }
            }
        }
        protected override GeometryPrimitive drawingPrimitive(Block block,
            bool includeFrontFace, bool includeBackFace,
            bool includeTopFace, bool includeBottomFace,
            bool includeLeftFace, bool includeRightFace)
        {
            int flag = BlockHandler.ConvertBoolFlagsToInt(
                includeFrontFace, includeBackFace,
                includeTopFace, includeBottomFace,
                includeLeftFace, includeRightFace);

            return primitives[flag];
        }
        protected override float friction(Block block)
        {
            switch (block.blockID)
            {
                case 1:
                    return 20;

                case 2:
                    return 0.3f;

                default:
                    throw new ArgumentOutOfRangeException();
            }
        }
        protected override bool isPassable(Block block)
        {
            switch (block.blockID)
            {
                case 0:
                    return true;

                case 1:
                case 2:
                    return false;

                default:
                    throw new ArgumentOutOfRangeException();
            }
        }
        protected override GeometryPrimitive drawingPrimitive(Block block,
            bool includeFrontFace = true, bool includeBackFace = true,
            bool includeTopFace = true, bool includeBottomFace = true,
            bool includeLeftFace = true, bool includeRightFace = true)
        {
            switch (block.blockID)
            {
                case 1:
                case 2:
                    int flags = ConvertBoolFlagsToInt(includeFrontFace, includeBackFace, includeTopFace, includeBottomFace, includeLeftFace, includeRightFace);
                    return fullSizeBlocks[flags];

                default: throw new ArgumentOutOfRangeException();
            }
        }
Example #7
0
        /// <summary>
        /// Construct a new collider object for a block.  Note the specified coordinates are for
        /// the block itself (describing its position in space) and not for the thing it's colliding with.
        /// </summary>
        /// <param name="block"></param>
        /// <param name="chunkX"></param>
        /// <param name="blockX"></param>
        /// <param name="chunkZ"></param>
        /// <param name="blockZ"></param>
        /// <param name="handler"></param>
        public Collider(Block block, int chunkX, int chunkZ, int blockX, int blockY, int blockZ)
        {
            #if DEBUG
            this.collidedObject = block;
            #endif

            this.colliderChunkX = chunkX;
            this.colliderChunkZ = chunkZ;

            this.StartingBoundingBox = BlockHandler.PhysicalBlockingBox(block);
            Vector3 translation = new Vector3(blockX, blockY, blockZ);

            this.StartingBoundingBox = new BoundingBox(
                StartingBoundingBox.Min + translation, StartingBoundingBox.Max + translation);

            this.Friction = BlockHandler.Friction(block);
            this.FrictionVelocity = BlockHandler.FrictionVelocity(block);
        }
Example #8
0
 /// <summary>
 /// This takes as input a position and a Ray and a maximum distance, then finds
 /// the first Block impacted by the Ray on this map, if any.  Return types are
 /// through a large number of "out" parameters.  Note it will never return the
 /// cell which contains the start of the Ray.
 /// 
 /// Note: if successful is FALSE, the returned data will be garbage (since it's
 /// not easily nullable).  So be aware of that.
 /// </summary>
 /// <param name="chunkX">The chunk(X) position to start the Ray from.  This will be
 /// set to the chunk(X) position we end on.</param>
 /// <param name="chunkZ">The chunk(Z) position to start the Ray from.  This will be
 /// set to the chunk(Z) position we end on.</param>
 /// <param name="lookRay">The Ray to look along.</param>
 /// <param name="maxDistance">The maximum distance along the ray that collisions
 /// will be considered.  Uses the MAX distance.</param>
 /// <param name="requireVisible">Whether or not to skip invisible blocks.</param>
 /// <param name="requireImpassable">Whether or not to skip passable blocks.</param>
 /// <param name="foundBlock">The block that was actually found.</param>
 /// <param name="blockPosition">The in-chunk (integer) position of the block that was found.</param>
 /// <param name="faceTouched">The face that was first touched by the Ray.</param>
 /// <param name="successful">Whether ot not anything was found</param>
 public void BlockLookedAt(ref int chunkX, ref int chunkZ, Ray lookRay, int maxDistance,
     bool requireVisible, bool requireImpassable,
     out Block foundBlock, out Point3 blockPosition,
     out Face faceTouched, out bool successful)
 {
     Map.BlockLookedAt(ref chunkX, ref chunkZ, lookRay, maxDistance, requireVisible, requireImpassable,
         out foundBlock, out blockPosition, out faceTouched, out successful);
 }
Example #9
0
        /// <summary>
        /// Helper method for "BlockLookedAt."  Determines whether or not the Block we found fits the requirements
        /// for a successful "find."  Specifically, if "RequireImpassible" is true, then it checks for intersection
        /// with the passability bounding box, and if "RequireVisible" is true, then it checks for intersection with
        /// the visibility bounding box.
        /// </summary>
        /// <param name="lookRay"></param>
        /// <param name="requireVisible"></param>
        /// <param name="requireImpassable"></param>
        /// <param name="foundBlock"></param>
        /// <param name="blockBounds"></param>
        /// <returns></returns>
        private bool BlockLookedAt_TestCompatibility(Ray lookRay, bool requireVisible, bool requireImpassable,
            Block foundBlock, BoundingBox blockBounds)
        {
            bool compatible = true;

            if (requireVisible)
            {
                if (BlockHandler.IsVisible(foundBlock))
                {
                    BoundingBox visualBox = HelperMethods.TranslateBox(BlockHandler.VisualBoundingBox(foundBlock), blockBounds.Min);
                    compatible = compatible && visualBox.Intersects(lookRay).HasValue;
                }
                else
                {
                    compatible = false;
                }
            }

            if (requireImpassable)
            {
                if (BlockHandler.IsPassable(foundBlock))
                {
                    compatible = false;
                }
                else
                {
                    BoundingBox blockingBox = HelperMethods.TranslateBox(BlockHandler.PhysicalBlockingBox(foundBlock), blockBounds.Min);
                    compatible = compatible && blockingBox.Intersects(lookRay).HasValue;
                }
            }

            return compatible;
        }
Example #10
0
 /// <summary>
 /// Whether or not to draw this block.
 /// </summary>
 /// <param name="block"></param>
 /// <returns></returns>
 protected abstract bool isVisible(Block block);
 protected override Vector3 frictionVelocity(Block block)
 {
     return Vector3.Zero;
 }
Example #12
0
        public void ChangeBlock(int chunkX, int chunkZ, int blockX, int blockY, int blockZ, Block newBlock)
        {
            HelperMethods.FixCoordinates(ref chunkX, ref chunkZ, ref blockX, ref blockY, ref blockZ);

            lock (CacheLock)
            {
                if (!IsReady(chunkX, chunkZ))
                    throw new ArgumentException("Can't modify a chunk we haven't generated!");

                CacheData dat = this[chunkX, chunkZ];

                dat.Chunk[blockX, blockY, blockZ] = newBlock;
                dat.Chunk.RecalculateVisualGeometry();

                SaveChunk(chunkX, chunkZ);
            }
        }
Example #13
0
 protected abstract int textureIndex(Block block);
Example #14
0
 /// <summary>
 /// Whether or not this block, when drawn,
 /// fills the entire allotted space and is
 /// completely opaque (and in particular, is
 /// visible!).  Used for culling drawing
 /// data, so be sure to be correct :P
 /// 
 /// This particular form is whether it blocks the
 /// view to the right; that is, whether the right
 /// face is completely opaque and fills the space.
 /// 
 /// Default behavior is to return IsVisible;
 /// this need only be overridden if this block is
 /// partially transparent.
 /// </summary>
 /// <param name="block"></param>
 /// <returns></returns>
 protected virtual bool isFullAndOpaqueToTheRight(Block block)
 {
     return instance.isVisible(block);
 }
Example #15
0
 public static GeometryPrimitive DrawingPrimitive(Block block,
     bool includeFrontFace, bool includeBackFace,
     bool includeTopFace, bool includeBottomFace,
     bool includeLeftFace, bool includeRightFace)
 {
     return instance.drawingPrimitive(block,
         includeFrontFace, includeBackFace, includeTopFace,
         includeBottomFace, includeLeftFace, includeRightFace);
 }
Example #16
0
 /// <summary>
 /// The model for drawing this block.  Not required to
 /// be implemented when IsVisible is false.
 /// 
 /// The optional parameters refer to possibly excluding occluded
 /// faces.  Failure to take these into account will hurt performance
 /// significantly.
 /// </summary>
 /// <param name="block"></param>
 /// <returns></returns>
 protected abstract GeometryPrimitive drawingPrimitive(Block block,
     bool includeFrontFace, bool includeBackFace,
     bool includeTopFace, bool includeBottomFace,
     bool includeLeftFace, bool includeRightFace);
Example #17
0
 public static BoundingBox VisualBoundingBox(Block block) { return instance.visualBoundingBox(block); }
Example #18
0
 /// <summary>
 /// The boundingbox which this square actually blocks
 /// passage through.  This method is only valid when IsVisible
 /// is true.
 /// </summary>
 /// <param name="block"></param>
 /// <returns></returns>
 protected BoundingBox visualBoundingBox(Block block)
 {
     return new BoundingBox(Vector3.Zero, Vector3.One);
 }
Example #19
0
 public static bool IsVisible(Block block) { return instance.isVisible(block); }
Example #20
0
        /// <summary>
        /// This takes as input a maximum distance, then finds the first Block impacted
        /// by the Camera's Forward Ray on this map, if any.  Return types are through
        /// a large number of "out" parameters.  Note it will never return the
        /// cell which contains the start of the Ray.
        /// 
        /// This is just a convenient default parameter set for the other BlockLookedAt
        /// method.  The effect and output are the same as filling in the arguments with
        /// information from Camera.
        /// 
        /// Note: if successful is FALSE, the returned data will be garbage (since it's
        /// not easily nullable).  So be aware of that.
        /// </summary>
        /// <param name="maxDistance">The maximum distance along the ray that collisions
        /// will be considered.  Uses the MAX-norm.</param>
        /// <param name="requireVisible">Whether or not to skip invisible blocks.</param>
        /// <param name="requireImpassable">Whether or not to skip passable blocks.</param>
        /// <param name="foundBlock">The block that was actually found.</param>
        /// <param name="chunkX">The chunk(X) position we end on.</param>
        /// <param name="chunkZ">The chunk(Z) position we end on.</param>
        /// <param name="blockPosition">The in-chunk (integer) position of the block that was found.</param>
        /// <param name="faceTouched">The face that was first touched by the Ray.</param>
        /// <param name="successful">Whether ot not anything was found</param>
        public void BlockLookedAt(int maxDistance, bool requireVisible, bool requireImpassable,
            out Block foundBlock, out int chunkX, out int chunkZ, out Point3 blockPosition,
            out Face faceTouched, out bool successful)
        {
            chunkX = Camera.ChunkX;
            chunkZ = Camera.ChunkZ;

            Map.BlockLookedAt(ref chunkX, ref chunkZ, Camera.ForwardRay, maxDistance,
                requireVisible, requireImpassable,
                out foundBlock, out blockPosition, out faceTouched,
                out successful);
        }
Example #21
0
 public override void MakeChunkData(int chunkX, int chunkZ, Block[, ,] arrayToFill, List<EntitySchema> entityDataToFill)
 {
     addEntityData(entityDataToFill);
     addBlockData(chunkX, chunkZ, arrayToFill);
 }
Example #22
0
 public static bool IsFullAndOpaqueToTheRight(Block block) { return instance.isFullAndOpaqueToTheRight(block); }
Example #23
0
 public static Vector3 FrictionVelocity(Block block) { return instance.frictionVelocity(block); }
Example #24
0
 public static float Friction(Block block) { return instance.friction(block); }
        protected override int textureIndex(Block block)
        {
            switch (block.blockID)
            {
                case 1:
                    return 0;

                case 2:
                    return 1;

                default:
                    throw new NotImplementedException();
            }
        }
Example #26
0
 public void ChangeBlock(int chunkX, int chunkZ, int blockX, int blockY, int blockZ, Block newBlock)
 {
     Cache.ChangeBlock(chunkX, chunkZ, blockX, blockY, blockZ, newBlock);
 }
Example #27
0
 protected abstract Vector3 frictionVelocity(Block block);
Example #28
0
 /// <summary>
 /// This is where you get to do your procedural generation!
 /// By whatever means you deem appropriate, construct a chunk
 /// of cubes at the designated "chunk coordinates."
 /// 
 /// FUN FACT: you need to include a "buffer block" on each lateral
 /// (that is, x or z) side.  It is important that this is the same
 /// block as would actually be generated by the appropriate other call!
 /// </summary>
 /// <param name="chunkX"></param>
 /// <param name="chunkZ"></param>
 /// <param name="chunkBlocksToFill">The array to fill with block data</param>
 /// <returns></returns>
 public abstract void MakeChunkData(int chunkX, int chunkZ, Block[, ,] chunkBlocksToFill, List<EntitySchema> entityListToFill);
Example #29
0
        /// <summary>
        /// This takes as input a position and a Ray and a maximum distance, then finds
        /// the first Block impacted by the Ray on this map, if any.  Return types are
        /// through a large number of "out" parameters.  Note it will never return the
        /// cell which contains the start of the Ray.
        /// 
        /// Note: if successful is FALSE, the returned data will be garbage (since it's
        /// not easily nullable).  So be aware of that.
        /// </summary>
        /// <param name="chunkX">The chunk(X) position to start the Ray from.  This will be
        /// set to the chunk(X) position we end on.</param>
        /// <param name="chunkZ">The chunk(Z) position to start the Ray from.  This will be
        /// set to the chunk(Z) position we end on.</param>
        /// <param name="lookRay">The Ray to look along.</param>
        /// <param name="maxDistance">The maximum distance along the ray that collisions
        /// will be considered.  Uses the MAX distance.</param>
        /// <param name="requireVisible">Whether or not to skip invisible blocks.</param>
        /// <param name="requireImpassable">Whether or not to skip passable blocks.</param>
        /// <param name="foundBlock">The block that was actually found.</param>
        /// <param name="blockPosition">The in-chunk (integer) position of the block that was found.</param>
        /// <param name="faceTouched">The face that was first touched by the Ray.</param>
        /// <param name="successful">Whether ot not anything was found</param>
        public void BlockLookedAt(ref int chunkX, ref int chunkZ, Ray lookRay, int maxDistance,
            bool requireVisible, bool requireImpassable,
            out Block foundBlock, out Point3 blockPosition,
            out Face faceTouched, out bool successful)
        {
            if (lookRay.Position.Y < 0 || lookRay.Position.Y >= GameConstants.CHUNK_Y_HEIGHT)
                throw new ArgumentException("Can't cast rays from offscreen!");

            successful = false;

            blockPosition = Point3.RoundDown(lookRay.Position);
            BoundingBox blockBounds = new BoundingBox(
                new Vector3(blockPosition.X, blockPosition.Y, blockPosition.Z),
                new Vector3(blockPosition.X + 1, blockPosition.Y + 1, blockPosition.Z + 1));

            if (!blockBounds.Intersects(lookRay).HasValue)
                throw new NotImplementedException();

            int xChange = Numerical.sign(lookRay.Direction.X);
            int yChange = Numerical.sign(lookRay.Direction.Y);
            int zChange = Numerical.sign(lookRay.Direction.Z);

            faceTouched = Face.FRONT;
            foundBlock = new Block();

            while (blockPosition.Y >= 0 && blockPosition.Y < GameConstants.CHUNK_Y_HEIGHT)
            {
                bool canMoveX = (xChange != 0);
                bool canMoveY = (yChange != 0 && (blockPosition.Y + yChange >= 0 && blockPosition.Y + yChange < GameConstants.CHUNK_Y_HEIGHT));
                bool canMoveZ = (zChange != 0);

                bool hitX = false;
                bool hitY = false;
                bool hitZ = false;

                BoundingBox oldBox = blockBounds;

                int hits = 0;

                #region Move and count hits...
                if (canMoveX)
                {
                    BoundingBox box = new BoundingBox(oldBox.Min + new Vector3(xChange, 0, 0), oldBox.Max + new Vector3(xChange, 0, 0));

                    float? result = box.Intersects(lookRay);
                    hitX = result.HasValue;

                    if (hitX)
                    {
                        hits++;

                        blockPosition.X += xChange;
                        faceTouched = (xChange < 0 ? Face.RIGHT : Face.LEFT);
                        blockBounds = box;

                        if (Math.Abs(blockPosition.X - lookRay.Position.X) > maxDistance) return;
                    }
                }

                if (canMoveY)
                {
                    BoundingBox box = new BoundingBox(oldBox.Min + new Vector3(0, yChange, 0), oldBox.Max + new Vector3(0, yChange, 0));

                    float? result = box.Intersects(lookRay);
                    hitY = result.HasValue;

                    if (hitY)
                    {
                        hits++;

                        blockPosition.Y += yChange;
                        faceTouched = (yChange < 0 ? Face.TOP : Face.BOTTOM);
                        blockBounds = box;

                        if (Math.Abs(blockPosition.Y - lookRay.Position.Y) > maxDistance) return;
                    }
                }

                if (canMoveZ)
                {
                    BoundingBox box = new BoundingBox(oldBox.Min + new Vector3(0, 0, zChange), oldBox.Max + new Vector3(0, 0, zChange));

                    float? result = box.Intersects(lookRay);
                    hitZ = result.HasValue;

                    if (hitZ)
                    {
                        hits++;

                        blockPosition.Z += zChange;
                        faceTouched = (zChange < 0 ? Face.BACK : Face.FRONT);
                        blockBounds = box;

                        if (Math.Abs(blockPosition.Z - lookRay.Position.Z) > maxDistance) return;
                    }
                }
                #endregion

                //We either hit a corner (yielding multiple matches) or ran off
                //the edge of the world.  In either case, I'm OK with "no result."
                if (hits != 1)
                    return;

                foundBlock = GetHighPriorityBlock(chunkX, chunkZ, blockPosition.X, blockPosition.Y, blockPosition.Z);

                if (BlockLookedAt_TestCompatibility(lookRay, requireVisible, requireImpassable, foundBlock, blockBounds))
                {
                    successful = true;
                    HelperMethods.FixCoordinates(ref chunkX, ref chunkZ, ref blockPosition);

                    return;
                }
            }
        }
Example #30
0
 public static int TextureIndex(Block block) { return instance.textureIndex(block); }