Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm pretty new to programming games (this is my 1st program in XNA), and I ran into a problem. I want to make a block engine, and this far I have a chunk, and I can move around it with the camera while random blocks are constantly removed from the chunk. My problem is that every time I'm rebuilding the chunk: clearing the vertexlist than adding the required sides of the cubes to it (I only add sides if the neighbor is inactive), the game freezes up for a short time. My chunk only have 800-1200 triangles this way so it shouldn't really tax the computer (FPS is between 50-60), I guess the rebuilding delays the camera movement. I will post my code, could anybody give me some advice on it? (for example would it help if I would make a separate thread for rebuilding the chunk? )

I won't add the Block class (it has a bool if its active or not), and the Dev_Messages class (FPS and triangle display), but the other 3 classes might be relevant.

Thanks in advance!

namespace Chunk
{

    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;

        Camera camera;
        Dev_Messages dev;

        Chunk chunk;

        //TESTING
        bool animate = true;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }


        protected override void Initialize()
        {
            camera = new Camera(this, new Vector3(0, 0, 40), Vector3.Zero, Vector3.Up);
            chunk = new Chunk(GraphicsDevice);
            dev = new Dev_Messages(this);

            Components.Add(camera);

            base.Initialize();
        }


        protected override void LoadContent()
        {
        }


        protected override void UnloadContent()
        {

        }


        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            if (animate == true) chunk.Update(gameTime.ElapsedGameTime.TotalMilliseconds);

            if (Keyboard.GetState().IsKeyDown(Keys.D1)) animate = false;
            if (Keyboard.GetState().IsKeyDown(Keys.D2)) animate = true;

            dev.Update(gameTime);

            base.Update(gameTime);
        }


        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            GraphicsDevice.DepthStencilState = DepthStencilState.Default;
            GraphicsDevice.BlendState = BlendState.Opaque;

            chunk.Draw(camera);

            dev.Draw(chunk.getTriangleCount());

            base.Draw(gameTime);
        }
    }
}

CHUNK CLASS:

namespace Chunk
{
    class Chunk
    {
        private const int DIM_X = 8;
        private const int DIM_Y = 8;
        private const int DIM_Z = 8;

        Block[,,] block = new Block [DIM_X, DIM_Y, DIM_Z];

        Random random = new Random();
        int rnd1, rnd2, rnd3;
        double TIME = 0;

        private float R = 1;
        private Vector3 POS = new Vector3(0,0,0);

        private VertexBuffer vertexbuffer;
        private List<VertexPositionColor> vertexlist;
        private GraphicsDevice device;
        private BasicEffect effect;

        public Chunk(GraphicsDevice device_) {
            device = device_;
            effect = new BasicEffect(device);
            vertexlist = new List<VertexPositionColor>();

            for (int x = 0; x < DIM_X; x++) {
                for (int y = 0; y < DIM_Y; y++) {
                    for (int z = 0; z < DIM_Z; z++) {
                        block[x, y, z] = new Block(true);
                    }
                }
            }

            Build();
        }


        public int getTriangleCount() {
            return vertexbuffer.VertexCount / 3;
        }


