How to draw lines using XNA?

I read a bunch of XNA tutorials (and these are different versions), and I'm still a bit confused about drawing primitives. Everything seems really confusing.

Can someone show me, using code, the simplest implementation of XNA to draw one or two lines on the screen? Perhaps with a brief explanation (including template)?

I am not a game programmer and I have little XNA experience. My ultimate goal is to draw some lines on the screen that I will eventually convert with rotations, etc. (Manually). However, for this first step. I just need to draw lines! I remember that in its ancient days, OpenGL was pretty simple when drawing a line with several method calls. Should I just revert to using unmanaged directx calls?

+43
primitive xna shapes drawing lines
Nov 06 '08 at 20:32
source share
10 answers

When working with XNA, everything (even 2d primitives) must be expressed in such a way that the 3d map can understand, which means that the string is just a collection of vertices.

MSDN has some nice step-by-step instructions:

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

You will find that rendering the primitive line requires more code than would be required to just tweak the textured square and rotate it, since essentially you are doing the same thing when rendering the line.

+19
Nov 06 '08 at 20:41
source share

After NoHayProblema's answer (I still can't comment).

This answer, although correct for this old question, is incomplete. The Texture2D constructor returns an uninitialized texture that is never drawn on the screen. To use this approach, you need to set the texture data as follows:

Texture2D SimpleTexture = new Texture2D(GraphicsDevice, 1, 1, false, SurfaceFormat.Color); Int32[] pixel = {0xFFFFFF}; // White. 0xFF is Red, 0xFF0000 is Blue SimpleTexture.SetData<Int32> (pixel, 0, SimpleTexture.Width * SimpleTexture.Height); // Paint a 100x1 line starting at 20, 50 this.spriteBatch.Draw(SimpleTexture, new Rectangle(20, 50, 100, 1), Color.Blue); 

Note that the way to write data to a pixel must match the texture of SurfaceFormat. The example works because the texture is formatted as RGB. Spins can be applied to spriteBatch.Draw as follows:

 this.spriteBatch.Draw (SimpleTexture, new Rectangle(0, 0, 100, 1), null, Color.Blue, -(float)Math.PI/4, new Vector2 (0f, 0f), SpriteEffects.None, 1f); 
+16
Jan 15 2018-11-11T00:
source share

Well, you can do it very simply without getting into 3D terrible vector material.

Just create a quick texture, for example:

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

And then just draw a line using this texture:

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

I hope this helps

+6
Sep 19 '10 at 14:53
source share

found a tutorial for this http://www.bit-101.com/blog/?p=2832

its use of BasicEffect (shader) and the built-in primitive user primitive in XNA 4.0

Some sample code that I find useful:

content loading method

 basicEffect = new BasicEffect(GraphicsDevice); basicEffect.VertexColorEnabled = true; basicEffect.Projection = Matrix.CreateOrthographicOffCenter (0, GraphicsDevice.Viewport.Width,    // left, right GraphicsDevice.Viewport.Height, 0,   // bottom, top 0, 1); 

drawing method

 basicEffect.CurrentTechnique.Passes[0].Apply(); var vertices = new VertexPositionColor[4]; vertices[0].Position = new Vector3(100, 100, 0); vertices[0].Color = Color.Black; vertices[1].Position = new Vector3(200, 100, 0); vertices[1].Color = Color.Red; vertices[2].Position = new Vector3(200, 200, 0); vertices[2].Color = Color.Black; vertices[3].Position = new Vector3(100, 200, 0); vertices[3].Color = Color.Red; GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.LineList, vertices, 0, 2); 

have fun and vote if it helps you. also have a look at the tutorial from which i got this.

+6
Nov 12
source share

The easiest way, I think, is to get an image with only a white pixel, and then stretch that pixel in a rectangle so that it looks like a line

I made the 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

+4
Nov 13 '13 at 15:32
source share

There is also a "round line" code that "mandrels" have released in CodePlex:


Here is a blog post about it:

+2
Jul 06 '09 at 3:00
source share

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

A class for storing some simple beam data. The default XNA beam class might work, but it does not preserve the beam length until intersection.

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

The list for storing the rays to draw:

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

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

