Draw an endless line in XNA

I am drawing a line in XNA that I never want to end. I also have a tool that moves forward in the X direction and a camera centered with that tool. However, when I get to the end of the viewport, the lines are no longer drawn. Here are some illustrations to illustrate my problem:

enter image description here

At the beginning, the line crosses the entire screen, but as my tool progresses, we reach the end of the line.

Here is the method that draws the lines:

        private void DrawEvenlySpacedSprites (Texture2D texture, Vector2 point1, Vector2 point2, float increment)
    {
        var distance = Vector2.Distance (point1, point2);    // the distance between two points
        var iterations = (int)(distance / increment);       // how many sprites with be drawn
        var normalizedIncrement = 1.0f / iterations;        // the Lerp method needs values between 0.0 and 1.0
        var amount = 0.0f;

        if (iterations == 0)
            iterations = 1;

        for (int i = 0; i < iterations; i++) {
            var drawPoint = Vector2.Lerp (point1, point2, amount);
            spriteBatch.Draw (texture, drawPoint, Color.White);
            amount += normalizedIncrement;
        }
    }

      

Here is the in-game drawing method. The dots are my lines:

protected override void Draw (GameTime gameTime)
    {
        graphics.GraphicsDevice.Clear(Color.Black);
        nyVector = nextVector (gammelVector);
        GraphicsDevice.SetRenderTarget (renderTarget);
        spriteBatch.Begin ();
        DrawEvenlySpacedSprites (dot, gammelVector, nyVector, 0.9F);
        spriteBatch.End ();

        GraphicsDevice.SetRenderTarget (null);
        spriteBatch.Begin (SpriteSortMode.Deferred, BlendState.AlphaBlend, null, null, null, null, camera.transform);
        spriteBatch.Draw (renderTarget, new Vector2 (), Color.White);
        spriteBatch.Draw (tool, new Vector2(toolPos.X - (tool.Width/2), toolPos.Y - (tool.Height/2)), Color.White);
        spriteBatch.End ();

        gammelVector = new Vector2 (nyVector.X, nyVector.Y);
        base.Draw (gameTime);
    }

      

Can anyone point me in the right direction? I'm guessing it has to do with viewport.width, but I'm not really sure how to solve it. Thanks for reading!

+3


source to share


1 answer


I read this and thought it would be fun this morning, so I decided to write this for fun.

The implementation is pretty simple, keep adding lines to each other until the last line is outside the visible area.

The following code will draw a line going infinitely to the right. As an additional optimization, the lines on the left side of the screen are removed as they pass. You could easily make it keep the lines that were there earlier, or create lines going to the left as well. I will leave these exercises to you.

Take a look at the following Line class , which will define one line on the screen:

public class Line
{
    Texture2D Texture;
    Color Color;
    public Vector2 PointA;
    public Vector2 PointB;
    float Width;

    public Line(Vector2 pointA, Vector2 pointB, float width, Color color, Texture2D texture)
    {
        Texture = texture;
        PointA = pointA;
        PointB = pointB;
        Width = width;
        Color = color;
    }

    public void Draw(SpriteBatch spritebatch)
    {
        float angle = (float)Math.Atan2(PointB.Y - PointA.Y, PointB.X - PointA.X);
        float length = Vector2.Distance(PointA, PointB);
        spritebatch.Draw(Texture, PointA, null, Color, angle, Vector2.Zero, new Vector2(length, Width), SpriteEffects.None, 0);
    }

}

      