        public void Build() {
            Color c1 = new Color(155, 255, 155);
            Color c2 = new Color(0, 50, 0);
            Color c3 = new Color(0, 150, 0);

            for (int x = 0; x < DIM_X; x++) {
                for (int y = 0; y < DIM_Y; y++) {
                    for (int z = 0; z < DIM_Z; z++) {
                        if (block[x, y, z].IsActive()) {

                            POS = new Vector3(2 * x + 1, 2 * y + 1, -2 * z - 1);

                            //FRONT
                            if ((z > 0) && (block[x, y, z-1].IsActive() == false) || z == 0)
                            {
                                vertexlist.Add(new VertexPositionColor(new Vector3(POS.X - R, POS.Y + R, POS.Z + R), c1));
                                vertexlist.Add(new VertexPositionColor(new Vector3(POS.X + R, POS.Y + R, POS.Z + R), c2));
                                vertexlist.Add(new VertexPositionColor(new Vector3(POS.X - R, POS.Y - R, POS.Z + R), c2));
                                vertexlist.Add(new VertexPositionColor(new Vector3(POS.X - R, POS.Y - R, POS.Z + R), c2)); //verts[2]
                                vertexlist.Add(new VertexPositionColor(new Vector3(POS.X + R, POS.Y + R, POS.Z + R), c2));//verts[1]
                                vertexlist.Add(new VertexPositionColor(new Vector3(POS.X + R, POS.Y - R, POS.Z + R), c3));
                            }

                            //BACK
                            if ((z < DIM_Z - 1) && (block[x, y, z + 1].IsActive() == false) || z == DIM_Z - 1)
                            {
                                vertexlist.Add(new VertexPositionColor(new Vector3(POS.X + R, POS.Y + R, POS.Z - R), c1));
                                vertexlist.Add(new VertexPositionColor(new Vector3(POS.X - R, POS.Y + R, POS.Z - R), c2));
                                vertexlist.Add(new VertexPositionColor(new Vector3(POS.X + R, POS.Y - R, POS.Z - R), c2));
                                vertexlist.Add(new VertexPositionColor(new Vector3(POS.X + R, POS.Y - R, POS.Z - R), c2));
                                vertexlist.Add(new VertexPositionColor(new Vector3(POS.X - R, POS.Y + R, POS.Z - R), c2));
                                vertexlist.Add(new VertexPositionColor(new Vector3(POS.X - R, POS.Y - R, POS.Z - R), c3));
                            }

                            //TOP
                            if ((y < DIM_Y-1) && (block[x, y+1, z].IsActive() == false) || y == DIM_Y-1)
                            {
                                vertexlist.Add(new VertexPositionColor(new Vector3(POS.X - R, POS.Y + R, POS.Z - R), c3));
                                vertexlist.Add(new VertexPositionColor(new Vector3(POS.X + R, POS.Y + R, POS.Z - R), c2));
                                vertexlist.Add(new VertexPositionColor(new Vector3(POS.X - R, POS.Y + R, POS.Z + R), c2));
                                vertexlist.Add(new VertexPositionColor(new Vector3(POS.X - R, POS.Y + R, POS.Z + R), c2));
                                vertexlist.Add(new VertexPositionColor(new Vector3(POS.X + R, POS.Y + R, POS.Z - R), c2));
                                vertexlist.Add(new VertexPositionColor(new Vector3(POS.X + R, POS.Y + R, POS.Z + R), c1));
                            }

                            //BOTTOM
                            if ((y > 0) && (block[x, y - 1, z].IsActive() == false) || y == 0)
                            {
                                vertexlist.Add(new VertexPositionColor(new Vector3(POS.X + R, POS.Y - R, POS.Z - R), c1));
                                vertexlist.Add(new VertexPositionColor(new Vector3(POS.X - R, POS.Y - R, POS.Z - R), c2));
                                vertexlist.Add(new VertexPositionColor(new Vector3(POS.X + R, POS.Y - R, POS.Z + R), c2));
                                vertexlist.Add(new VertexPositionColor(new Vector3(POS.X + R, POS.Y - R, POS.Z + R), c2));
                                vertexlist.Add(new VertexPositionColor(new Vector3(POS.X - R, POS.Y - R, POS.Z - R), c2));
                                vertexlist.Add(new VertexPositionColor(new Vector3(POS.X - R, POS.Y - R, POS.Z + R), c3));
                            }

                            //LEFT
                            if ((x > 0) && (block[x-1, y, z].IsActive() == false) || x == 0)
                            {
                                vertexlist.Add(new VertexPositionColor(new Vector3(POS.X - R, POS.Y + R, POS.Z - R), c1));
                                vertexlist.Add(new VertexPositionColor(new Vector3(POS.X - R, POS.Y + R, POS.Z + R), c2));
                                vertexlist.Add(new VertexPositionColor(new Vector3(POS.X - R, POS.Y - R, POS.Z - R), c2));
                                vertexlist.Add(new VertexPositionColor(new Vector3(POS.X - R, POS.Y - R, POS.Z - R), c2));
                                vertexlist.Add(new VertexPositionColor(new Vector3(POS.X - R, POS.Y + R, POS.Z + R), c2));
                                vertexlist.Add(new VertexPositionColor(new Vector3(POS.X - R, POS.Y - R, POS.Z + R), c3));
                            }

                            //RIGHT
                            if ((x < DIM_X-1) && (block[x + 1, y, z].IsActive() == false) || x == DIM_X-1)
                            {
                                vertexlist.Add(new VertexPositionColor(new Vector3(POS.X + R, POS.Y + R, POS.Z + R), c1));
                                vertexlist.Add(new VertexPositionColor(new Vector3(POS.X + R, POS.Y + R, POS.Z - R), c2));
                                vertexlist.Add(new VertexPositionColor(new Vector3(POS.X + R, POS.Y - R, POS.Z + R), c2));
                                vertexlist.Add(new VertexPositionColor(new Vector3(POS.X + R, POS.Y - R, POS.Z + R), c2));
                                vertexlist.Add(new VertexPositionColor(new Vector3(POS.X + R, POS.Y + R, POS.Z - R), c2));
                                vertexlist.Add(new VertexPositionColor(new Vector3(POS.X + R, POS.Y - R, POS.Z - R), c3));
                            }

                            vertexbuffer = new VertexBuffer(device, typeof(VertexPositionColor), vertexlist.Count, BufferUsage.None);
                            vertexbuffer.SetData(vertexlist.ToArray());
                        }
                    }
                }
            }
        }


