Page 1 of 1

C# XNA - 2d Primitives (pixel, line, rectangle, etc.)

#1 Lurler  Icon User is offline

  • New D.I.C Head
  • member icon

Reputation: 3
  • View blog
  • Posts: 29
  • Joined: 30-May 11

Posted 02 June 2011 - 04:27 AM

My native language isn't english but I hope you can undertand me :)

Okay, lets start.

I was very surprised that XNA doesn't come with 2d primitives library, you can't draw lines, rectangles and other simple objects, you can only draw sprites, which is a bit odd...

Anyway, I searched the net but couldn't find any library that could replace it. Also there wasn't any general solution to it also.

So... I decided to write my own library :)

Here it is. Just look at it for now, then I explain everthing.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace QWE
{
    class Primitives2d
    {
        Texture2D pixel; //our pixel texture we will be using to draw primitives
        GraphicsDevice gd; //graphics device to use
        SpriteBatch sb; //sprite batch to use

        public Primitives2d(GraphicsDevice graphicsDevice, SpriteBatch spriteBatch)
        {
            //saving GD for use in drawing funtions
            this.gd = graphicsDevice;
            this.sb = spriteBatch;
            //creating our simple pixel
            pixel = new Texture2D(gd, 1, 1);
            pixel.SetData(new Color[] { Color.White });
        }

        //draws a pixel
        public void DrawPixel(int x, int y , Color col)
        {
            sb.Draw(pixel, new Vector2(x,y), col);
        }

        //draws a line obviously :)/>
        public void DrawLine(int x1, int y1, int x2, int y2, Color col)
        {
            int deltax, deltay, x, y, xinc1, xinc2, yinc1, yinc2, den, num, numadd, numpixels, curpixel;

            deltax = Math.Abs(x2 - x1);        // The difference between the x's
            deltay = Math.Abs(y2 - y1);        // The difference between the y's
            x = x1;                       // Start x off at the first pixel
            y = y1;                       // Start y off at the first pixel

            if (x2 >= x1)                 // The x-values are increasing
            {
                xinc1 = 1;
                xinc2 = 1;
            }
            else                          // The x-values are decreasing
            {
                xinc1 = -1;
                xinc2 = -1;
            }

            if (y2 >= y1)                 // The y-values are increasing
            {
                yinc1 = 1;
                yinc2 = 1;
            }
            else                          // The y-values are decreasing
            {
                yinc1 = -1;
                yinc2 = -1;
            }

            if (deltax >= deltay)         // There is at least one x-value for every y-value
            {
                xinc1 = 0;                  // Don't change the x when numerator >= denominator
                yinc2 = 0;                  // Don't change the y for every iteration
                den = deltax;
                num = deltax / 2;
                numadd = deltay;
                numpixels = deltax;         // There are more x-values than y-values
            }
            else                          // There is at least one y-value for every x-value
            {
                xinc2 = 0;                  // Don't change the x for every iteration
                yinc1 = 0;                  // Don't change the y when numerator >= denominator
                den = deltay;
                num = deltay / 2;
                numadd = deltax;
                numpixels = deltay;         // There are more y-values than x-values
            }

            for (curpixel = 0; curpixel <= numpixels; curpixel++)
            {
                DrawPixel(x,y,col);
                num += numadd;              // Increase the numerator by the top of the fraction
                if (num >= den)             // Check if numerator >= denominator
                {
                    num -= den;               // Calculate the new numerator value
                    x += xinc1;               // Change the x as appropriate
                    y += yinc1;               // Change the y as appropriate
                }
                x += xinc2;                 // Change the x as appropriate
                y += yinc2;                 // Change the y as appropriate
            }
        }

        public void DrawRectangle(Rectangle rect, Color col, Boolean filled)
        {
            if (filled)
            {
                sb.Draw(pixel, rect, col);
            }
            else
            {
                DrawLine(rect.X, rect.Y, rect.X + rect.Width, rect.Y,col);
                DrawLine(rect.X, rect.Y, rect.X, rect.Y + rect.Height,col);
                DrawLine(rect.X + rect.Width, rect.Y, rect.X + rect.Width, rect.Y + rect.Height, col);
                DrawLine(rect.X, rect.Y + rect.Height, rect.X + rect.Width, rect.Y + rect.Height, col);
            }
        }

    }
}



Okay. What I do.

First I create texture/sprite in memory with only one pixel and white color. We will be using this sprite to draw all of our primitives manually, pixel by pixel.

First function is drawing a pixel itself. It's pretty straightforward.
DrawLine is drawing the line using previous DrawPisel function and this algorithm http://en.wikipedia...._line_algorithm
Draw Rectangle is also similar to previous function.

This realisation is quite slow, drawind just 500 lines with length about 400 will drop fps to 12/sec.
Still I think it's enought for vector games or other purposes.

You can implement drawing circle and other premitives using the same principle.

Ah, and how you call these functions:

spriteBatch.Begin();

primitives2d.DrawPixel(25, 25, new Color(255,255,255));

Random rnd = new Random();
for(int i = 0; i<5; i++) {
    primitives2d.DrawLine(rnd.Next(0,800), rnd.Next(0,800), rnd.Next(0,800), rnd.Next(0,800), new Color(255, 255, 255));
}

primitives2d.DrawRectangle(new Rectangle(100, 100, 500, 500), new Color(0, 32, 0, 128), true);

primitives2d.DrawRectangle(new Rectangle(100, 100, 500, 200), new Color(255, 0, 0), false);

spriteBatch.End();



Is This A Good Question/Topic? 0
  • +

Page 1 of 1