Then run this in the drawing 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 occurs in my game, it does it (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 (maybe it looks harder than it is), and it would be easy to put it in a separate class that you never have to think about. It also allows you to draw multiple lines at once.

+1
Feb 23 '17 at 16:51
source share

Here is a simple way that I use to create lines by setting the starting coordinate, the coordinate of the end, the width and color of them:

NOTE: you must add a file named "dot" to the content directory (the string will be made from them).

 using System; using System.Collections.Generic; using System.Linq; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Audio; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.GamerServices; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Media; namespace Xna.LineHelper { public class LineManager { int loopCounter; int lineLegnth; Vector2 lineDirection; Vector2 _position; Color dotColor; Rectangle _rectangle; List<Texture2D> _dots = new List<Texture2D>(); FunctionsLibrary functions = new FunctionsLibrary(); public void CreateLineFiles(Vector2 startPosition, Vector2 endPosition, int width, Color color, ContentManager content) { dotColor = color; _position.X = startPosition.X; _position.Y = startPosition.Y; lineLegnth = functions.Distance((int)startPosition.X, (int)endPosition.X, (int)startPosition.Y, (int)endPosition.Y); lineDirection = new Vector2((endPosition.X - startPosition.X) / lineLegnth, (endPosition.Y - startPosition.Y) / lineLegnth); _dots.Clear(); loopCounter = 0; _rectangle = new Rectangle((int)startPosition.X, (int)startPosition.Y, width, width); while (loopCounter < lineLegnth) { Texture2D dot = content.Load<Texture2D>("dot"); _dots.Add(dot); loopCounter += 1; } } public void DrawLoadedLine(SpriteBatch sb) { foreach (Texture2D dot in _dots) { _position.X += lineDirection.X; _position.Y += lineDirection.Y; _rectangle.X = (int)_position.X; _rectangle.Y = (int)_position.Y; sb.Draw(dot, _rectangle, dotColor); } } } public class FunctionsLibrary { //Random for all methods Random Rand = new Random(); #region math public int TriangleArea1(int bottom, int height) { int answer = (bottom * height / 2); return answer; } public double TriangleArea2(int A, int B, int C) { int s = ((A + B + C) / 2); double answer = (Math.Sqrt(s * (s - A) * (s - B) * (s - C))); return answer; } public int RectangleArea(int side1, int side2) { int answer = (side1 * side2); return answer; } public int SquareArea(int side) { int answer = (side * side); return answer; } public double CircleArea(int diameter) { double answer = (((diameter / 2) * (diameter / 2)) * Math.PI); return answer; } public int Diference(int A, int B) { int distance = Math.Abs(A - B); return distance; } #endregion #region standardFunctions public int RollDice(int sides) { int result = (Rand.Next(1, sides + 1)); return result; } public void ConsoleWelcomeMessage(string gameName, string playerName = "\b") { Console.WriteLine("Welcome " + playerName + " to " + gameName + "!"); } public string ConsoleGetName() { Console.WriteLine(); Console.Write("Type your name: "); string name = Console.ReadLine(); Console.WriteLine("Your name will be: " + name); return name; } public int ConsoleGetDifficulty(int min, int max) { bool done = false; int difficulty = 1; Console.WriteLine(); Console.Write("Choose your difficulty from " + min + " to " + max + ": "); while (done == false) { try { string input = Console.ReadLine(); difficulty = int.Parse(input); if (difficulty < max + 1 && difficulty > min - 1) { done = true; } else { //Ends the try block with an impossible action (bool.Parse) bool tester = bool.Parse(input); } } catch { Console.Write("Enter a valid number: "); } } Console.WriteLine("Your difficulty will be: " + difficulty); return difficulty; } public int Distance(int x1, int x2, int y1, int y2) { return (int)(Math.Sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))); } public void Test() { } #endregion } } 
0
Dec 04 '13 at 6:29
source share

I ran into this problem and decided to create a LineBatch class. LineBatch will draw lines without the need for spriteBatch or dots. Class below.

 public class LineBatch { bool cares_about_begin_without_end; bool began; GraphicsDevice GraphicsDevice; List<VertexPositionColor> verticies = new List<VertexPositionColor>(); BasicEffect effect; public LineBatch(GraphicsDevice graphics) { GraphicsDevice = graphics; effect = new BasicEffect(GraphicsDevice); Matrix world = Matrix.Identity; Matrix view = Matrix.CreateTranslation(-GraphicsDevice.Viewport.Width / 2, -GraphicsDevice.Viewport.Height / 2, 0); Matrix projection = Matrix.CreateOrthographic(GraphicsDevice.Viewport.Width, -GraphicsDevice.Viewport.Height, -10, 10); effect.World = world; effect.View = view; effect.VertexColorEnabled = true; effect.Projection = projection; effect.DiffuseColor = Color.White.ToVector3(); cares_about_begin_without_end = true; } public LineBatch(GraphicsDevice graphics, bool cares_about_begin_without_end) { this.cares_about_begin_without_end = cares_about_begin_without_end; GraphicsDevice = graphics; effect = new BasicEffect(GraphicsDevice); Matrix world = Matrix.Identity; Matrix view = Matrix.CreateTranslation(-GraphicsDevice.Viewport.Width / 2, -GraphicsDevice.Viewport.Height / 2, 0); Matrix projection = Matrix.CreateOrthographic(GraphicsDevice.Viewport.Width, -GraphicsDevice.Viewport.Height, -10, 10); effect.World = world; effect.View = view; effect.VertexColorEnabled = true; effect.Projection = projection; effect.DiffuseColor = Color.White.ToVector3(); } public void DrawAngledLineWithRadians(Vector2 start, float length, float radians, Color color) { Vector2 offset = new Vector2( (float)Math.Sin(radians) * length, //x -(float)Math.Cos(radians) * length //y ); Draw(start, start + offset, color); } public void DrawOutLineOfRectangle(Rectangle rectangle, Color color) { Draw(new Vector2(rectangle.X, rectangle.Y), new Vector2(rectangle.X + rectangle.Width, rectangle.Y), color); Draw(new Vector2(rectangle.X, rectangle.Y), new Vector2(rectangle.X, rectangle.Y + rectangle.Height), color); Draw(new Vector2(rectangle.X + rectangle.Width, rectangle.Y), new Vector2(rectangle.X + rectangle.Width, rectangle.Y + rectangle.Height), color); Draw(new Vector2(rectangle.X, rectangle.Y + rectangle.Height), new Vector2(rectangle.X + rectangle.Width, rectangle.Y + rectangle.Height), color); } public void DrawOutLineOfTriangle(Vector2 point_1, Vector2 point_2, Vector2 point_3, Color color) { Draw(point_1, point_2, color); Draw(point_1, point_3, color); Draw(point_2, point_3, color); } float GetRadians(float angleDegrees) { return angleDegrees * ((float)Math.PI) / 180.0f; } public void DrawAngledLine(Vector2 start, float length, float angleDegrees, Color color) { DrawAngledLineWithRadians(start, length, GetRadians(angleDegrees), color); } public void Draw(Vector2 start, Vector2 end, Color color) { verticies.Add(new VertexPositionColor(new Vector3(start, 0f), color)); verticies.Add(new VertexPositionColor(new Vector3(end, 0f), color)); } public void Draw(Vector3 start, Vector3 end, Color color) { verticies.Add(new VertexPositionColor(start, color)); verticies.Add(new VertexPositionColor(end, color)); } public void End() { if (!began) if (cares_about_begin_without_end) throw new ArgumentException("Please add begin before end!"); else Begin(); if (verticies.Count > 0) { VertexBuffer vb = new VertexBuffer(GraphicsDevice, typeof(VertexPositionColor), verticies.Count, BufferUsage.WriteOnly); vb.SetData<VertexPositionColor>(verticies.ToArray()); GraphicsDevice.SetVertexBuffer(vb); foreach (EffectPass pass in effect.CurrentTechnique.Passes) { pass.Apply(); GraphicsDevice.DrawPrimitives(PrimitiveType.LineList, 0, verticies.Count / 2); } } began = false; } public void Begin() { if (began) if (cares_about_begin_without_end) throw new ArgumentException("You forgot end."); else End(); verticies.Clear(); began = true; } } 
0
Sep 19 '14 at 15:45
source share

Just stretch the 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(); } 
-one
Jun 08 '16 at 8:04 on
source share



All Articles