I wrote the implementation inside the game class since I was speedcoding. You can see the Game Class below:

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

    Texture2D LineTexture;
    List<Line> Lines;
    Random Random;

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

    protected override void Initialize()
    {
        base.Initialize();
    }

    protected override void LoadContent()
    {
        spriteBatch = new SpriteBatch(GraphicsDevice);
        Camera = new Camera(GraphicsDevice.Viewport, 1f);

        LineTexture = new Texture2D(GraphicsDevice, 1, 1);
        LineTexture.SetData<Color>(new Color[] { Color.White });

        Random = new Random();
        Lines = new List<Line>();
    }

    protected override void UnloadContent()
    {
    }


    protected override void Update(GameTime gameTime)
    {
        //handle input
        KeyboardState kbState = Keyboard.GetState();

        if (kbState.IsKeyDown(Keys.Escape))
            this.Exit();

        if (kbState.IsKeyDown(Keys.OemMinus))
            Camera.Zoom -= 0.015f;
        else if (kbState.IsKeyDown(Keys.OemPlus))
            Camera.Zoom += 0.015f;

        if (kbState.IsKeyDown(Keys.Up))
            Camera.Move(new Vector2(0, -30));
        else if (kbState.IsKeyDown(Keys.Down))
            Camera.Move(new Vector2(0, 30));
        if (kbState.IsKeyDown(Keys.Left))
            Camera.Move(new Vector2(-30, 0));
        else if (kbState.IsKeyDown(Keys.Right))
            Camera.Move(new Vector2(30, 0));


        //check if line is still in viewport - if not remove it
        for (int i = 0; i < Lines.Count; i++)
        {
            if (Lines[i].PointB.X < Camera.Viewport.X)
            {
                Lines.RemoveAt(i);
                i--;
            }
        }

        //if there are no lines, create one to get started
        if (Lines.Count == 0)
        {
            Vector2 p1 = new Vector2(Camera.Viewport.X, Random.Next(Camera.Viewport.Y + 50, Camera.Viewport.Height - 100));
            Vector2 p2 = new Vector2(p1.X + Random.Next(5, 20), p1.Y + Random.Next(-5, 5));
            Line line = new Line(p1, p2, 1, Color.Black, LineTexture);
            Lines.Add(line);
        }

        //Check if we need to add some lines to the right of our last list item
        while (Lines[Lines.Count - 1].PointB.X < Camera.Viewport.X + Camera.Viewport.Width)
        {
            Vector2 p1 = new Vector2(Lines[Lines.Count - 1].PointB.X, Lines[Lines.Count - 1].PointB.Y); ;
            Vector2 p2 = new Vector2(p1.X + Random.Next(5, 20), p1.Y + Random.Next(-5, 5));
            Line line = new Line(p1, p2, 1, Color.Black, LineTexture);
            Lines.Add(line);
        }

        base.Update(gameTime);
    }

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(new Color(30, 90, 150));

        spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, Camera.View);

        foreach (Line line in Lines)
            line.Draw(spriteBatch);

        spriteBatch.End();

        base.Draw(gameTime);
    }
}

      

I've also included the Camera class for your convenience:

public class Camera
{
    private const float zoomUpperLimit = 1.5f;
    private const float zoomLowerLimit = 0.1f;

    private float _zoom;
    private Vector2 _pos;

    private int ViewportWidth, ViewportHeight;

    #region Properties

    public float Zoom
    {
        get { return _zoom; }
        set
        {
            _zoom = value;
            if (_zoom < zoomLowerLimit)
                _zoom = zoomLowerLimit;
            if (_zoom > zoomUpperLimit)
                _zoom = zoomUpperLimit;
        }
    }

    public Rectangle Viewport 
    {
        get
        {
            int width = (int)((ViewportWidth / _zoom));
            int height = (int)((ViewportHeight / _zoom));
            return new Rectangle((int)(_pos.X - width / 2), (int)(_pos.Y - height / 2), width, height);
        }
    }

    public void Move(Vector2 amount)
    {
        _pos += amount;
    }

    public Vector2 Position
    {
        get { return _pos; }
        set { _pos = value; }
    }

    public Matrix View
    {
        get
        {
            return Matrix.CreateTranslation(new Vector3(-_pos.X, -_pos.Y, 0)) *
                    Matrix.CreateScale(new Vector3(Zoom, Zoom, 1)) *
                    Matrix.CreateTranslation(new Vector3(ViewportWidth * 0.5f, ViewportHeight * 0.5f, 0));
        }
    }

    #endregion

    public Camera(Viewport viewport, float initialZoom)
    {
        _zoom = initialZoom;
        _pos = Vector2.Zero;
        ViewportWidth = viewport.Width;
        ViewportHeight = viewport.Height;
    }

}

      

+1


source







All Articles