        public void Update(double time) {
            TIME += time;
            if (TIME > 1000)
            {
                rnd1 = random.Next(0, DIM_X);
                rnd2 = random.Next(0, DIM_Y);
                rnd3 = random.Next(0, DIM_Z);

                if (block[rnd1, rnd2, rnd3].IsActive() == true)
                {
                    block[rnd1, rnd2, rnd3].setActive(false);

                    vertexlist.Clear();
                    TIME = 0;
                    Build();
                }
            }
        }


        public void Draw(Camera camera) {

            effect.World = Matrix.Identity;
            effect.View = camera.view;
            effect.Projection = camera.projection;
            effect.VertexColorEnabled = true;

            foreach (EffectPass pass in effect.CurrentTechnique.Passes)
            {
                pass.Apply();

                device.SetVertexBuffer(vertexbuffer);
                device.DrawPrimitives(PrimitiveType.TriangleList, 0, vertexbuffer.VertexCount / 3);
            }
        }

    }
}

CAMERA CLASS:

namespace Chunk
{

    public class Camera : Microsoft.Xna.Framework.GameComponent
    {
        public Matrix view {get; protected set;}
        public Matrix projection {get; protected set;}
        public Vector3 cameraPosition { get; protected set;}

        MouseState originalMouseState;

        Vector3 cameraDirection;
        Vector3 cameraUp;

        float leftrightRot = 0;
        float updownRot = 0;
        const float rotationSpeed = 0.003f;

        public Camera(Game game, Vector3 pos, Vector3 target, Vector3 up)
            : base(game)
        {
            //Build camera view matrix
            cameraPosition = pos;
            cameraDirection = target - pos;
            cameraDirection.Normalize();
            cameraUp = up;

            //projection matrix (FOV, Aspect ratio, near/far clipping)
            projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, 
            (float)Game.Window.ClientBounds.Width / (float)Game.Window.ClientBounds.Height, 1, 300);
        }

        private void UpdateViewMatrix()
        {
            Matrix cameraRotation = Matrix.CreateRotationX(updownRot) * Matrix.CreateRotationY(leftrightRot);

            Vector3 cameraOriginalTarget = new Vector3(0, 0, -1);
            Vector3 cameraRotatedTarget = Vector3.Transform(cameraOriginalTarget, cameraRotation);
            Vector3 cameraFinalTarget = cameraPosition + cameraRotatedTarget;

            Vector3 cameraOriginalUpVector = new Vector3(0, 1, 0);
            Vector3 cameraRotatedUpVector = Vector3.Transform(cameraOriginalUpVector, cameraRotation);

            view = Matrix.CreateLookAt(cameraPosition, cameraFinalTarget, cameraRotatedUpVector);
        }

