3

在 XNA 上的另一个线程中,Callum Rogers 编写了一些代码来创建带有圆形轮廓的纹理,但我正在尝试创建一个充满颜色的圆形。我必须修改此代码以用颜色填充圆圈?

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

4 回答 4

4

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

只需使用三角扇画出类似于馅饼的圆圈。您将需要以下顶点。

  • 圆心
  • x 点在圆的边界上。

前两点将定义圆心与其边界之间的一条线。第三个顶点将定义第一个多边形。然后顶点 1、3 和 4 将定义第二个多边形,依此类推。

要获取圆圈边界上的点,请使用示例中的公式。第一个角度将是 0°,接下来是(360°/圆上的点)的倍数。要获得一个完整的圆圈,您需要一个与第二个点(边界上的第一个点)相匹配的附加点。

根据圆上的顶点数,您将得到不同的 n 边形。您使用的顶点越多,形状看起来就越圆(以一些性能成本为代价):

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

实际上,用于绘制 primites 的 XNA 示例展示了如何使用三角形扇形绘制圆形(或 n 边形)。

于 2011-04-13T00:31:35.500 回答
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;
于 2011-12-09T21:44:11.970 回答
1

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

于 2011-04-12T21:24:22.663 回答
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;
    }
于 2013-07-27T00:34:29.650 回答