XNA画一个圆圈

时间:2011-04-12 21:00:41

标签: c# math c#-4.0 xna xna-4.0

在XNA上的另一个主题中,Callum Rogers wrote some code创建一个带圆圈轮廓的纹理,但我正在尝试创建一个充满颜色的圆圈。我必须修改此代码以用颜色填充圆圈?

public Texture2D CreateCircle(int radius)
{
    int outerRadius = radius*2 + 2; // So circle doesn't go out of bounds
    Texture2D texture = new Texture2D(GraphicsDevice, outerRadius, outerRadius);

    Color[] data = new Color[outerRadius * outerRadius];

    // Colour the entire texture transparent first.
    for (int i = 0; i < data.Length; i++)
        data[i] = Color.Transparent;

    // Work out the minimum step necessary using trigonometry + sine approximation.
    double angleStep = 1f/radius;

    for (double angle = 0; angle < Math.PI*2; angle += angleStep)
    {
        // Use the parametric definition of a circle: http://en.wikipedia.org/wiki/Circle#Cartesian_coordinates
        int x = (int)Math.Round(radius + radius * Math.Cos(angle));
        int y = (int)Math.Round(radius + radius * Math.Sin(angle));

        data[y * outerRadius + x + 1] = Color.White;
    }

    texture.SetData(data);
    return texture;
}

4 个答案:

答案 0 :(得分:4)

不要为这样的东西使用纹理(特别是对于单一颜色的东西!) - 也不要尝试逐个像素地进行。你有3D加速的原因。

使用三角形扇形绘制类似于饼图的圆圈。你需要以下顶点。

  • 圈子中心
  • x指向圆圈的边框。

前两个点将定义圆心和边界之间的直线。第三个顶点将定义第一个多边形。然后,顶点1,3和4将定义第二个多边形等

要获取圆圈边框上的点,请使用示例中的公式。第一个角度为0°,以下为多个(圆圈上的360°/ )。要获得一个完整的圆,你需要一个与第二个点(边界上的第一个点)匹配的附加点。

根据圆上顶点的数量,您将获得不同的n-gons。你使用圆形的顶点越多,形状就越好(以某种性能成本):

  • (由于多边形需要至少绘制3个顶点,因此不可能有2个顶点。)
  • 总共4个点(圆圈上的3个点)将产生一个三角形。
  • 总共5个点(圆上4个点)将产生一个正方形。
  • 总共6分(圆圈上5分)将产生五角大楼
  • ...

实际上XNA example for drawing primites显示了如何使用三角扇绘制圆圈(或n-gon)。

答案 1 :(得分:4)

对于任何想要逐像素进行的人来说......我根据给出的信息制定了解决方案。在您的2D纹理方法中,添加以下代码以填充圆圈。我正在制作游戏,希望能够制作不同颜色和大小的圆圈。因此,在CreateCircle(int radius)方法中,在创建轮廓后添加以下代码:

        bool finished = false;
        int firstSkip = 0;
        int lastSkip = 0;
        for (int i = 0; i <= data.Length - 1; i++)
        {
            if (finished == false)
            {
                //T = transparent W = White;
                //Find the First Batch of Colors TTTTWWWTTTT The top of the circle
                if ((data[i] == Color.White) && (firstSkip == 0))
                {
                    while (data[i + 1] == Color.White)
                    {
                        i++;
                    }
                    firstSkip = 1;
                    i++;
                }
                //Now Start Filling                       TTTTTTTTWWTTTTTTTT
                //circle in Between                       TTTTTTW--->WTTTTTT
                //transaparent blancks                    TTTTTWW--->WWTTTTT
                //                                        TTTTTTW--->WTTTTTT
                //                                        TTTTTTTTWWTTTTTTTT
                if (firstSkip == 1)
                {
                    if (data[i] == Color.White && data[i + 1] != Color.White)
                    {
                        i++;
                        while (data[i] != Color.White)
                        {
                                //Loop to check if its the last row of pixels
                                //We need to check this because of the 
                                //int outerRadius = radius * 2 + -->'2'<--;
                                for (int j = 1; j <= outerRadius; j++)
                                {
                                    if (data[i + j] != Color.White)
                                    {
                                        lastSkip++;
                                    }
                                }
                                //If its the last line of pixels, end drawing
                                if (lastSkip == outerRadius)
                                {
                                    break;
                                    finished = true;
                                }
                                else
                                {
                                    data[i] = Color.White;
                                    i++;
                                    lastSkip = 0;
                                }
                            }
                        while (data[i] == Color.White)
                        {
                            i++;
                        }
                        i--;
                    }


                }
            }
        }
        // Set the data when finished 
        //-- don't need to paste this part, already given up above
        texture.SetData(data);
        return texture;

答案 2 :(得分:1)

如果您需要从头开始(尽管我猜测有更简单的方法),请更改执行渲染的方式。而不是迭代角度和绘制像素,迭代像素并确定它们相对于圆的位置。如果它们是<R,则绘制为填充颜色。如果它们是~= R,则绘制为边框颜色。

答案 3 :(得分:0)

我知道我有点迟了,但我修改了你的代码以填补中心

public static Texture2D CreateCircle(GraphicsDevice importedGraphicsDevice, int radius)
    {
        int outerRadius = radius * 2 + 2; // So circle doesn't go out of bounds
        Texture2D texture = new Texture2D(importedGraphicsDevice, outerRadius, outerRadius);

        Color[] data = new Color[outerRadius * outerRadius];

        // Colour the entire texture transparent first.
        for (int i = 0; i < data.Length; i++)
            data[i] = Color.Transparent;

        // Work out the minimum step necessary using trigonometry + sine approximation.
        double angleStep = 1f / radius;

        for (double angle = 0; angle < Math.PI * 2; angle += angleStep)
        {
            // Use the parametric definition of a circle: http://en.wikipedia.org/wiki/Circle#Cartesian_coordinates
            int x = (int)Math.Round(radius + radius * Math.Cos(angle));
            int y = (int)Math.Round(radius + radius * Math.Sin(angle));

            data[y * outerRadius + x + 1] = Color.White;
        }

                    //width
        for (int i = 0; i < outerRadius; i++)
        {
            int yStart = -1;
            int yEnd = -1;


            //loop through height to find start and end to fill
            for (int j = 0; j < outerRadius; j++)
            {

                if (yStart == -1)
                {
                    if (j == outerRadius - 1)
                    {
                        //last row so there is no row below to compare to
                        break;
                    }

                    //start is indicated by Color followed by Transparent
                    if (data[i + (j * outerRadius)] == Color.White && data[i + ((j + 1) * outerRadius)] == Color.Transparent)
                    {
                        yStart = j + 1;
                        continue;
                    }
                }
                else if (data[i + (j * outerRadius)] == Color.White)
                {
                    yEnd = j;
                    break;
                }
            }

            //if we found a valid start and end position
            if (yStart != -1 && yEnd != -1)
            {
                //height
                for (int j = yStart; j < yEnd; j++)
                {
                    data[i + (j * outerRadius)] = new Color(10, 10, 10, 10);
                }
            }
        }

        texture.SetData(data);
        return texture;
    }