        public override void Initialize()
        {
            UpdateViewMatrix();

            // Set mouse position and do initial get state
            Mouse.SetPosition(Game.Window.ClientBounds.Width / 2, Game.Window.ClientBounds.Height / 2);
            originalMouseState = Mouse.GetState();

            base.Initialize();
        }

        public override void Update(GameTime gameTime)
        {
            Vector3 moveVector = new Vector3(0, 0, 0);

            // Move forward/backward
            if (Keyboard.GetState( ).IsKeyDown(Keys.W))
                moveVector += new Vector3(0, 0, -1);
            if (Keyboard.GetState( ).IsKeyDown(Keys.S))
                moveVector += new Vector3(0, 0, 1);

            // Move side to side
            if (Keyboard.GetState( ).IsKeyDown(Keys.A))
                moveVector += new Vector3(-1, 0, 0);
            if (Keyboard.GetState( ).IsKeyDown(Keys.D))
                moveVector += new Vector3(1, 0, 0);

            // Ascend / Descend
            if (Keyboard.GetState().IsKeyDown(Keys.Space))
                cameraPosition += new Vector3(0, 1, 0);
            if (Keyboard.GetState().IsKeyDown(Keys.LeftControl))
                cameraPosition += new Vector3(0, -1, 0);

            float TimeDiff = (float)gameTime.ElapsedGameTime.TotalMilliseconds / 10f;

            //Move
            AddToCameraPosition(moveVector * TimeDiff);

            //Mouse Look
            MouseState currentMouseState = Mouse.GetState();
            if (currentMouseState != originalMouseState) {
                float xDifference = currentMouseState.X - originalMouseState.X;
                float yDifference = currentMouseState.Y - originalMouseState.Y;
                leftrightRot -= rotationSpeed * xDifference * TimeDiff;
                updownRot -= rotationSpeed * yDifference * TimeDiff;
                Mouse.SetPosition(Game.Window.ClientBounds.Width / 2, Game.Window.ClientBounds.Height / 2);              
            }

            UpdateViewMatrix();

            base.Update(gameTime);
        }

        private void AddToCameraPosition(Vector3 vectorToAdd) {
            Matrix cameraRotation = Matrix.CreateRotationX(updownRot) * Matrix.CreateRotationY(leftrightRot);
            Vector3 rotatedVector = Vector3.Transform(vectorToAdd, cameraRotation);
            cameraPosition += rotatedVector;
            UpdateViewMatrix();            
        }

    }
}
share|improve this question
    
Voting to close for "debug my code for me." This would be better asked in our chat or in a discussion forum which is designed for personal assistance. We're aiming for more universal and concrete Q&A, here. :) –  Trevor Powell Feb 13 '13 at 0:22
add comment

closed as too localized by Byte56, Sean Middleditch, Josh Petrie, Trevor Powell, bummzack Feb 13 '13 at 8:39

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.If this question can be reworded to fit the rules in the help center, please edit the question.

2 Answers

up vote 0 down vote accepted

I think you recreate the vertexbuffer after each new block in the three for-loops in the Build() method. Just try to recreate the vertexbuffer only one time after this loops ;)

share|improve this answer
    
Thank you it solved the problem! –  szendroib Feb 11 '13 at 16:36
add comment

You might want to redesign the build method wherein you're not instancing new objects. One reason for the delays, is probably the amount of new objects you are recreating every time during the chunk update.

I experienced this when coding Techcraft. Feel free to look through earlier commits of the code there. http://techcraft.codeplex.com

share|improve this answer
    
Correct me if I'm wrong, but I thought that creting new instances of a value type is perfectly fine and (almost) just as fast as changing existing value's fields. –  Jaakko Lipsanen Feb 11 '13 at 16:05
    
Thank you for the Techcraft codes, I'm sure it will help a lot. –  szendroib Feb 11 '13 at 16:35
    
Last year, I added HUD GUI objects to another voxel project i'm working on link During testing, I noticed how creation of new instances of HUD objects in the update and draw calls was slowing my framerate down by 60%. After refactoring, the framerate was back around 60fps. Of course, it requires a considerable amount of new instances to notice this behaviour. –  Jason Coombes Feb 12 '13 at 11:47
add comment

Not the answer you're looking for? Browse other questions tagged or ask your own question.