How do I draw lines using XNA?

后端 未结 10 1155
情书的邮戳
情书的邮戳 2020-12-05 04:19

I\'ve read a bunch of tutorials involving XNA (and it\'s various versions) and I still am a little confused on drawing primitives. Everything seems to be really convoluted.

相关标签:
10条回答
  • 2020-12-05 04:27

    When working with XNA, everything (even 2d primitives) have to be expressed in a way that a 3d card can understand, which means that a line is just a set of vertices.

    MSDN has a pretty good walkthrough here:

    http://msdn.microsoft.com/en-us/library/bb196414.aspx#ID2EEF

    You'll find that it takes more code to render a primitive line than it would take to just setup a textured quad and rotate that, since in essence, your doing the same thing when rendering a line.

    0 讨论(0)
  • 2020-12-05 04:29

    Just stretch a white pixel.

            point = game.Content.Load<Texture2D>("ui/point");
    
            public void DrawLine(Vector2 start, Vector2 end, Color color)
            {
                Vector2 edge = end - start;
                float angle = (float)Math.Atan2(edge.Y, edge.X);
    
                spriteBatch.Begin();
                spriteBatch.Draw(point,
                    new Rectangle((int)start.X, (int)start.Y, (int)edge.Length(), 1),
                    null, 
                    color, 
                    angle,
                    new Vector2(0, 0),
                    SpriteEffects.None,
                    0);
                spriteBatch.End();
            }
    
    0 讨论(0)
  • 2020-12-05 04:31

    The simplest best way, I think, is to get the image of just a white pixel then stretch that pixel in a rectangle to look like a line

    I made a Line class,

    class Line
    {
        Texture pixel = ((set this to a texture of a white pixel with no border));
        Vector2 p1, p2; //this will be the position in the center of the line
        int length, thickness; //length and thickness of the line, or width and height of rectangle
        Rectangle rect; //where the line will be drawn
        float rotation; // rotation of the line, with axis at the center of the line
        Color color;
    
    
        //p1 and p2 are the two end points of the line
        public Line(Vector2 p1, Vector2 p2, int thickness, Color color)
        {
            this.p1 = p1;
            this.p2 = p2;
            this.thickness = thickness;
            this.color = color;
        }
    
        public void Update(GameTime gameTime)
        {
            length = (int)Vector2.Distance(p1, p2); //gets distance between the points
            rotation = getRotation(p1.X, p1.Y, p2.X, p2.Y); //gets angle between points(method on bottom)
            rect = new Rectangle((int)p1.X, (int)p1.Y, length, thickness)
    
            //To change the line just change the positions of p1 and p2
        }
    
        public void Draw(SpriteBatch spriteBatch, GameTime gameTime)
        {
            spriteBatch.Draw(pixel, rect, null, color, rotation, new Vector2.Zero, SpriteEffects.None, 0.0f);
        }
    
        //this returns the angle between two points in radians 
        private float getRotation(float x, float y, float x2, float y2)
        {
            float adj = x - x2;
            float opp = y - y2;
            float tan = opp / adj;
            float res = MathHelper.ToDegrees((float)Math.Atan2(opp, adj));
            res = (res - 180) % 360;
            if (res < 0) { res += 360; }
            res = MathHelper.ToRadians(res);
            return res;
        }
    

    Hope this helps

    0 讨论(0)
  • 2020-12-05 04:33

    There is also the "round line" code that "manders" has released on CodePlex:

    • http://roundline.codeplex.com/


    Here is the blog post about it:

    • XNA RoundLine Code Released on CodePlex
    0 讨论(0)
  • 2020-12-05 04:34

    Well, you can do it in a very simple way without getting into the 3D horrible vector stuff.

    Just create a quick texture, for example:

    Texture2D SimpleTexture = new Texture2D(GraphicsDevice, 1, 1, false, SurfaceFormat.Color);

    And then just draw a line using that texture:

    this.spriteBatch.Draw(SimpleTexture, new Rectangle(100, 100, 100, 1), Color.Blue);

    I hope this helps

    0 讨论(0)
  • 2020-12-05 04:34

    I wanted to draw rays so that I could debug rays created by explosions and where they intersect objects. This will draw a single pixel thin line between two points. This is what I did:

    Class to store some simple ray data. The XNA default ray class could work, but it doesn't store the length of the ray to intersection.

    public class myRay
    {
        public Vector3 position, direction;
        public float length;
    }   
    

    A list to store the rays that are to be drawn:

    List<myRay> DebugRays= new List<myRay>();
    

    Create a BasicEffect and pass it a "Matrix.CreateOrthographicOffCenter" projection with your desired resolution in the LoadContent method.

    Then run this in the draw method:

    private void DrawRays()
    {
        spriteBatch.Begin();
    
        foreach (myRay ray in DebugRays)
            {
                //An array of 2 vertices - a start and end position
                VertexPositionColor[] Vertices = new VertexPositionColor[2];
                int[] Indices = new int[2];
    
                //Starting position of the ray
                Vertices[0] = new VertexPositionColor()
                {
                    Color = Color.Orange,
                    Position = ray.position
                };
    
                //End point of the ray
                Vertices[1] = new VertexPositionColor()
                {
                    Color = Color.Orange,
                    Position = ray.position + (ray.direction * ray.length)
                };
    
                Indices[0] = 0;
                Indices[1] = 1;
    
                foreach (EffectPass pass in BasicEffect.CurrentTechnique.Passes)
                {
                    pass.Apply();
                    GraphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.LineStrip, Vertices, 0, 2, Indices, 0, 1, VertexPositionColorTexture.VertexDeclaration);
                }
            }
    
        spriteBatch.End();
    }
    

    So when an explosion happens in my game it does this (Psuedocode):

    OnExplosionHappened()
    {
        DebugRays.Clear()
    
        myRay ray = new myRay()
                        {
                            position = explosion.Position,
                            direction = GetDirection(explosion, solid),
                            //Used GetValueOrDefault here to prevent null value errors
                            length = explosionRay.Intersects(solid.BoundingBox).GetValueOrDefault()
                        };
    
        DebugRays.Add(ray);
    }
    

    It's pretty simple (It possibly looks way more complicated than it is) and it'd be easy to put it into a separate class that you never have to think about again. It also lets you draw a whole lot of lines at once.

    0 讨论(0)
提交回复
热议问题